cedric's eet and edje patches to use eet dictionaries for strings.
authorraster <raster>
Sat, 1 Mar 2008 06:38:09 +0000 (06:38 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 1 Mar 2008 06:38:09 +0000 (06:38 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/libs/eet@33873 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Eet.h
src/lib/Eet_private.h
src/lib/Makefile.am
src/lib/eet_data.c
src/lib/eet_image.c
src/lib/eet_lib.c
src/lib/eet_memfile.c

index fd28b81..bdc842a 100644 (file)
@@ -38,19 +38,20 @@ extern "C" {
 
 /***************************************************************************/
 
-#define EET_T_UNKNOW     0 /**< Unknown data encoding type */
-#define EET_T_CHAR       1 /**< Data type: char */
-#define EET_T_SHORT      2 /**< Data type: short */
-#define EET_T_INT        3 /**< Data type: int */
-#define EET_T_LONG_LONG  4 /**< Data type: long long */
-#define EET_T_FLOAT      5 /**< Data type: float */
-#define EET_T_DOUBLE     6 /**< Data type: double */
-#define EET_T_UCHAR      7 /**< Data type: unsigned char */
-#define EET_T_USHORT     8 /**< Data type: unsigned short */
-#define EET_T_UINT       9 /**< Data type: unsigned int */
-#define EET_T_ULONG_LONG 10 /**< Data type: unsigned long long */
-#define EET_T_STRING     11 /**< Data type: char * */
-#define EET_T_LAST       12 /**< Last data type */
+#define EET_T_UNKNOW            0 /**< Unknown data encoding type */
+#define EET_T_CHAR              1 /**< Data type: char */
+#define EET_T_SHORT             2 /**< Data type: short */
+#define EET_T_INT               3 /**< Data type: int */
+#define EET_T_LONG_LONG         4 /**< Data type: long long */
+#define EET_T_FLOAT             5 /**< Data type: float */
+#define EET_T_DOUBLE            6 /**< Data type: double */
+#define EET_T_UCHAR             7 /**< Data type: unsigned char */
+#define EET_T_USHORT            8 /**< Data type: unsigned short */
+#define EET_T_UINT              9 /**< Data type: unsigned int */
+#define EET_T_ULONG_LONG        10 /**< Data type: unsigned long long */
+#define EET_T_STRING            11 /**< Data type: char * */
+#define EET_T_INLINED_STRING    12 /**< Data type: char * (but compressed inside the resulting eet) */
+#define EET_T_LAST              13 /**< Last data type */
 
 #define EET_G_UNKNOWN    100 /**< Unknown group data encoding type */
 #define EET_G_ARRAY      101 /**< Fixed size array group type */
@@ -84,11 +85,12 @@ extern "C" {
      } Eet_Error;
 
    typedef struct _Eet_File                  Eet_File;
+   typedef struct _Eet_Dictionary            Eet_Dictionary;
    typedef struct _Eet_Data_Descriptor       Eet_Data_Descriptor;
 
    typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class;
 
-#define EET_DATA_DESCRIPTOR_CLASS_VERSION 1
+#define EET_DATA_DESCRIPTOR_CLASS_VERSION 2
    struct _Eet_Data_Descriptor_Class
      {
        int         version;
@@ -97,7 +99,7 @@ extern "C" {
        struct {
           void   *(*mem_alloc) (size_t size);
           void    (*mem_free) (void *mem);
-          char   *(*str_alloc) (const char *str);
+           char   *(*str_alloc) (const char *str);
           void    (*str_free) (const char *str);
           void   *(*list_next) (void *l);
           void   *(*list_append) (void *l, void *d);
@@ -106,6 +108,8 @@ extern "C" {
           void    (*hash_foreach) (void *h, int (*func) (void *h, const char *k, void *dt, void *fdt), void *fdt);
           void   *(*hash_add) (void *h, const char *k, void *d);
           void    (*hash_free) (void *h);
+           char   *(*str_direct_alloc) (const char *str);
+           void    (*str_direct_free) (const char *str);
        } func;
      };
 
@@ -216,6 +220,9 @@ extern "C" {
     */
    EAPI Eet_Error eet_close(Eet_File *ef);
 
+   /* FIXME: Add some documentation */
+   EAPI Eet_Dictionary* eet_dictionary_get(Eet_File *ef);
+
    /**
     * Read a specified entry from an eet file and return data
     * @param ef A valid eet file handle opened for reading.
@@ -667,12 +674,6 @@ extern "C" {
     *    blah.blah3 = evas_list_append(blah.blah3, &blah3);
     *
     *    data = eet_data_descriptor_encode(edd, &blah, &size);
-    *    f = fopen("out", "w");
-    *    if (f)
-    *      {
-    *         fwrite(data, size, 1, f);
-    *         fclose(f);
-    *      }
     *    printf("-----DECODING\n");
     *    blah_in = eet_data_descriptor_decode(edd, data, size);
     *
@@ -716,6 +717,7 @@ extern "C" {
     * move happens - but be warned
     */
    EAPI Eet_Data_Descriptor *eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc);
+   EAPI Eet_Data_Descriptor *eet_data_descriptor3_new(Eet_Data_Descriptor_Class *eddc);
 
    /**
     * This function frees a data descriptor when it is not needed anymore.
index 044ba83..37b4dc1 100644 (file)
@@ -51,6 +51,51 @@ void *alloca (size_t);
 # endif
 #endif
 
+typedef struct _Eet_String              Eet_String;
+
+struct _Eet_String
+{
+  const char            *mmap;
+  char                  *str;
+
+  struct
+  {
+    unsigned int         converted : 1;
+    unsigned int         is_float : 1;
+  } flags;
+  union
+  {
+    float                f;
+    double               d;
+  } convert;
+
+  int                    hash;
+  int                    len;
+
+  int                    next;
+  int                    prev;
+};
+struct _Eet_Dictionary
+{
+  Eet_String   *all;
+
+  int           size;
+  int           offset;
+
+  int           hash[256];
+
+  int           count;
+  int           total;
+};
+
+Eet_Dictionary  *eet_dictionary_add(void);
+void             eet_dictionary_free(Eet_Dictionary *ed);
+int              eet_dictionary_string_add(Eet_Dictionary *ed, const char *string);
+int              eet_dictionary_string_get_size(const Eet_Dictionary *ed, int index);
+const char      *eet_dictionary_string_get_char(const Eet_Dictionary *ed, int index);
+int              eet_dictionary_string_get_float(const Eet_Dictionary *ed, int index, float *result);
+int              eet_dictionary_string_get_double(const Eet_Dictionary *ed, int index, double *result);
+
 FILE *_eet_memfile_read_open(const void *data, size_t size);
 void  _eet_memfile_read_close(FILE *f);
 FILE *_eet_memfile_write_open(void **data, size_t *size);
index 0a98bce..fc72819 100644 (file)
@@ -15,6 +15,7 @@ eet_lib.c \
 eet_data.c \
 eet_image.c \
 eet_memfile.c \
+eet_dictionary.c \
 eet_utils.c \
 Eet_private.h
 
index 8f2fbe6..8a12e2b 100644 (file)
@@ -1,7 +1,7 @@
 #include <math.h>
 
-#include "Eet_private.h"
 #include "Eet.h"
+#include "Eet_private.h"
 
 /*
  * routines for doing data -> struct and struct -> data conversion
@@ -55,13 +55,14 @@ typedef struct _Eet_Data_Encode_Hash_Info   Eet_Data_Encode_Hash_Info;
 struct _Eet_Data_Basic_Type_Decoder
 {
    int     size;
-   int   (*get) (const void *src, const void *src_end, void *dest);
-   void *(*put) (const void *src, int *size_ret);
+   int   (*get) (const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+   void *(*put) (Eet_Dictionary *ed, const void *src, int *size_ret);
 };
 
 struct _Eet_Data_Chunk
 {
    char          *name;
+   int            len;
    int            size;
    void          *data;
    unsigned char  type;
@@ -83,13 +84,15 @@ struct _Eet_Data_Descriptor_Hash
 
 struct _Eet_Data_Descriptor
 {
-   const char *name;
-   int   size;
+   const char           *name;
+   int                   size;
    struct {
       void *(*mem_alloc) (size_t size);
       void  (*mem_free) (void *mem);
       char *(*str_alloc) (const char *str);
+      char *(*str_direct_alloc) (const char *str);
       void  (*str_free) (const char *str);
+      void  (*str_direct_free) (const char *str);
       void *(*list_next) (void *l);
       void *(*list_append) (void *l, void *d);
       void *(*list_data) (void *l);
@@ -99,11 +102,11 @@ struct _Eet_Data_Descriptor
       void  (*hash_free) (void *h);
    } func;
    struct {
-      int               num;
-      Eet_Data_Element *set;
+      int                num;
+      Eet_Data_Element  *set;
       struct {
-        int                       size;
-        Eet_Data_Descriptor_Hash *buckets;
+        int                             size;
+        Eet_Data_Descriptor_Hash       *buckets;
       } hash;
    } elements;
 //   char *strings;
@@ -123,31 +126,34 @@ struct _Eet_Data_Element
 
 struct _Eet_Data_Encode_Hash_Info
 {
-   Eet_Data_Stream  *ds;
-   Eet_Data_Element *ede;
+  Eet_Data_Stream       *ds;
+  Eet_Data_Element      *ede;
+  Eet_Dictionary        *ed;
 };
 
 /*---*/
 
-static int   eet_data_get_char(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_char(const void *src, int *size_ret);
-static int   eet_data_get_short(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_short(const void *src, int *size_ret);
-static int   eet_data_get_int(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_int(const void *src, int *size_ret);
-static int   eet_data_get_long_long(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_long_long(const void *src, int *size_ret);
-static int   eet_data_get_float(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_float(const void *src, int *size_ret);
-static int   eet_data_get_double(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_double(const void *src, int *size_ret);
-static int   eet_data_get_string(const void *src, const void *src_end, void *dest);
-static void *eet_data_put_string(const void *src, int *size_ret);
-
-static int   eet_data_get_type(int type, const void *src, const void *src_end, void *dest);
-static void *eet_data_put_type(int type, const void *src, int *size_ret);
-
-static void            eet_data_chunk_get(Eet_Data_Chunk *chnk, const void *src, int size);
+static int   eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_char(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_short(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_short(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_int(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_int(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_long_long(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_long_long(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret);
+static int   eet_data_get_istring(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_istring(Eet_Dictionary *ed, const void *src, int *size_ret);
+
+static int   eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest);
+static void *eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret);
+
+static void            eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size);
 static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, const char *name, int type, int group_type);
 static void            eet_data_chunk_free(Eet_Data_Chunk *chnk);
 
@@ -155,9 +161,17 @@ static Eet_Data_Stream *eet_data_stream_new(void);
 static void             eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size);
 static void             eet_data_stream_free(Eet_Data_Stream *ds);
 
-static void             eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
+static void             eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds);
 
-static int  eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata);
+static int       eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata);
+static void     *_eet_data_descriptor_encode(Eet_Dictionary *ed, Eet_Data_Descriptor *edd, const void *data_in, int *size_ret);
+static void     *_eet_data_descriptor_decode(const Eet_Dictionary *ed,
+                                             Eet_Data_Descriptor *edd,
+                                             const void *data_in,
+                                             int size_in,
+                                             int level,
+                                             void (*dumpfunc) (void *data, const char *str),
+                                             void *dumpdata);
 
 /*---*/
 
@@ -173,7 +187,8 @@ const Eet_Data_Basic_Type_Decoder eet_coder[] =
      {sizeof(short),     eet_data_get_short,     eet_data_put_short    },
      {sizeof(int),       eet_data_get_int,       eet_data_put_int      },
      {sizeof(long long), eet_data_get_long_long, eet_data_put_long_long},
-     {sizeof(char *),    eet_data_get_string,    eet_data_put_string   }
+     {sizeof(char *),    eet_data_get_string,    eet_data_put_string   },
+     {sizeof(char *),    eet_data_get_istring,   eet_data_put_istring  }
 };
 
 static int words_bigendian = -1;
@@ -203,11 +218,13 @@ static int words_bigendian = -1;
 #define CONV32(x) {if (words_bigendian) SWAP32(x);}
 #define CONV64(x) {if (words_bigendian) SWAP64(x);}
 
+#define IS_SIMPLE_TYPE(Type)    (Type > EET_T_UNKNOW && Type < EET_T_LAST)
+
 /*---*/
 
 /* CHAR TYPE */
 static int
-eet_data_get_char(const void *src, const void *src_end, void *dst)
+eet_data_get_char(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
    char *s, *d;
 
@@ -220,7 +237,7 @@ eet_data_get_char(const void *src, const void *src_end, void *dst)
 }
 
 static void *
-eet_data_put_char(const void *src, int *size_ret)
+eet_data_put_char(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
    char *s, *d;
 
@@ -235,7 +252,7 @@ eet_data_put_char(const void *src, int *size_ret)
 
 /* SHORT TYPE */
 static int
-eet_data_get_short(const void *src, const void *src_end, void *dst)
+eet_data_get_short(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
    short *d;
 
@@ -247,7 +264,7 @@ eet_data_get_short(const void *src, const void *src_end, void *dst)
 }
 
 static void *
-eet_data_put_short(const void *src, int *size_ret)
+eet_data_put_short(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
    short *s, *d;
 
@@ -262,7 +279,7 @@ eet_data_put_short(const void *src, int *size_ret)
 
 /* INT TYPE */
 static int
-eet_data_get_int(const void *src, const void *src_end, void *dst)
+eet_data_get_int(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
    int *d;
 
@@ -274,7 +291,7 @@ eet_data_get_int(const void *src, const void *src_end, void *dst)
 }
 
 static void *
-eet_data_put_int(const void *src, int *size_ret)
+eet_data_put_int(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
    int *s, *d;
 
@@ -289,7 +306,7 @@ eet_data_put_int(const void *src, int *size_ret)
 
 /* LONG LONG TYPE */
 static int
-eet_data_get_long_long(const void *src, const void *src_end, void *dst)
+eet_data_get_long_long(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
    unsigned long long *d;
 
@@ -301,7 +318,7 @@ eet_data_get_long_long(const void *src, const void *src_end, void *dst)
 }
 
 static void *
-eet_data_put_long_long(const void *src, int *size_ret)
+eet_data_put_long_long(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
    unsigned long long *s, *d;
 
@@ -316,34 +333,57 @@ eet_data_put_long_long(const void *src, int *size_ret)
 
 /* STRING TYPE */
 static int
-eet_data_get_string(const void *src, const void *src_end, void *dst)
+eet_data_get_string(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
-   char *s, **d, *p;
-   int len;
+   char *s, **d;
 
-   s = (char *)src;
    d = (char **)dst;
-   p = s;
-   len = 0;
-   while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
-   if (len == 0)
+
+   if (ed)
+     {
+        const char       *str;
+        int               index;
+
+        if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
+
+        str = eet_dictionary_string_get_char(ed, index);
+        if (str == NULL)
+          return -1;
+
+        *d = (char *) str;
+        return eet_dictionary_string_get_size(ed, index);
+     }
+
+   s = (char *)src;
+   if (s == NULL)
      {
-       *d = NULL;
-       return 0;
+        *d = NULL;
+        return 0;
      }
-   *d = malloc(len + 1);
-   if (!(*d)) return -1;
-   memcpy(*d, s, len);
-   (*d)[len] = 0;
-   return len + 1;
+
+   *d = s;
+   return strlen(s) + 1;
 }
 
 static void *
-eet_data_put_string(const void *src, int *size_ret)
+eet_data_put_string(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
    char *s, *d;
    int len;
-   /* const char *empty_s = ""; */
+
+   if (ed)
+     {
+        const char      *str;
+        int              index;
+
+        str = *((const char **) src);
+        if (!str) return NULL;
+
+        index = eet_dictionary_string_add(ed, str);
+        if (index == -1) return NULL;
+
+        return eet_data_put_int(ed, &index, size_ret);
+     }
 
    s = (char *)(*((char **)src));
    if (!s) return NULL;
@@ -355,6 +395,19 @@ eet_data_put_string(const void *src, int *size_ret)
    return d;
 }
 
+/* ALWAYS INLINED STRING TYPE */
+static int
+eet_data_get_istring(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
+{
+   return eet_data_get_string(NULL, src, src_end, dst);
+}
+
+static void *
+eet_data_put_istring(Eet_Dictionary *ed, const void *src, int *size_ret)
+{
+   return eet_data_put_string(NULL, src, size_ret);
+}
+
 /**
  * Fast lookups of simple doubles/floats.
  *
@@ -362,7 +415,7 @@ eet_data_put_string(const void *src, int *size_ret)
  * values, but have a so simple math that is almost as fast.
  */
 static inline int
-_eet_data_float_cache_get(char *s, int len, float *d)
+_eet_data_float_cache_get(const char *s, int len, float *d)
 {
    /* fast handle of simple case 0xMp+E*/
    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
@@ -379,7 +432,7 @@ _eet_data_float_cache_get(char *s, int len, float *d)
 }
 
 static inline int
-_eet_data_double_cache_get(char *s, int len, double *d)
+_eet_data_double_cache_get(const char *s, int len, double *d)
 {
    /* fast handle of simple case 0xMp+E*/
    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
@@ -397,109 +450,145 @@ _eet_data_double_cache_get(char *s, int len, double *d)
 
 /* FLOAT TYPE */
 static int
-eet_data_get_float(const void *src, const void *src_end, void *dst)
+eet_data_get_float(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
-   float *d;
-   long long mantisse;
-   long      exponent;
-   char *s, *str, *p;
-   int len;
+   float        *d;
+   int           index;
 
-   s = (char *)src;
-   d = (float *)dst;
-   p = s;
-   len = 0;
-   while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
+   d = (float *) dst;
+   if (!ed)
+     {
+        const char   *s, *p;
+        long long     mantisse;
+        long          exponent;
+        int           len;
 
-   if (_eet_data_float_cache_get(s, len, d) != 0) return len + 1;
+        s = (const char *)src;
+        p = s;
+        len = 0;
+        while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
 
-   str = alloca(len + 1);
-   memcpy(str, s, len);
-   str[len] = '\0';
+        if (_eet_data_float_cache_get(s, len, d) != 0) return len + 1;
 
-   _eet_string_to_double_convert(str, &mantisse, &exponent);
-   *d = (float)ldexp((double)mantisse, exponent);
-   
-   return len + 1;
+        _eet_string_to_double_convert(s, &mantisse, &exponent);
+        *d = (float)ldexp((double)mantisse, exponent);
+
+        return len + 1;
+     }
+
+   if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
+
+   if (!eet_dictionary_string_get_float(ed, index, d))
+     return -1;
+   return 1;
 }
 
 static void *
-eet_data_put_float(const void *src, int *size_ret)
+eet_data_put_float(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
-   char   buf[64];
-   char  *d;
-   int    len;
+   char  buf[64];
+   int   index;
 
    _eet_double_to_string_convert(buf, (double)(*(float *)src));
-   len = strlen(buf);
-   d = malloc(len + 1);
-   if (!d) return NULL;
-   strcpy(d, buf);
-   *size_ret = len + 1;
 
-   return d;
+   if (!ed)
+     {
+        char    *d;
+        int      len;
+
+        len = strlen(buf);
+        d = malloc(len + 1);
+        if (!d) return NULL;
+        strcpy(d, buf);
+        *size_ret = len + 1;
+        return d;
+     }
+
+   index = eet_dictionary_string_add(ed, buf);
+   if (index == -1) return NULL;
+
+   return eet_data_put_int(ed, &index, size_ret);
 }
 
 /* DOUBLE TYPE */
 static int
-eet_data_get_double(const void *src, const void *src_end, void *dst)
+eet_data_get_double(const Eet_Dictionary *ed, const void *src, const void *src_end, void *dst)
 {
-   double   *d;
-   long long mantisse = 0;
-   long      exponent = 0;
-   char *s, *str, *p;
-   int len;
+   double       *d;
+   int           index;
 
-   s = (char *)src;
-   d = (double *)dst;
-   p = s;
-   len = 0;
-   while ((p < (char *)src_end) && (*p != 0)) {len++; p++;}
+   d = (double *) dst;
 
-   if (_eet_data_double_cache_get(s, len, d) != 0) return len + 1;
+   if (!ed)
+     {
+        const char     *s, *p;
+        long long       mantisse = 0;
+        long            exponent = 0;
+        int             len;
+
+        s = (const char *) src;
+        p = s;
+        len = 0;
+        while ((p < (const char *)src_end) && (*p != 0)) {len++; p++;}
+
+        if (_eet_data_double_cache_get(s, len, d) != 0) return len + 1;
 
-   str = alloca(len + 1);
-   memcpy(str, s, len);
-   str[len] = '\0';
+        _eet_string_to_double_convert(s, &mantisse, &exponent);
+        *d = ldexp((double) mantisse, exponent);
 
-   _eet_string_to_double_convert(str, &mantisse, &exponent);
-   *d = ldexp((double)mantisse, exponent);
+        return len + 1;
+     }
+
+   if (eet_data_get_int(ed, src, src_end, &index) < 0) return -1;
 
-   return len + 1;
+   if (!eet_dictionary_string_get_double(ed, index, d))
+     return -1;
+   return 1;
 }
 
 static void *
-eet_data_put_double(const void *src, int *size_ret)
+eet_data_put_double(Eet_Dictionary *ed, const void *src, int *size_ret)
 {
-   char    buf[128];
-   char   *d;
-   int     len;
+   char  buf[128];
+   int   index;
 
    _eet_double_to_string_convert(buf, (double)(*(double *)src));
-   len = strlen(buf);
-   d = malloc(len + 1);
-   if (!d) return NULL;
-   strcpy(d, buf);
-   *size_ret = len + 1;
 
-   return d;
+   if (!ed)
+     {
+        char   *d;
+        int     len;
+
+        len = strlen(buf);
+        d = malloc(len + 1);
+        if (!d) return NULL;
+        strcpy(d, buf);
+        *size_ret = len + 1;
+
+        return d;
+     }
+
+   index = eet_dictionary_string_add(ed, buf);
+   if (index == -1) return NULL;
+
+   return eet_data_put_int(ed, &index, size_ret);
 }
 
 static int
-eet_data_get_type(int type, const void *src, const void *src_end, void *dest)
+eet_data_get_type(const Eet_Dictionary *ed, int type, const void *src, const void *src_end, void *dest)
 {
    int ret;
 
-   ret = eet_coder[type - 1].get(src, src_end, dest);
+   ret = eet_coder[type - 1].get(ed, src, src_end, dest);
    return ret;
 }
 
 static void *
-eet_data_put_type(int type, const void *src, int *size_ret)
+eet_data_put_type(Eet_Dictionary *ed, int type, const void *src, int *size_ret)
 {
    void *ret;
 
-   ret = eet_coder[type - 1].put(src, size_ret);
+   ret = eet_coder[type - 1].put(ed, src, size_ret);
    return ret;
 }
 
@@ -517,7 +606,7 @@ eet_data_put_type(int type, const void *src, int *size_ret)
  */
 
 static void
-eet_data_chunk_get(Eet_Data_Chunk *chnk, const void *src, int size)
+eet_data_chunk_get(const Eet_Dictionary *ed, Eet_Data_Chunk *chnk, const void *src, int size)
 {
    const char *s;
    int ret1, ret2;
@@ -556,7 +645,7 @@ eet_data_chunk_get(Eet_Data_Chunk *chnk, const void *src, int size)
             return;
          }
      }
-   ret1 = eet_data_get_type(EET_T_INT, (s + 4), (s + size), &(chnk->size));
+   ret1 = eet_data_get_type(ed, EET_T_INT, (s + 4), (s + size), &(chnk->size));
    if (ret1 <= 0)
      {
        return;
@@ -565,13 +654,24 @@ eet_data_chunk_get(Eet_Data_Chunk *chnk, const void *src, int size)
      {
        return;
      }
-   ret2 = eet_data_get_type(EET_T_STRING, (s + 8), (s + size), &(chnk->name));
+   ret2 = eet_data_get_type(ed, EET_T_STRING, (s + 8), (s + size), &(chnk->name));
    if (ret2 <= 0)
      {
        return;
      }
-   chnk->data = (char *)src + 4 + ret1 + ret2;
-   chnk->size -= ret2;
+
+   chnk->len = ret2;
+   if (ed)
+     {
+        chnk->data = (char *)src + 4 + ret1 + sizeof(int);
+        chnk->size -= sizeof(int);
+     }
+   else
+     {
+        chnk->data = (char *)src + 4 + ret1 + chnk->len;
+        chnk->size -= chnk->len;
+     }
+
    return;
 }
 
@@ -585,6 +685,7 @@ eet_data_chunk_new(void *data, int size, const char *name, int type, int group_t
    if (!chnk) return NULL;
 
    chnk->name = strdup(name);
+   chnk->len = strlen(name) + 1;
    chnk->size = size;
    chnk->data = data;
    chnk->type = type;
@@ -638,32 +739,48 @@ eet_data_stream_write(Eet_Data_Stream *ds, const void *data, int size)
 }
 
 static void
-eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
+eet_data_chunk_put(Eet_Dictionary *ed, Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
 {
-   int *size;
-   int s;
-   int size_ret = 0;
+   int  *size;
+   void *string;
+   int   s;
+   int   size_ret = 0;
+   int   string_ret = 0;
    unsigned char buf[4] = "CHK";
-   
+
    if (!chnk->data) return;
    /* chunk head */
-   
+
 /*   eet_data_stream_write(ds, "CHnK", 4);*/
    if (chnk->type != EET_T_UNKNOW) buf[3] = chnk->type;
    else buf[3] = chnk->group_type;
-   eet_data_stream_write(ds, buf, 4);
+
+   string = eet_data_put_string(ed, &chnk->name, &string_ret);
+   if (!string)
+     return ;
+
    /* size of chunk payload data + name */
-   s = strlen(chnk->name) + 1 + chnk->size;
-   size = eet_data_put_int(&s, &size_ret);
-   if (size)
-     {
-       eet_data_stream_write(ds, size, size_ret);
-       free(size);
-     }
+   s = chnk->size + string_ret;
+   size = eet_data_put_int(ed, &s, &size_ret);
+
+   /* FIXME: If something goes wrong the resulting file will be corrupted. */
+   if (!size)
+     goto on_error;
+
+   eet_data_stream_write(ds, buf, 4);
+
+   /* write chunk length */
+   eet_data_stream_write(ds, size, size_ret);
+
    /* write chunk name */
-   eet_data_stream_write(ds, chnk->name, strlen(chnk->name) + 1);
+   eet_data_stream_write(ds, string, string_ret);
+
    /* write payload */
    eet_data_stream_write(ds, chnk->data, chnk->size);
+
+   free(string);
+ on_error:
+   free(size);
 }
 
 /*---*/
@@ -775,17 +892,16 @@ eet_data_descriptor_new(const char *name,
    Eet_Data_Descriptor *edd;
 
    if (!name) return NULL;
-/*   
-   edd = calloc(1, sizeof(Eet_Data_Descriptor) + strlen(name) + 1);
-   edd->name = ((char *)edd) + sizeof(Eet_Data_Descriptor);
-   strcpy(edd->name, name);
- */
    edd = calloc(1, sizeof(Eet_Data_Descriptor));
+   if (!edd) return NULL;
+
    edd->name = name;
    edd->size = size;
    edd->func.mem_alloc = _eet_mem_alloc;
    edd->func.mem_free = _eet_mem_free;
    edd->func.str_alloc = _eet_str_alloc;
+   edd->func.str_direct_alloc = NULL;
+   edd->func.str_direct_free = NULL;
    edd->func.str_free = _eet_str_free;
    edd->func.list_next = func_list_next;
    edd->func.list_append = func_list_append;
@@ -804,8 +920,45 @@ eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc)
    Eet_Data_Descriptor *edd;
 
    if (!eddc) return NULL;
+   if (eddc->version < 1) return NULL;
+   edd = calloc(1, sizeof(Eet_Data_Descriptor));
+   if (!edd) return NULL;
+
+   edd->name = eddc->name;
+   edd->size = eddc->size;
+   edd->func.mem_alloc = _eet_mem_alloc;
+   edd->func.mem_free = _eet_mem_free;
+   edd->func.str_alloc = _eet_str_alloc;
+   edd->func.str_free = _eet_str_free;
+   if (eddc->func.mem_alloc)
+     edd->func.mem_alloc = eddc->func.mem_alloc;
+   if (eddc->func.mem_free)
+     edd->func.mem_free = eddc->func.mem_free;
+   if (eddc->func.str_alloc)
+     edd->func.str_alloc = eddc->func.str_alloc;
+   if (eddc->func.str_free)
+     edd->func.str_free = eddc->func.str_free;
+   edd->func.list_next = eddc->func.list_next;
+   edd->func.list_append = eddc->func.list_append;
+   edd->func.list_data = eddc->func.list_data;
+   edd->func.list_free = eddc->func.list_free;
+   edd->func.hash_foreach = eddc->func.hash_foreach;
+   edd->func.hash_add = eddc->func.hash_add;
+   edd->func.hash_free = eddc->func.hash_free;
+
+   return edd;
+}
+
+EAPI Eet_Data_Descriptor *
+eet_data_descriptor3_new(Eet_Data_Descriptor_Class *eddc)
+{
+   Eet_Data_Descriptor *edd;
+
+   if (!eddc) return NULL;
+   if (eddc->version < 2) return NULL;
    edd = calloc(1, sizeof(Eet_Data_Descriptor));
-   if (eddc->version < 1) return edd;
+   if (!edd) return NULL;
+
    edd->name = eddc->name;
    edd->size = eddc->size;
    edd->func.mem_alloc = _eet_mem_alloc;
@@ -820,6 +973,10 @@ eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc)
      edd->func.str_alloc = eddc->func.str_alloc;
    if (eddc->func.str_free)
      edd->func.str_free = eddc->func.str_free;
+   if (eddc->func.str_direct_alloc)
+     edd->func.str_direct_alloc = eddc->func.str_direct_alloc;
+   if (eddc->func.str_direct_free)
+     edd->func.str_direct_free = eddc->func.str_direct_free;
    edd->func.list_next = eddc->func.list_next;
    edd->func.list_append = eddc->func.list_append;
    edd->func.list_data = eddc->func.list_data;
@@ -827,6 +984,7 @@ eet_data_descriptor2_new(Eet_Data_Descriptor_Class *eddc)
    edd->func.hash_foreach = eddc->func.hash_foreach;
    edd->func.hash_add = eddc->func.hash_add;
    edd->func.hash_free = eddc->func.hash_free;
+
    return edd;
 }
 
@@ -834,7 +992,6 @@ EAPI void
 eet_data_descriptor_free(Eet_Data_Descriptor *edd)
 {
    _eet_descriptor_hash_free(edd);
-//   if (edd->strings) free(edd->strings);
    if (edd->elements.set) free(edd->elements.set);
    free(edd);
 }
@@ -855,71 +1012,39 @@ eet_data_descriptor_element_add(Eet_Data_Descriptor *edd,
    edd->elements.set = realloc(edd->elements.set, edd->elements.num * sizeof(Eet_Data_Element));
    if (!edd->elements.set) return;
    ede = &(edd->elements.set[edd->elements.num - 1]);
-/*
-   l1 = strlen(name);
-   p1 = edd->strings_len;
-   if (counter_name)
-     {
-       l2 = strlen(counter_name);
-       p2 = p1 + l1 + 1;
-     }
-   else l2 = -1;
-   ps = edd->strings;
-   edd->strings_len += l1 + 1 + l2 + 1;
-   edd->strings = realloc(edd->strings, edd->strings_len);
-   if (!edd->strings)
-     {
-       edd->strings = ps;
-       return;
-     }
-   for (i = 0; i < edd->elements.num; i++)
-     {
-       edd->elements.set[i].name = 
-         edd->strings + (edd->elements.set[i].name - ps);
-       if (edd->elements.set[i].counter_name)
-         edd->elements.set[i].counter_name =
-         edd->strings + (edd->elements.set[i].counter_name - ps);
-     }
-   ede->name = edd->strings + p1;
-   strcpy(ede->name, name);
- */
    ede->name = name;
-   
+
    ede->type = type;
    ede->group_type = group_type;
    ede->offset = offset;
    ede->count = count;
-/*     
-   if (counter_name)
-     {
-       ede->counter_name = edd->strings + p2;
-       strcpy(ede->counter_name, counter_name);
-     }
-   else ede->counter_name = NULL;
- */
    ede->counter_name = counter_name;
-       
+
    ede->subtype = subtype;
 }
 
 EAPI void *
 eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name)
 {
-   void *data_dec;
-   void *data;
-   int size;
-   int required_free = 0;
+   const Eet_Dictionary *ed = NULL;
+   const void           *data;
+   void                 *data_dec;
+   int                   size;
+   int                   required_free = 0;
+
+   ed = eet_dictionary_get(ef);
 
-   data = (void *)eet_read_direct(ef, name, &size);
+   data = eet_read_direct(ef, name, &size);
    if (!data)
      {
        required_free = 1;
        data = eet_read(ef, name, &size);
        if (!data) return NULL;
      }
-   data_dec = eet_data_descriptor_decode(edd, data, size);
+
+   data_dec = _eet_data_descriptor_decode(ed, edd, data, size, 0, NULL, NULL);
    if (required_free)
-     free(data);
+     free((void*)data);
 
    return data_dec;
 }
@@ -927,227 +1052,205 @@ eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name)
 EAPI int
 eet_data_write(Eet_File *ef, Eet_Data_Descriptor *edd, const char *name, const void *data, int compress)
 {
-   void *data_enc;
-   int size;
-   int val;
+   Eet_Dictionary       *ed;
+   void                 *data_enc;
+   int                   size;
+   int                   val;
 
-   data_enc = eet_data_descriptor_encode(edd, data, &size);
+   ed = eet_dictionary_get(ef);
+
+   data_enc = _eet_data_descriptor_encode(ed, edd, data, &size);
    if (!data_enc) return 0;
    val = eet_write(ef, name, data_enc, size, compress);
    free(data_enc);
    return val;
 }
 
-static int    freelist_ref = 0;
-static int    freelist_len = 0;
-static int    freelist_num = 0;
-static void **freelist = NULL;
+typedef struct _Eet_Free        Eet_Free;
+struct _Eet_Free
+{
+  int     ref;
+  int     len;
+  int     num;
+  void  **list;
+};
 
 static void
-_eet_freelist_add(void *data)
+_eet_free_add(Eet_Free *ef, void *data)
 {
-   freelist_num++;
-   if (freelist_num > freelist_len)
+   int  i;
+
+   for (i = 0; i < ef->num; ++i)
+     if (ef->list[i] == data) return;
+
+   ef->num++;
+   if (ef->num > ef->len)
      {
-       freelist_len += 16;
-       freelist = realloc(freelist, freelist_len * sizeof(void *));
+        void    **tmp;
+
+        tmp = realloc(ef->list, (ef->len + 16) * sizeof(void*));
+        if (!tmp) return ;
+
+        ef->len += 16;
+        ef->list = tmp;
      }
-   freelist[freelist_num - 1] = data;
+   ef->list[ef->num - 1] = data;
 }
-
 static void
-_eet_freelist_reset(void)
+_eet_free_reset(Eet_Free *ef)
 {
-   if (freelist_ref > 0) return;
-   freelist_len = 0;
-   freelist_num = 0;
-   if (freelist) free(freelist);
-   freelist = NULL;
+   if (ef->ref > 0) return ;
+   ef->len = 0;
+   ef->num = 0;
+   if (ef->list) free(ef->list);
+   ef->list = NULL;
 }
-
 static void
-_eet_freelist_free(Eet_Data_Descriptor *edd)
+_eet_free_ref(Eet_Free *ef)
 {
-   int i;
-
-   if (freelist_ref > 0) return;
-   for (i = 0; i < freelist_num; i++)
-     {
-       if (edd)
-         edd->func.mem_free(freelist[i]);
-       else
-         free(freelist[i]);
-     }
-   _eet_freelist_reset();
+   ef->ref++;
 }
-
 static void
-_eet_freelist_ref(void)
+_eet_free_unref(Eet_Free *ef)
 {
-   freelist_ref++;
+   ef->ref--;
 }
 
-static void
-_eet_freelist_unref(void)
-{
-   freelist_ref--;
-}
+static Eet_Free freelist = { 0, 0, 0, NULL };
 
-static int     freelist_list_ref = 0;
-static int     freelist_list_len = 0;
-static int     freelist_list_num = 0;
-static void ***freelist_list = NULL;
+#define _eet_freelist_add(Data)         _eet_free_add(&freelist, Data);
+#define _eet_freelist_reset()           _eet_free_reset(&freelist);
+#define _eet_freelist_ref()             _eet_free_ref(&freelist);
+#define _eet_freelist_unref()           _eet_free_unref(&freelist);
 
 static void
-_eet_freelist_list_add(void **data)
+_eet_freelist_free(Eet_Data_Descriptor *edd)
 {
    int i;
 
-   for (i = 0; i < freelist_list_num; i++)
-     {
-       if (freelist_list[i] == data) return;
-     }
-   freelist_list_num++;
-   if (freelist_list_num > freelist_list_len)
+   if (freelist.ref > 0) return;
+   for (i = 0; i < freelist.num; i++)
      {
-       freelist_list_len += 16;
-       freelist_list = realloc(freelist_list, freelist_list_len * sizeof(void *));
+       if (edd)
+         edd->func.mem_free(freelist.list[i]);
+       else
+         free(freelist.list[i]);
      }
-   freelist_list[freelist_list_num - 1] = data;
+   _eet_free_reset(&freelist);
 }
 
-static void
-_eet_freelist_list_reset(void)
-{
-   if (freelist_list_ref > 0) return;
-   freelist_list_len = 0;
-   freelist_list_num = 0;
-   if (freelist_list) free(freelist_list);
-   freelist_list = NULL;
-}
+static Eet_Free freelist_list = { 0, 0, 0, NULL };
+
+#define _eet_freelist_list_add(Data)    _eet_free_add(&freelist_list, Data);
+#define _eet_freelist_list_reset()      _eet_free_reset(&freelist_list);
+#define _eet_freelist_list_ref()        _eet_free_ref(&freelist_list);
+#define _eet_freelist_list_unref()      _eet_free_unref(&freelist_list);
 
 static void
 _eet_freelist_list_free(Eet_Data_Descriptor *edd)
 {
    int i;
 
-   if (freelist_list_ref > 0) return;
-   for (i = 0; i < freelist_list_num; i++)
+   if (freelist_list.ref > 0) return;
+   for (i = 0; i < freelist_list.num; i++)
      {
        if (edd)
-         edd->func.list_free(*(freelist_list[i]));
+         edd->func.list_free(*((void**)(freelist_list.list[i])));
      }
-   _eet_freelist_list_reset();
+   _eet_free_reset(&freelist_list);
 }
 
-static void
-_eet_freelist_list_ref(void)
-{
-   freelist_list_ref++;
-}
+static Eet_Free freelist_str = { 0, 0, 0, NULL };
 
-static void
-_eet_freelist_list_unref(void)
-{
-   freelist_list_ref--;
-}
-
-static int    freelist_str_ref = 0;
-static int    freelist_str_len = 0;
-static int    freelist_str_num = 0;
-static void **freelist_str = NULL;
+#define _eet_freelist_str_add(Data)     _eet_free_add(&freelist_str, Data);
+#define _eet_freelist_str_reset()       _eet_free_reset(&freelist_str);
+#define _eet_freelist_str_ref()         _eet_free_ref(&freelist_str);
+#define _eet_freelist_str_unref()       _eet_free_unref(&freelist_str);
 
 static void
-_eet_freelist_str_add(void *data)
+_eet_freelist_str_free(Eet_Data_Descriptor *edd)
 {
-   freelist_str_num++;
-   if (freelist_str_num > freelist_str_len)
+   int i;
+
+   if (freelist_str.ref > 0) return;
+   for (i = 0; i < freelist_str.num; i++)
      {
-       freelist_str_len += 16;
-       freelist_str = realloc(freelist_str, freelist_str_len * sizeof(void *));
+       if (edd)
+          edd->func.str_free(freelist_str.list[i]);
+       else
+         free(freelist_str.list[i]);
      }
-   freelist_str[freelist_str_num - 1] = data;
+   _eet_free_reset(&freelist_str);
 }
 
-static void
-_eet_freelist_str_reset(void)
-{
-   if (freelist_str_ref > 0) return;
-   freelist_str_len = 0;
-   freelist_str_num = 0;
-   if (freelist_str) free(freelist_str);
-   freelist_str = NULL;
-}
+static Eet_Free freelist_direct_str = { 0, 0, 0, NULL };
+
+#define _eet_freelist_direct_str_add(Data)      _eet_free_add(&freelist_direct_str, Data);
+#define _eet_freelist_direct_str_reset()        _eet_free_reset(&freelist_direct_str);
+#define _eet_freelist_direct_str_ref()          _eet_free_ref(&freelist_direct_str);
+#define _eet_freelist_direct_str_unref()        _eet_free_unref(&freelist_direct_str);
 
 static void
-_eet_freelist_str_free(Eet_Data_Descriptor *edd)
+_eet_freelist_direct_str_free(Eet_Data_Descriptor *edd)
 {
    int i;
 
-   if (freelist_str_ref > 0) return;
-   for (i = 0; i < freelist_str_num; i++)
+   if (freelist_str.ref > 0) return;
+   for (i = 0; i < freelist_str.num; i++)
      {
        if (edd)
-         edd->func.str_free(freelist_str[i]);
+          edd->func.str_direct_free(freelist_str.list[i]);
        else
-         free(freelist_str[i]);
+         free(freelist_str.list[i]);
      }
-   _eet_freelist_str_reset();
-}
-
-static void
-_eet_freelist_str_ref(void)
-{
-   freelist_str_ref++;
-}
-
-static void
-_eet_freelist_str_unref(void)
-{
-   freelist_str_ref--;
+   _eet_free_reset(&freelist_str);
 }
 
 static int
 eet_data_descriptor_encode_hash_cb(void *hash, const char *key, void *hdata, void *fdata)
 {
-   Eet_Data_Encode_Hash_Info *edehi;
-   Eet_Data_Stream    *ds;
-   Eet_Data_Element   *ede;
-   Eet_Data_Chunk     *echnk;
-   void               *data = NULL;
-   int                 size;
+   Eet_Dictionary               *ed;
+   Eet_Data_Encode_Hash_Info    *edehi;
+   Eet_Data_Stream              *ds;
+   Eet_Data_Element             *ede;
+   Eet_Data_Chunk               *echnk;
+   void                         *data = NULL;
+   int                           size;
 
    edehi = fdata;
    ede = edehi->ede;
    ds = edehi->ds;
+   ed = edehi->ed;
 
    /* Store key */
-   data = eet_data_put_type(EET_T_STRING,
+   data = eet_data_put_type(ed,
+                            EET_T_STRING,
                            &key,
                            &size);
    if (data)
      {
        echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
-       eet_data_chunk_put(echnk, ds);
+       eet_data_chunk_put(ed, echnk, ds);
        eet_data_chunk_free(echnk);
        free(data);
        data = NULL;
      }
 
    /* Store data */
-   if ((ede->type >= EET_T_CHAR) &&
-       (ede->type <= EET_T_STRING))
-     data = eet_data_put_type(ede->type,
+   if (IS_SIMPLE_TYPE(ede->type))
+     data = eet_data_put_type(ed,
+                              ede->type,
                              hdata,
                              &size);
    else if (ede->subtype)
-     data = eet_data_descriptor_encode(ede->subtype,
-                                      hdata,
-                                      &size);
+     data = _eet_data_descriptor_encode(ed,
+                                        ede->subtype,
+                                        hdata,
+                                        &size);
    if (data)
      {
        echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
-       eet_data_chunk_put(echnk, ds);
+       eet_data_chunk_put(ed, echnk, ds);
        eet_data_chunk_free(echnk);
        free(data);
        data = NULL;
@@ -1344,7 +1447,8 @@ _eet_data_dump_free(Node *node)
 }
 
 static void *
-_eet_data_dump_encode(Node *node,
+_eet_data_dump_encode(Eet_Dictionary *ed,
+                      Node *node,
                      int *size_ret)
 {
    Eet_Data_Chunk *chnk = NULL, *echnk = NULL;
@@ -1361,7 +1465,7 @@ _eet_data_dump_encode(Node *node,
        if (v == 0x12345678) words_bigendian = 1;
        else words_bigendian = 0;
      }
-   
+
    ds = eet_data_stream_new();
    if (!ds) return NULL;
    
@@ -1370,7 +1474,7 @@ _eet_data_dump_encode(Node *node,
       case EET_G_UNKNOWN:
        for (n = node->values; n; n = n->next)
          {
-            data = _eet_data_dump_encode(n, &size);
+            data = _eet_data_dump_encode(ed, n, &size);
             if (data)
               {
                  eet_data_stream_write(ds, data, size);
@@ -1381,7 +1485,7 @@ _eet_data_dump_encode(Node *node,
       case EET_G_ARRAY:
        for (n = node->values; n; n = n->next)
          {
-            data = _eet_data_dump_encode(n, &size);
+            data = _eet_data_dump_encode(ed, n, &size);
             if (data)
               {
                  eet_data_stream_write(ds, data, size);
@@ -1392,7 +1496,7 @@ _eet_data_dump_encode(Node *node,
       case EET_G_VAR_ARRAY:
        for (n = node->values; n; n = n->next)
          {
-            data = _eet_data_dump_encode(n, &size);
+            data = _eet_data_dump_encode(ed, n, &size);
             if (data)
               {
                  eet_data_stream_write(ds, data, size);
@@ -1403,7 +1507,7 @@ _eet_data_dump_encode(Node *node,
       case EET_G_LIST:
        for (n = node->values; n; n = n->next)
          {
-            data = _eet_data_dump_encode(n, &size);
+            data = _eet_data_dump_encode(ed, n, &size);
             if (data)
               {
                  eet_data_stream_write(ds, data, size);
@@ -1414,20 +1518,21 @@ _eet_data_dump_encode(Node *node,
       case EET_G_HASH:
        if (node->key)
          {
-            data = eet_data_put_type(EET_T_STRING,
+            data = eet_data_put_type(ed,
+                                      EET_T_STRING,
                                      &node->key,
                                      &size);
             if (data)
               {
                  echnk = eet_data_chunk_new(data, size, node->name, node->type, node->type);
-                 eet_data_chunk_put(echnk, ds);
+                 eet_data_chunk_put(ed, echnk, ds);
                  eet_data_chunk_free(echnk);
                  free(data);
               }
          }
        for (n = node->values; n; n = n->next)
          {
-            data = _eet_data_dump_encode(n, &size);
+            data = _eet_data_dump_encode(ed, n, &size);
             if (data)
               {
                  eet_data_stream_write(ds, data, size);
@@ -1436,7 +1541,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_CHAR:
-       data = eet_data_put_type(node->type, &(node->data.c), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.c), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1444,7 +1549,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_SHORT:
-       data = eet_data_put_type(node->type, &(node->data.s), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.s), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1452,7 +1557,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_INT:
-       data = eet_data_put_type(node->type, &(node->data.i), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.i), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1460,7 +1565,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_LONG_LONG:
-       data = eet_data_put_type(node->type, &(node->data.l), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.l), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1468,7 +1573,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_FLOAT:
-       data = eet_data_put_type(node->type, &(node->data.f), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.f), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1476,7 +1581,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_DOUBLE:
-       data = eet_data_put_type(node->type, &(node->data.d), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.d), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1484,7 +1589,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_UCHAR:
-       data = eet_data_put_type(node->type, &(node->data.uc), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.uc), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1492,7 +1597,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_USHORT:
-       data = eet_data_put_type(node->type, &(node->data.us), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.us), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1500,7 +1605,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_UINT:
-       data = eet_data_put_type(node->type, &(node->data.ui), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.ui), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1508,7 +1613,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_ULONG_LONG:
-       data = eet_data_put_type(node->type, &(node->data.ul), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.ul), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1516,7 +1621,7 @@ _eet_data_dump_encode(Node *node,
          }
        break;
       case EET_T_STRING:
-       data = eet_data_put_type(node->type, &(node->data.str), &size);
+        data = eet_data_put_type(ed, node->type, &(node->data.str), &size);
        if (data)
          {
             eet_data_stream_write(ds, data, size);
@@ -1536,7 +1641,7 @@ _eet_data_dump_encode(Node *node,
    eet_data_stream_free(ds);
    
    ds = eet_data_stream_new();
-   eet_data_chunk_put(chnk, ds);
+   eet_data_chunk_put(ed, chnk, ds);
    cdata = ds->data;
    csize = ds->pos;
                             
@@ -1552,7 +1657,8 @@ _eet_data_dump_encode(Node *node,
 }
 
 static void *
-_eet_data_dump_parse(int *size_ret,
+_eet_data_dump_parse(Eet_Dictionary *ed,
+                     int *size_ret,
                     const char *src,
                     int size)
 {
@@ -1767,14 +1873,23 @@ _eet_data_dump_parse(int *size_ret,
 
    if (node_base)
      {
-       cdata = _eet_data_dump_encode(node_base, size_ret);
+       cdata = _eet_data_dump_encode(ed, node_base, size_ret);
        _eet_data_dump_free(node_base);
      }
    return cdata;
 }
 
+#define NEXT_CHUNK(P, Size, Echnk, Ed)                  \
+  {                                                     \
+     int        tmp;                                    \
+     tmp = Ed ? sizeof (int) * 2 : Echnk.len + 4;       \
+     P += (4 + Echnk.size + tmp);                       \
+     Size -= (4 + Echnk.size + tmp);                    \
+  }
+
 static void *
-_eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
+_eet_data_descriptor_decode(const Eet_Dictionary *ed,
+                            Eet_Data_Descriptor *edd,
                            const void *data_in,
                            int size_in,
                            int level,
@@ -1806,14 +1921,17 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
    if (data) _eet_freelist_add(data);
    dump = 0;
    memset(&chnk, 0, sizeof(Eet_Data_Chunk));
-   eet_data_chunk_get(&chnk, data_in, size_in);
+   eet_data_chunk_get(ed, &chnk, data_in, size_in);
    if (!chnk.name) goto error;
    if (edd)
      {
        if (strcmp(chnk.name, edd->name)) goto error;
      }
    p = chnk.data;
-   size = size_in - (4 + 4 + strlen(chnk.name) + 1);
+   if (ed)
+     size = size_in - (4 + sizeof(int) * 2);
+   else
+     size = size_in - (4 + 4 + chnk.len);
    if (edd)
      {
        if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
@@ -1855,7 +1973,7 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
 
        /* get next data chunk */
        memset(&echnk, 0, sizeof(Eet_Data_Chunk));
-       eet_data_chunk_get(&echnk, p, size);
+       eet_data_chunk_get(ed, &echnk, p, size);
        if (!echnk.name) goto error;
        /* FIXME: don't REPLY on edd - work without */
        if ((edd) && (!dumpfunc))
@@ -1888,24 +2006,31 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                       int ret;
                       void *data_ret;
                       
-                      if ((type >= EET_T_CHAR) &&
-                          (type <= EET_T_STRING))
+                      if (IS_SIMPLE_TYPE(type))
                         {
-                           ret = eet_data_get_type(type,
+                           ret = eet_data_get_type(ed,
+                                                    type,
                                                    echnk.data,
                                                    ((char *)echnk.data) + echnk.size,
                                                    ((char *)data) + ede->offset);
                            if (type == EET_T_STRING)
                              {
-                                char **str, *str2;
+                                char **str;
                                 
                                 str = (char **)(((char *)data) + ede->offset);
                                 if (*str)
                                   {
-                                     str2 = edd->func.str_alloc(*str);
-                                     free(*str);
-                                     *str = str2;
-                                     _eet_freelist_str_add(str2);
+                                      if (ed == NULL
+                                          || edd->func.str_direct_alloc == NULL)
+                                        {
+                                           *str = edd->func.str_alloc(*str);
+                                           _eet_freelist_str_add(*str);
+                                        }
+                                      else
+                                        {
+                                           *str = edd->func.str_direct_alloc(*str);
+                                           _eet_freelist_direct_str_add(*str);
+                                        }
                                   }
                              }
                         }
@@ -1913,7 +2038,8 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                         {
                            void **ptr;
                            
-                           data_ret = _eet_data_descriptor_decode(ede->subtype,
+                           data_ret = _eet_data_descriptor_decode(ed,
+                                                                   ede->subtype,
                                                                   echnk.data,
                                                                   echnk.size,
                                                                   level + 1,
@@ -1944,14 +2070,14 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                 ptr = (void **)(((char *)data) + ede->offset);
                                 list = *ptr;
                                 data_ret = NULL;
-                                if ((type >= EET_T_CHAR) &&
-                                    (type <= EET_T_STRING))
+                                if (IS_SIMPLE_TYPE(type))
                                   {
                                      data_ret = calloc(1, eet_coder[type].size);
                                      if (data_ret)
                                        {
                                           _eet_freelist_add(data_ret);
-                                          ret = eet_data_get_type(type,
+                                          ret = eet_data_get_type(ed,
+                                                                   type,
                                                                   echnk.data,
                                                                   ((char *)echnk.data) + echnk.size,
                                                                   data_ret);
@@ -1961,7 +2087,8 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                        goto error;
                                   }
                                 else if (ede->subtype)
-                                  data_ret = _eet_data_descriptor_decode(ede->subtype,
+                                  data_ret = _eet_data_descriptor_decode(ed,
+                                                                          ede->subtype,
                                                                          echnk.data,
                                                                          echnk.size,
                                                                          level + 2,
@@ -1989,29 +2116,28 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                 hash = *ptr;
                                 
                                 /* Read key */
-                                ret = eet_data_get_type(EET_T_STRING,
+                                ret = eet_data_get_type(ed,
+                                                         EET_T_STRING,
                                                         echnk.data,
                                                         ((char *)echnk.data) + echnk.size,
                                                         &key);
                                 if (ret <= 0) goto error;
                                 
                                 /* Advance to next chunk */
-                                p += (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
-                                size -= (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
-                                free(echnk.name);
+                                 NEXT_CHUNK(p, size, echnk, ed);
                                 memset(&echnk, 0, sizeof(Eet_Data_Chunk));
                                 
                                 /* Read value */
-                                eet_data_chunk_get(&echnk, p, size);
+                                eet_data_chunk_get(ed, &echnk, p, size);
                                 if (!echnk.name) goto error;
-                                if ((type >= EET_T_CHAR) &&
-                                    (type <= EET_T_STRING))
+                                if (IS_SIMPLE_TYPE(type))
                                   {
                                      data_ret = calloc(1, eet_coder[type].size);
                                      if (data_ret)
                                        {
                                           _eet_freelist_add(data_ret);
-                                          ret = eet_data_get_type(type,
+                                          ret = eet_data_get_type(ed,
+                                                                   type,
                                                                   echnk.data,
                                                                   ((char *)echnk.data) + echnk.size,
                                                                   data_ret);
@@ -2022,7 +2148,8 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                   }
                                 else if (ede->subtype)
                                   {
-                                     data_ret = _eet_data_descriptor_decode(ede->subtype,
+                                     data_ret = _eet_data_descriptor_decode(ed,
+                                                                             ede->subtype,
                                                                             echnk.data,
                                                                             echnk.size,
                                                                             level + 2,
@@ -2033,12 +2160,10 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                   {
                                      hash = edd->func.hash_add(hash, key, data_ret);
                                      *ptr = hash;
-                                     free(key);
                                      _eet_freelist_list_add(ptr);
                                   }
                                 else
                                   {
-                                     free(key);
                                      goto error;
                                   }
                              }
@@ -2066,10 +2191,10 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                  int ret;
                  void *data_ret;
                  
-                 if ((type >= EET_T_CHAR) &&
-                     (type <= EET_T_STRING))
+                 if (IS_SIMPLE_TYPE(type))
                    {
-                      ret = eet_data_get_type(type,
+                      ret = eet_data_get_type(ed,
+                                               type,
                                               echnk.data,
                                               ((char *)echnk.data) + echnk.size,
                                               dd);
@@ -2129,7 +2254,6 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                      dumpfunc(dumpdata, "string: \"");
                                      _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
                                      dumpfunc(dumpdata, "\"");
-                                     free(s);
                                   }
                              }
                            break;
@@ -2141,7 +2265,8 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                    }
                  else
                    {
-                      data_ret = _eet_data_descriptor_decode(NULL,
+                      data_ret = _eet_data_descriptor_decode(ed,
+                                                              NULL,
                                                              echnk.data,
                                                              echnk.size,
                                                              level + 1,
@@ -2187,18 +2312,19 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                            void *data_ret;
                            
                            data_ret = NULL;
-                           if ((type >= EET_T_CHAR) &&
-                               (type <= EET_T_STRING))
+                           if (IS_SIMPLE_TYPE(type))
                              {
                                 data_ret = (void *)1;
-                                ret = eet_data_get_type(type,
+                                ret = eet_data_get_type(ed,
+                                                         type,
                                                         echnk.data,
                                                         ((char *)echnk.data) + echnk.size,
                                                         dd);
                                 if (ret <= 0) goto error;
                              }
                            else
-                             data_ret = _eet_data_descriptor_decode(NULL,
+                             data_ret = _eet_data_descriptor_decode(ed,
+                                                                     NULL,
                                                                     echnk.data,
                                                                     echnk.size,
                                                                     level + 2,
@@ -2215,26 +2341,25 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                            void *data_ret = NULL;
                            
                            /* Read key */
-                           ret = eet_data_get_type(EET_T_STRING,
+                           ret = eet_data_get_type(ed,
+                                                    EET_T_STRING,
                                                    echnk.data,
                                                    ((char *)echnk.data) + echnk.size,
                                                    &key);
                            if (ret <= 0) goto error;
                            
                            /* Advance to next chunk */
-                           p += (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
-                           size -= (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
-                           free(echnk.name);
+                            NEXT_CHUNK(p, size, echnk, ed);
                            memset(&echnk, 0, sizeof(Eet_Data_Chunk));
                            
                            /* Read value */
-                           eet_data_chunk_get(&echnk, p, size);
+                           eet_data_chunk_get(ed, &echnk, p, size);
                            if (!echnk.name) goto error;
-                           if ((type >= EET_T_CHAR) &&
-                               (type <= EET_T_STRING))
+                           if (IS_SIMPLE_TYPE(type))
                              {
                                 data_ret = (void *)1;
-                                ret = eet_data_get_type(type,
+                                ret = eet_data_get_type(ed,
+                                                         type,
                                                         echnk.data,
                                                         ((char *)echnk.data) + echnk.size,
                                                         dd);
@@ -2252,18 +2377,16 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                      _eet_data_dump_string_escape(dumpdata, dumpfunc, s);
                                      dumpfunc(dumpdata, "\";\n");
                                   }
-                                data_ret = _eet_data_descriptor_decode(NULL,
+                                data_ret = _eet_data_descriptor_decode(ed,
+                                                                        NULL,
                                                                        echnk.data,
                                                                        echnk.size,
                                                                        level + 2,
                                                                        dumpfunc,
                                                                        dumpdata);
                              }
-                           if (data_ret)
-                             free(key);
-                           else
+                            if (!data_ret)
                              {
-                                free(key);
                                 goto error;
                              }
                         }
@@ -2279,18 +2402,16 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
               }
          }
        /* advance to next chunk */
-       p += (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
-       size -= (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
-       free(echnk.name);
+        NEXT_CHUNK(p, size, echnk, ed);
      }
    
-   free(chnk.name);
    _eet_freelist_unref();
    _eet_freelist_str_unref();
    _eet_freelist_list_unref();
    if (dumpfunc)
      {
        _eet_freelist_str_free(edd);
+       _eet_freelist_direct_str_free(edd);
        _eet_freelist_list_free(edd);
        _eet_freelist_free(edd);
      }
@@ -2315,11 +2436,11 @@ _eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
    return data;
 
 error:
-   if (chnk.name) free(chnk.name);
    _eet_freelist_unref();
    _eet_freelist_str_unref();
    _eet_freelist_list_unref();
    _eet_freelist_str_free(edd);
+   _eet_freelist_direct_str_free(edd);
    _eet_freelist_list_free(edd);
    _eet_freelist_free(edd);
    if (dumpfunc)
@@ -2342,7 +2463,7 @@ eet_data_text_dump(const void *data_in,
                   void (*dumpfunc) (void *data, const char *str),
                   void *dumpdata)
 {
-   if (_eet_data_descriptor_decode(NULL, data_in, size_in, 0,
+   if (_eet_data_descriptor_decode(NULL, NULL, data_in, size_in, 0,
                                   dumpfunc, dumpdata))
      return 1;
    return 0;
@@ -2353,7 +2474,7 @@ eet_data_text_undump(const char *text,
                     int textlen,
                     int *size_ret)
 {
-   return _eet_data_dump_parse(size_ret, text, textlen);
+   return _eet_data_dump_parse(NULL, size_ret, text, textlen);
 }
 
 EAPI void *
@@ -2361,19 +2482,21 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                           const void *data_in,
                           int size_in)
 {
-   return _eet_data_descriptor_decode(edd, data_in, size_in, 0, NULL, NULL);
+   return _eet_data_descriptor_decode(NULL, edd, data_in, size_in, 0,
+                                      NULL, NULL);
 }
 
-EAPI void *
-eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
-                          const void *data_in,
-                          int *size_ret)
+static void *
+_eet_data_descriptor_encode(Eet_Dictionary *ed,
+                            Eet_Data_Descriptor *edd,
+                            const void *data_in,
+                            int *size_ret)
 {
-   Eet_Data_Chunk *chnk;
-   Eet_Data_Stream *ds;
-   int i;
-   void *cdata;
-   int csize;
+   Eet_Data_Stream      *ds;
+   Eet_Data_Chunk       *chnk;
+   void                 *cdata;
+   int                   csize;
+   int                   i;
 
    if (words_bigendian == -1)
      {
@@ -2396,22 +2519,23 @@ eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
        data = NULL;
        if (ede->group_type == EET_G_UNKNOWN)
          {
-            if ((ede->type >= EET_T_CHAR) &&
-                (ede->type <= EET_T_STRING))
-              data = eet_data_put_type(ede->type,
+            if (IS_SIMPLE_TYPE(ede->type))
+              data = eet_data_put_type(ed,
+                                        ede->type,
                                        ((char *)data_in) + ede->offset,
                                        &size);
             else if (ede->subtype)
               {
                  if (*((char **)(((char *)data_in) + ede->offset)))
-                   data = eet_data_descriptor_encode(ede->subtype,
-                                                     *((char **)(((char *)data_in) + ede->offset)),
-                                                     &size);
+                   data = _eet_data_descriptor_encode(ed,
+                                                       ede->subtype,
+                                                       *((char **)(((char *)data_in) + ede->offset)),
+                                                       &size);
               }
             if (data)
               {
                  echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
-                 eet_data_chunk_put(echnk, ds);
+                 eet_data_chunk_put(ed, echnk, ds);
                  eet_data_chunk_free(echnk);
                  free(data);
                  data = NULL;
@@ -2434,19 +2558,20 @@ eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
                       l = *((void **)(((char *)data_in) + ede->offset));
                       for (; l; l = edd->func.list_next(l))
                         {
-                           if ((ede->type >= EET_T_CHAR) &&
-                               (ede->type <= EET_T_STRING))
-                             data = eet_data_put_type(ede->type,
+                           if (IS_SIMPLE_TYPE(ede->type))
+                             data = eet_data_put_type(ed,
+                                                       ede->type,
                                                       edd->func.list_data(l),
                                                       &size);
                            else if (ede->subtype)
-                             data = eet_data_descriptor_encode(ede->subtype,
-                                                               edd->func.list_data(l),
-                                                               &size);
+                             data = _eet_data_descriptor_encode(ed,
+                                                                 ede->subtype,
+                                                                 edd->func.list_data(l),
+                                                                 &size);
                            if (data)
                              {
                                 echnk = eet_data_chunk_new(data, size, ede->name, ede->type, ede->group_type);
-                                eet_data_chunk_put(echnk, ds);
+                                eet_data_chunk_put(ed, echnk, ds);
                                 eet_data_chunk_free(echnk);
                                 free(data);
                                 data = NULL;
@@ -2462,6 +2587,7 @@ eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
                       l = *((void **)(((char *)data_in) + ede->offset));
                       fdata.ds = ds;
                       fdata.ede = ede;
+                       fdata.ed = ed;
                       edd->func.hash_foreach(l, eet_data_descriptor_encode_hash_cb, &fdata);
                    }
                  break;
@@ -2476,7 +2602,7 @@ eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
    eet_data_stream_free(ds);
 
    ds = eet_data_stream_new();
-   eet_data_chunk_put(chnk, ds);
+   eet_data_chunk_put(ed, chnk, ds);
    cdata = ds->data;
    csize = ds->pos;
 
@@ -2490,3 +2616,11 @@ eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
 
    return cdata;
 }
+
+EAPI void *
+eet_data_descriptor_encode(Eet_Data_Descriptor *edd,
+                          const void *data_in,
+                          int *size_ret)
+{
+   return _eet_data_descriptor_encode(NULL, edd, data_in, size_ret);
+}
index 09d6fdd..6b1eac5 100644 (file)
@@ -1,5 +1,5 @@
-#include "Eet_private.h"
 #include "Eet.h"
+#include "Eet_private.h"
 
 /*---*/
 
@@ -728,10 +728,11 @@ eet_data_image_read(Eet_File *ef, const char *name,
                    unsigned int *w, unsigned int *h, int *alpha,
                    int *compress, int *quality, int *lossy)
 {
-   void                *data;
-   int         size;
    unsigned int *d = NULL;
-   int         free_data = 0;
+   void                *data;
+   int          size;
+   int          free_data = 0;
+
 
    data = (void *)eet_read_direct(ef, name, &size);
    if (!data)
index 324705f..3357267 100644 (file)
@@ -2,8 +2,8 @@
  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
  */
 
-#include "Eet_private.h"
 #include "Eet.h"
+#include "Eet_private.h"
 
 #include <sys/types.h>
 #ifdef HAVE_SYS_MMAN_H
@@ -17,6 +17,8 @@
 #define EET_MAGIC_FILE                  0x1ee7ff00
 #define EET_MAGIC_FILE_HEADER           0x1ee7ff01
 
+#define EET_MAGIC_FILE2                 0x1ee70f42
+
 typedef struct _Eet_File_Header         Eet_File_Header;
 typedef struct _Eet_File_Node           Eet_File_Node;
 typedef struct _Eet_File_Directory      Eet_File_Directory;
@@ -27,6 +29,7 @@ struct _Eet_File
    FILE                 *fp;
    Eet_File_Header      *header;
    const unsigned char  *data;
+   Eet_Dictionary       *ed;
 
    int                   magic;
    int                   references;
@@ -53,19 +56,24 @@ struct _Eet_File_Directory
 
 struct _Eet_File_Node
 {
-   char          *name;
-   void          *data;
-   Eet_File_Node *next; /* FIXME: make buckets linked lists */
+   char                 *name;
+   void                 *data;
+   Eet_File_Node        *next; /* FIXME: make buckets linked lists */
 
-   int            offset;
-   int            size;
-   int            data_size;
+   int                   offset;
+   int                   dictionary_offset;
+   int                   name_offset;
 
-   unsigned char  free_name : 1;
-   unsigned char  compression : 1;
+   int                   name_size;
+   int                   size;
+   int                   data_size;
+
+   unsigned char         free_name : 1;
+   unsigned char         compression : 1;
 };
 
 #if 0
+/* Version 2 */
 /* NB: all int's are stored in network byte order on disk */
 /* file format: */
 int magic; /* magic number ie 0x1ee7ff00 */
@@ -78,17 +86,54 @@ struct
    int size; /* size of the data chunk */
    int data_size; /* size of the (uncompressed) data chunk */
    int name_size; /* length in bytes of the name field */
-   char name[name_size]; /* name string (variable length) */
+   char name[name_size]; /* name string (variable length) and \0 terminated */
 } directory[num_directory_entries];
 /* and now startes the data stream... */
 #endif
 
+#if 0
+/* Version 3 */
+/* NB: all int's are stored in network byte order on disk */
+/* file format: */
+int magic; /* magic number ie 0x1ee70f42 */
+int num_directory_entries; /* number of directory entries to follow */
+int num_dictionary_entries; /* number of dictionary entries to follow */
+struct
+{
+  int data_offset; /* bytes offset into file for data chunk */
+  int size; /* size of the data chunk */
+  int data_size; /* size of the (uncompressed) data chunk */
+  int name_offset; /* bytes offset into file for name string */
+  int name_size; /* length in bytes of the name field */
+  int flags; /* flags - for now 0 = uncompressed, 1 = compressed */
+} directory[num_directory_entries];
+struct
+{
+  int hash;
+  int offset;
+  int size;
+  int prev;
+  int next;
+} dictionary[num_dictionary_entries];
+/* now start the string stream. */
+/* and right after them the data stream. */
+#endif
+
+#define EET_FILE2_HEADER_COUNT                  3
+#define EET_FILE2_DIRECTORY_ENTRY_COUNT         6
+#define EET_FILE2_DICTIONARY_ENTRY_COUNT        5
+
+#define EET_FILE2_HEADER_SIZE                   (sizeof(int) * EET_FILE2_HEADER_COUNT)
+#define EET_FILE2_DIRECTORY_ENTRY_SIZE          (sizeof(int) * EET_FILE2_DIRECTORY_ENTRY_COUNT)
+#define EET_FILE2_DICTIONARY_ENTRY_SIZE         (sizeof(int) * EET_FILE2_DICTIONARY_ENTRY_COUNT)
+
 /* prototypes of internal calls */
 static Eet_File                *eet_cache_find(const char *path, Eet_File **cache, int cache_num);
 static void            eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
 static void            eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
 static int             eet_string_match(const char *s1, const char *s2);
 static Eet_Error       eet_flush(Eet_File *ef);
+static Eet_Error       eet_flush2(Eet_File *ef);
 static Eet_File_Node   *find_node_by_name(Eet_File *ef, const char *name);
 static int             read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
 
@@ -263,6 +308,179 @@ eet_string_match(const char *s1, const char *s2)
    return (!strcmp(s1, s2));
 }
 
+/* flush out writes to a v2 eet file */
+static Eet_Error
+eet_flush2(Eet_File *ef)
+{
+   Eet_File_Node        *efn;
+   Eet_Error             error = EET_ERROR_NONE;
+   int                   head[EET_FILE2_HEADER_COUNT];
+   int                   num_directory_entries = 0;
+   int                   num_dictionary_entries = 0;
+   int                   bytes_directory_entries = 0;
+   int                   bytes_dictionary_entries = 0;
+   int                   bytes_strings = 0;
+   int                   data_offset = 0;
+   int                   strings_offset = 0;
+   int                   num;
+   int                   i;
+   int                   j;
+
+   if (eet_check_pointer(ef))
+     return EET_ERROR_BAD_OBJECT;
+   if (eet_check_header(ef))
+     return EET_ERROR_EMPTY;
+   if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
+     return EET_ERROR_NOT_WRITABLE;
+   if (!ef->writes_pending)
+     return EET_ERROR_NONE;
+
+   /* calculate string base offset and data base offset */
+   num = (1 << ef->header->directory->size);
+   for (i = 0; i < num; ++i)
+     {
+        for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
+          {
+             num_directory_entries++;
+             bytes_strings += strlen(efn->name) + 1;
+          }
+     }
+   if (ef->ed)
+     {
+        num_dictionary_entries = ef->ed->count;
+
+        for (i = 0; i < num_dictionary_entries; ++i)
+          bytes_strings += ef->ed->all[i].len;
+     }
+
+   /* calculate section bytes size */
+   bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
+   bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
+
+   /* calculate per entry offset */
+   strings_offset = bytes_directory_entries + bytes_dictionary_entries;
+   data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings;
+
+   for (i = 0; i < num; ++i)
+     {
+        for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
+          {
+             efn->offset = data_offset;
+             data_offset += efn->size;
+
+             efn->name_offset = strings_offset;
+             strings_offset += efn->name_size;
+          }
+     }
+
+   /* calculate dictionary strings offset */
+   if (ef->ed)
+     ef->ed->offset = strings_offset;
+
+   /* go thru and write the header */
+   head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2);
+   head[1] = (int) htonl ((unsigned int) num_directory_entries);
+   head[2] = (int) htonl ((unsigned int) num_dictionary_entries);
+
+   fseek(ef->fp, 0, SEEK_SET);
+   if (fwrite(head, sizeof (head), 1, ef->fp) != 1)
+     goto write_error;
+
+   /* write directories entry */
+   j = 0;
+   for (i = 0; i < num; i++)
+     {
+        for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
+          {
+             int        ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
+
+             ibuf[0] = (int) htonl ((unsigned int) efn->offset);
+             ibuf[1] = (int) htonl ((unsigned int) efn->size);
+             ibuf[2] = (int) htonl ((unsigned int) efn->data_size);
+             ibuf[3] = (int) htonl ((unsigned int) efn->name_offset);
+             ibuf[4] = (int) htonl ((unsigned int) efn->name_size);
+             ibuf[5] = (int) htonl ((unsigned int) efn->compression);
+
+             if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
+               goto write_error;
+          }
+     }
+
+   /* write dictionnary */
+   if (ef->ed)
+     {
+        int     offset = strings_offset;
+
+        for (j = 0; j < ef->ed->count; ++j)
+          {
+             int      sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
+
+             sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash);
+             sbuf[1] = (int) htonl ((unsigned int) offset);
+             sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len);
+             sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev);
+             sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next);
+
+             offset += ef->ed->all[j].len;
+
+             if (fwrite(sbuf, sizeof (sbuf), 1, ef->fp) != 1)
+               goto write_error;
+          }
+     }
+
+   /* write directories name */
+   for (i = 0; i < num; i++)
+     {
+        for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
+          {
+             if (fwrite(efn->name, efn->name_size, 1, ef->fp) != 1)
+               goto write_error;
+          }
+     }
+
+   /* write strings */
+   if (ef->ed)
+     for (j = 0; j < ef->ed->count; ++j)
+       if (ef->ed->all[j].str)
+         {
+            if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, ef->fp) != 1)
+              goto write_error;
+         }
+       else
+         {
+            if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, ef->fp) != 1)
+              goto write_error;
+         }
+
+   /* write data */
+   for (i = 0; i < num; i++)
+     {
+        for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
+          {
+             if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
+               goto write_error;
+          }
+     }
+
+   /* no more writes pending */
+   ef->writes_pending = 0;
+
+   return EET_ERROR_NONE;
+
+ write_error:
+   switch (ferror(ef->fp))
+     {
+      case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
+      case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
+      case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
+      case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
+      default: error = EET_ERROR_WRITE_ERROR; break;
+     }
+   fclose(ef->fp);
+   ef->fp = NULL;
+   return error;
+}
+
 /* flush out writes to an eet file */
 static Eet_Error
 eet_flush(Eet_File *ef)
@@ -454,22 +672,194 @@ eet_clearcache(void)
      }
 }
 
+/* FIXME: MMAP race condition in READ_WRITE_MODE */
 static Eet_File*
-eet_internal_read(Eet_File *ef)
+eet_internal_read2(Eet_File *ef)
 {
-   const unsigned char *dyn_buf = NULL;
-   const unsigned char *p = NULL;
-   int                 index = 0;
-   int                 num_entries;
-   int                 byte_entries;
-   int                 i;
+   const int    *data = (const int*) ef->data;
+   const char   *start = (const char*) ef->data;
+   int           index = 0;
+   int           num_directory_entries;
+   int           bytes_directory_entries;
+   int           num_dictionary_entries;
+   int           bytes_dictionary_entries;
+   int           i;
 
-   if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
+   index += sizeof(int);
+   if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef))
      return NULL;
+   data++;
 
-   if (eet_test_close(ef->data_size < sizeof(int) * 3, ef))
+#define GET_INT(Value, Pointer, Index)          \
+   {                                            \
+      Value = ntohl(*Pointer);                  \
+      Pointer++;                                \
+      Index += sizeof(int);                     \
+   }
+
+   /* get entries count and byte count */
+   GET_INT(num_directory_entries, data, index);
+   /* get dictionary count and byte count */
+   GET_INT(num_dictionary_entries, data, index);
+
+   bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
+   bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
+
+   /* we cant have <= 0 values here - invalid */
+   if (eet_test_close((num_directory_entries <= 0), ef))
+     return NULL;
+
+   /* we cant have more bytes directory and bytes in dictionaries than the size of the file */
+   if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef))
+     return NULL;
+
+   /* allocate header */
+   ef->header = calloc(1, sizeof(Eet_File_Header));
+   if (eet_test_close(!ef->header, ef))
      return NULL;
 
+   ef->header->magic = EET_MAGIC_FILE_HEADER;
+
+   /* allocate directory block in ram */
+   ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
+   if (eet_test_close(!ef->header->directory, ef))
+     return NULL;
+
+   /* 8 bit hash table (256 buckets) */
+   ef->header->directory->size = 8;
+   /* allocate base hash table */
+   ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
+   if (eet_test_close(!ef->header->directory->nodes, ef))
+     return NULL;
+
+   /* actually read the directory block - all of it, into ram */
+   for (i = 0; i < num_directory_entries; ++i)
+     {
+        const char      *name;
+        Eet_File_Node   *efn;
+        int              name_offset;
+        int              name_size;
+        int              hash;
+
+        /* out directory block is inconsistent - we have oveerun our */
+        /* dynamic block buffer before we finished scanning dir entries */
+        efn = malloc (sizeof(Eet_File_Node));
+        if (eet_test_close(!efn, ef))
+          return NULL;
+
+        /* get entrie header */
+        GET_INT(efn->offset, data, index);
+        GET_INT(efn->size, data, index);
+        GET_INT(efn->data_size, data, index);
+        GET_INT(name_offset, data, index);
+        GET_INT(name_size, data, index);
+        GET_INT(efn->compression, data, index);
+
+#define EFN_TEST(Test, Ef, Efn)                 \
+        if (eet_test_close(Test, Ef))           \
+          {                                     \
+             free(Efn);                         \
+             return NULL;                       \
+          }
+
+        /* check data pointer position */
+        EFN_TEST(!((efn->size > 0)
+                   && (efn->offset + efn->size <= ef->data_size)
+                   && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
+
+        /* check name position */
+        EFN_TEST(!((name_size > 0)
+                   && (name_offset + name_size < ef->data_size)
+                   && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
+
+        name = start + name_offset;
+
+        /* check '\0' at the end of name string */
+        EFN_TEST(name[name_size - 1] != '\0', ef, efn);
+
+        efn->free_name = 0;
+        efn->name = (char*) name;
+        efn->name_size = name_size;
+
+        hash = _eet_hash_gen(efn->name, ef->header->directory->size);
+        efn->next = ef->header->directory->nodes[hash];
+        ef->header->directory->nodes[hash] = efn;
+
+        /* read-only mode, so currently we have no data loaded */
+        if (ef->mode == EET_FILE_MODE_READ)
+          efn->data = NULL;
+        /* read-write mode - read everything into ram */
+        else
+          {
+             efn->data = malloc(efn->size);
+             if (efn->data)
+               memcpy(efn->data, ef->data + efn->offset, efn->size);
+          }
+     }
+
+   ef->ed = NULL;
+
+   if (num_dictionary_entries)
+     {
+        const int       *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT;
+        int              j;
+
+        if (eet_test_close((num_directory_entries * EET_FILE2_DICTIONARY_ENTRY_SIZE + index) > (bytes_dictionary_entries + bytes_directory_entries), ef))
+            return NULL;
+
+        ef->ed = calloc(1, sizeof (Eet_Dictionary));
+        if (eet_test_close(!ef->ed, ef)) return NULL;
+
+        ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
+        if (eet_test_close(!ef->ed->all, ef)) return NULL;
+
+        ef->ed->count = num_dictionary_entries;
+
+        for (j = 0; j < ef->ed->count; ++j)
+          {
+             int   hash;
+             int   offset;
+
+             GET_INT(hash, dico, index);
+             GET_INT(offset, dico, index);
+             GET_INT(ef->ed->all[j].len, dico, index);
+             GET_INT(ef->ed->all[j].prev, dico, index);
+             GET_INT(ef->ed->all[j].next, dico, index);
+
+             /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
+                So stick to int and check the value. */
+             if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL;
+
+             /* Check string position */
+             if (eet_test_close(!((ef->ed->all[j].len > 0)
+                                  && (offset > (bytes_dictionary_entries + bytes_directory_entries))
+                                  && (offset + ef->ed->all[j].len < ef->data_size)), ef))
+               return NULL;
+
+             ef->ed->all[j].mmap = start + offset;
+             ef->ed->all[j].str = NULL;
+
+             /* Check '\0' at the end of the string */
+             if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL;
+
+             if (ef->ed->all[j].prev == -1)
+               ef->ed->hash[hash] = j;
+          }
+     }
+
+   return ef;
+}
+
+static Eet_File*
+eet_internal_read1(Eet_File *ef)
+{
+   const unsigned char *dyn_buf = NULL;
+   const unsigned char *p = NULL;
+   int                  index = 0;
+   int                  num_entries;
+   int                  byte_entries;
+   int                  i;
+
    /* build header table if read mode */
    /* geat header */
    index += sizeof(int);
@@ -496,6 +886,10 @@ eet_internal_read(Eet_File *ef)
    if (eet_test_close((num_entries * 20) > byte_entries, ef))
      return NULL;
 
+   /* check we will not outrun the file limit */
+   if (eet_test_close(((byte_entries + sizeof(int) * 3) > ef->data_size), ef))
+     return NULL;
+
    /* allocate header */
    ef->header = calloc(1, sizeof(Eet_File_Header));
    if (eet_test_close(!ef->header, ef))
@@ -542,13 +936,15 @@ eet_internal_read(Eet_File *ef)
        if (eet_test_close(!efn, ef))
          return NULL;
 
-       /* get entrie header */
+        /* get entrie header */
        EXTRACT_INT(efn->offset, p, indexn);
        EXTRACT_INT(efn->compression, p, indexn);
        EXTRACT_INT(efn->size, p, indexn);
        EXTRACT_INT(efn->data_size, p, indexn);
        EXTRACT_INT(name_size, p, indexn);
 
+        efn->name_size = name_size;
+
        /* invalid size */
        if (eet_test_close(efn->size <= 0, ef))
          {
@@ -616,6 +1012,32 @@ eet_internal_read(Eet_File *ef)
    return ef;
 }
 
+static Eet_File*
+eet_internal_read(Eet_File *ef)
+{
+   const int    *data = (const int*) ef->data;
+
+   if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
+     return NULL;
+
+   if (eet_test_close(ef->data_size < sizeof(int) * 3, ef))
+     return NULL;
+
+   switch (ntohl(*data))
+     {
+      case EET_MAGIC_FILE:
+         return eet_internal_read1(ef);
+      case EET_MAGIC_FILE2:
+         return eet_internal_read2(ef);
+      default:
+         ef->delete_me_now = 1;
+         eet_close(ef);
+         break;
+     }
+
+   return NULL;
+}
+
 EAPI Eet_File *
 eet_memopen_read(const void *data, size_t size)
 {
@@ -628,6 +1050,7 @@ eet_memopen_read(const void *data, size_t size)
    if (!ef)
      return NULL;
 
+   ef->ed = NULL;
    ef->path = NULL;
    ef->magic = EET_MAGIC_FILE;
    ef->references = 1;
@@ -663,7 +1086,7 @@ eet_open(const char *file, Eet_File_Mode mode)
        ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
        if (ef)
          {
-            eet_flush(ef);
+            eet_flush2(ef);
             ef->delete_me_now = 1;
             eet_close(ef);
          }
@@ -741,6 +1164,9 @@ eet_open(const char *file, Eet_File_Mode mode)
    ef->data = NULL;
    ef->data_size = 0;
 
+   /* FIXME: Add new ed on EET_FILE_MODE_WRITE */
+   ef->ed = mode == EET_FILE_MODE_WRITE ? eet_dictionary_add() : NULL;
+
    /* if we can't open - bail out */
    if (eet_test_close(!ef->fp, ef))
      return NULL;
@@ -805,6 +1231,17 @@ eet_open(const char *file, Eet_File_Mode mode)
                    }
               }
          }
+
+        if (ef->ed)
+          {
+             for (i = 0; i < ef->ed->count; ++i)
+               if (ef->ed->all[i].mmap)
+                 {
+                    ef->ed->all[i].str = strdup(ef->ed->all[i].mmap);
+                    ef->ed->all[i].mmap = NULL;
+                 }
+          }
+
        fclose(ef->fp);
        unlink(ef->path);
        ef->fp = fopen(ef->path, "wb");
@@ -846,7 +1283,7 @@ eet_close(Eet_File *ef)
    /* if its still referenced - dont go any further */
    if (ef->references > 0) return EET_ERROR_NONE;
    /* flush any writes */
-   err = eet_flush(ef);
+   err = eet_flush2(ef);
 
    /* if not urgent to delete it - dont free it - leave it in cache */
    if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
@@ -892,6 +1329,8 @@ eet_close(Eet_File *ef)
        free(ef->header);
      }
 
+   eet_dictionary_free(ef->ed);
+
 #ifndef _WIN32
    if (ef->data) munmap((void*)ef->data, ef->data_size);
 #else
@@ -1156,7 +1595,9 @@ eet_write(Eet_File *ef, const char *name, const void *data, int size, int compre
             return 0;
          }
        efn->name = strdup(name);
-       efn->free_name = 1;
+        efn->name_size = strlen(efn->name) + 1;
+        efn->free_name = 1;
+
        efn->next = ef->header->directory->nodes[hash];
        ef->header->directory->nodes[hash] = efn;
        efn->offset = 0;
@@ -1210,6 +1651,8 @@ eet_delete(Eet_File *ef, const char *name)
               ef->header->directory->nodes[hash] = efn->next;
             else
               pefn->next = efn->next;
+
+             if (efn->free_name) free(efn->name);
             free(efn);
             exists_already = 1;
             break;
@@ -1223,6 +1666,15 @@ eet_delete(Eet_File *ef, const char *name)
    return exists_already;
 }
 
+EAPI Eet_Dictionary*
+eet_dictionary_get(Eet_File *ef)
+{
+   if (eet_check_pointer(ef)) return NULL;
+
+   return ef->ed;
+}
+
+
 EAPI char **
 eet_list(Eet_File *ef, const char *glob, int *count_ret)
 {
index 78c28fa..64fe3e9 100644 (file)
@@ -1,5 +1,7 @@
-#include "Eet_private.h"
+#define _GNU_SOURCE
+
 #include "Eet.h"
+#include "Eet_private.h"
 
 FILE *
 _eet_memfile_read_open(const void *data, size_t size)