and lo-and-behold. eet gets faster! a lot faster for data chunk decoding
authorraster <raster>
Thu, 26 May 2005 03:57:57 +0000 (03:57 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 26 May 2005 03:57:57 +0000 (03:57 +0000)
(used by edje and ecore_config and e_config) and just general eet archive
opening times...

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/libs/eet@14943 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Eet_private.h
src/lib/eet_data.c
src/lib/eet_lib.c

index 81c64d1..adde2ed 100644 (file)
@@ -34,7 +34,7 @@ void  _eet_memfile_write_close(FILE *f);
 void  _eet_memfile_shutdown();
 
 #ifndef PATH_MAX
-#define PATH_MAX 4095
+#define PATH_MAX 4096
 #endif
 
 #endif
index 7c6ec7a..1d3a0b7 100644 (file)
@@ -45,6 +45,7 @@ typedef struct _Eet_Data_Element            Eet_Data_Element;
 typedef struct _Eet_Data_Basic_Type_Decoder Eet_Data_Basic_Type_Decoder;
 typedef struct _Eet_Data_Chunk              Eet_Data_Chunk;
 typedef struct _Eet_Data_Stream             Eet_Data_Stream;
+typedef struct _Eet_Data_Descriptor_Hash    Eet_Data_Descriptor_Hash;
 
 /*---*/
 
@@ -69,6 +70,12 @@ struct _Eet_Data_Stream
    int   pos;
 };
 
+struct _Eet_Data_Descriptor_Hash
+{
+   Eet_Data_Element         *element;
+   Eet_Data_Descriptor_Hash *next;
+};
+
 struct _Eet_Data_Descriptor
 {
    char *name;
@@ -85,6 +92,10 @@ struct _Eet_Data_Descriptor
    struct {
       int               num;
       Eet_Data_Element *set;
+      struct {
+        int                       size;
+        Eet_Data_Descriptor_Hash *buckets;
+      } hash;
    } elements;
 };
 
@@ -567,6 +578,107 @@ eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
 
 /*---*/
 
+static int
+_eet_descriptor_hash_gen(char *key, int hash_size)
+{
+   int hash_num = 0, i;
+   unsigned char *ptr;
+   const int masks[9] =
+     {
+       0x00,
+         0x01,
+         0x03,
+         0x07,
+         0x0f,
+         0x1f,
+         0x3f,
+         0x7f,
+         0xff
+     };
+   
+   /* no string - index 0 */
+   if (!key) return 0;
+
+   /* calc hash num */
+   for (i = 0, ptr = (unsigned char *)key; *ptr; ptr++, i++)
+     hash_num ^= ((int)(*ptr) | ((int)(*ptr) << 8)) >> (i % 8);
+
+   /* mask it */
+   hash_num &= masks[hash_size];
+   /* return it */
+   return hash_num;
+}
+
+static void
+_eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
+{
+   int i;
+   
+   edd->elements.hash.size = 1 << 6;
+   edd->elements.hash.buckets = calloc(1, sizeof(Eet_Data_Descriptor_Hash) * edd->elements.hash.size);
+   for (i = 0; i < edd->elements.num; i++)
+     {
+       Eet_Data_Element *ede;
+       int hash;
+       
+       ede = &(edd->elements.set[i]);
+       hash = _eet_descriptor_hash_gen(ede->name, 6);
+       if (!edd->elements.hash.buckets[hash].element)
+         edd->elements.hash.buckets[hash].element = ede;
+       else
+         {
+            Eet_Data_Descriptor_Hash *bucket;
+            
+            bucket = calloc(1, sizeof(Eet_Data_Descriptor_Hash));
+            bucket->element = ede;
+            bucket->next = edd->elements.hash.buckets[hash].next;
+            edd->elements.hash.buckets[hash].next = bucket;
+         }
+     }
+}
+
+static void
+_eet_descriptor_hash_free(Eet_Data_Descriptor *edd)
+{
+   int i;
+   
+   for (i = 0; i < edd->elements.hash.size; i++)
+     {
+       Eet_Data_Descriptor_Hash *bucket, *pbucket;
+       
+       bucket = edd->elements.hash.buckets[i].next;
+       while (bucket)
+         {
+            pbucket = bucket;
+            bucket = bucket->next;
+            free(pbucket);
+         }
+     }
+   if (edd->elements.hash.buckets) free(edd->elements.hash.buckets);
+}
+
+static Eet_Data_Element *
+_eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name)
+{
+   int hash;
+   Eet_Data_Element *ede;
+   Eet_Data_Descriptor_Hash *bucket;
+   
+   hash = _eet_descriptor_hash_gen(name, 6);
+   if (!edd->elements.hash.buckets[hash].element) return NULL;
+   if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
+     return edd->elements.hash.buckets[hash].element;
+   bucket = edd->elements.hash.buckets[hash].next;
+   while (bucket)
+     {
+       if (!strcmp(bucket->element->name, name)) return bucket->element;
+       bucket = bucket->next;
+     }
+   return NULL;
+}
+
+/*---*/
+
 Eet_Data_Descriptor *
 eet_data_descriptor_new(char *name,
                        int size,
@@ -599,6 +711,7 @@ eet_data_descriptor_free(Eet_Data_Descriptor *edd)
 {
    int i;
 
+   _eet_descriptor_hash_free(edd);
    if (edd->name) free(edd->name);
    for (i = 0; i < edd->elements.num; i++)
      {
@@ -811,10 +924,11 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
      }
    p = chnk->data;
    size = size_in - (4 + 4 + strlen(chnk->name) + 1);
+   if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
    while (size > 0)
      {
        Eet_Data_Chunk *echnk;
-       int i;
+       Eet_Data_Element *ede;
 
        /* get next data chunk */
        echnk = eet_data_chunk_get(p, size);
@@ -827,88 +941,77 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
             eet_data_chunk_free(chnk);
             return NULL;
          }
-       for (i = 0; i < edd->elements.num; i++)
+       /* FIXME: this is a linear search/match - speed up by putting in a
+        * hash lookup
+        */
+       ede = _eet_descriptor_hash_find(edd, echnk->name);
+       if (ede)
          {
-            Eet_Data_Element *ede;
-
-            ede = &(edd->elements.set[i]);
-            if (!strcmp(echnk->name, ede->name))
+            if (ede->group_type == EET_G_UNKNOWN)
               {
-                 if (ede->group_type == EET_G_UNKNOWN)
+                 int ret;
+                 void *data_ret;
+                 
+                 if ((ede->type >= EET_T_CHAR) &&
+                     (ede->type <= EET_T_STRING))
                    {
-                      int ret;
-                      void *data_ret;
-
-                      if ((ede->type >= EET_T_CHAR) &&
-                          (ede->type <= EET_T_STRING))
+                      ret = eet_data_get_type(ede->type,
+                                              echnk->data,
+                                              ((char *)echnk->data) + echnk->size,
+                                              ((char *)data) + ede->offset);
+                   }
+                 else if (ede->subtype)
+                   {
+                      void **ptr;
+                      
+                      data_ret = eet_data_descriptor_decode(ede->subtype,
+                                                            echnk->data,
+                                                            echnk->size);
+                      if (!data_ret)
                         {
-                           ret = eet_data_get_type(ede->type,
-                                                   echnk->data,
-                                                   ((char *)echnk->data) + echnk->size,
-                                                   ((char *)data) + ede->offset);
-                        }
-                      else if (ede->subtype)
-                        {
-                           void **ptr;
-
-                           data_ret = eet_data_descriptor_decode(ede->subtype,
-                                                                 echnk->data,
-                                                                 echnk->size);
-                           if (!data_ret)
-                             {
-                                _eet_freelist_unref();
-                                _eet_freelist_list_unref();
-                                _eet_freelist_free();
-                                _eet_freelist_list_free(edd);
-                                eet_data_chunk_free(chnk);
-                                return NULL;
-                             }
-                           ptr = (void **)(((char *)data) + ede->offset);
-                           *ptr = (void *)data_ret;
+                           _eet_freelist_unref();
+                           _eet_freelist_list_unref();
+                           _eet_freelist_free();
+                           _eet_freelist_list_free(edd);
+                           eet_data_chunk_free(chnk);
+                           return NULL;
                         }
+                      ptr = (void **)(((char *)data) + ede->offset);
+                      *ptr = (void *)data_ret;
                    }
-                 else
+              }
+            else
+              {
+                 switch (ede->group_type)
                    {
-                      switch (ede->group_type)
+                    case EET_G_ARRAY:
+                    case EET_G_VAR_ARRAY:
                         {
-                         case EET_G_ARRAY:
-                         case EET_G_VAR_ARRAY:
-                             {
-                                printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n");
-                             }
-                           break;
-                         case EET_G_LIST:
+                           printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n");
+                        }
+                      break;
+                    case EET_G_LIST:
+                        {
+                           int ret;
+                           void *list = NULL;
+                           void **ptr;
+                           void *data_ret;
+                           
+                           ptr = (void **)(((char *)data) + ede->offset);
+                           list = *ptr;
+                           data_ret = NULL;
+                           if ((ede->type >= EET_T_CHAR) &&
+                               (ede->type <= EET_T_STRING))
                              {
-                                int ret;
-                                void *list = NULL;
-                                void **ptr;
-                                void *data_ret;
-
-                                ptr = (void **)(((char *)data) + ede->offset);
-                                list = *ptr;
-                                data_ret = NULL;
-                                if ((ede->type >= EET_T_CHAR) &&
-                                    (ede->type <= EET_T_STRING))
+                                data_ret = calloc(1, eet_coder[ede->type].size);
+                                if (data_ret)
                                   {
-                                     data_ret = calloc(1, eet_coder[ede->type].size);
-                                     if (data_ret)
-                                       {
-                                          _eet_freelist_add(data_ret);
-                                          ret = eet_data_get_type(ede->type,
-                                                                  echnk->data,
-                                                                  ((char *)echnk->data) + echnk->size,
-                                                                  data_ret);
-                                          if (ret <= 0)
-                                            {
-                                               _eet_freelist_unref();
-                                               _eet_freelist_list_unref();
-                                               _eet_freelist_free();
-                                               _eet_freelist_list_free(edd);
-                                               eet_data_chunk_free(chnk);
-                                               return NULL;
-                                            }
-                                       }
-                                     else
+                                     _eet_freelist_add(data_ret);
+                                     ret = eet_data_get_type(ede->type,
+                                                             echnk->data,
+                                                             ((char *)echnk->data) + echnk->size,
+                                                             data_ret);
+                                     if (ret <= 0)
                                        {
                                           _eet_freelist_unref();
                                           _eet_freelist_list_unref();
@@ -918,18 +1021,6 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                           return NULL;
                                        }
                                   }
-                                else if (ede->subtype)
-                                  {
-                                     data_ret = eet_data_descriptor_decode(ede->subtype,
-                                                                           echnk->data,
-                                                                           echnk->size);
-                                  }
-                                if (data_ret)
-                                  {
-                                     list = edd->func.list_append(list, data_ret);
-                                     *ptr = list;
-                                     _eet_freelist_list_add(ptr);
-                                  }
                                 else
                                   {
                                      _eet_freelist_unref();
@@ -940,15 +1031,35 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
                                      return NULL;
                                   }
                              }
-                           break;
-                         case EET_G_HASH:
-                           printf("HASH TYPE NOT IMPLIMENTED YET!!!\n");
-                           break;
-                         default:
-                           break;
+                           else if (ede->subtype)
+                             {
+                                data_ret = eet_data_descriptor_decode(ede->subtype,
+                                                                      echnk->data,
+                                                                      echnk->size);
+                             }
+                           if (data_ret)
+                             {
+                                list = edd->func.list_append(list, data_ret);
+                                *ptr = list;
+                                _eet_freelist_list_add(ptr);
+                             }
+                           else
+                             {
+                                _eet_freelist_unref();
+                                _eet_freelist_list_unref();
+                                _eet_freelist_free();
+                                _eet_freelist_list_free(edd);
+                                eet_data_chunk_free(chnk);
+                                return NULL;
+                             }
                         }
+                      break;
+                    case EET_G_HASH:
+                      printf("HASH TYPE NOT IMPLIMENTED YET!!!\n");
+                      break;
+                    default:
+                      break;
                    }
-                 break;
               }
          }
        /* advance to next chunk */
index 6fab64f..19cd576 100644 (file)
 
 #define EET_MAGIC_FILE                  0x1ee7ff00
 #define EET_MAGIC_FILE_HEADER           0x1ee7ff01
-#define EET_MAGIC_FILE_NODE             0x1ee7ff02
-#define EET_MAGIC_FILE_DIRECTORY        0x1ee7ff03
-#define EET_MAGIC_FILE_DIRECTORY_HASH   0x1ee7ff04
 
 typedef struct _Eet_File_Header         Eet_File_Header;
 typedef struct _Eet_File_Node           Eet_File_Node;
 typedef struct _Eet_File_Directory      Eet_File_Directory;
-typedef struct _Eet_File_Directory_Hash Eet_File_Directory_Hash;
 
 struct _Eet_File
 {
@@ -42,26 +38,21 @@ struct _Eet_File_Header
    Eet_File_Directory *directory;
 };
 
-struct _Eet_File_Node
-{
-   char *name;
-   int   offset;
-   int   compression;
-   int   size;
-   int   data_size;
-   void *data;
-};
-
 struct _Eet_File_Directory
 {
-   int                       size;
-   Eet_File_Directory_Hash  *hash;
+   int             size;
+   Eet_File_Node **nodes;
 };
 
-struct _Eet_File_Directory_Hash
+struct _Eet_File_Node
 {
+   char          *name;
+   int            offset;
+   int            compression;
    int            size;
-   Eet_File_Node *node;
+   int            data_size;
+   void          *data;
+   Eet_File_Node *next; /* FIXME: make buckets linked lists */
 };
 
 #if 0
@@ -200,7 +191,7 @@ eet_string_match(char *s1, char *s2)
 static int
 eet_hash_gen(char *key, int hash_size)
 {
-   int hash_num = 0;
+   int hash_num = 0, i;
    unsigned char *ptr;
    const int masks[9] =
      {
@@ -219,8 +210,8 @@ eet_hash_gen(char *key, int hash_size)
    if (!key) return 0;
 
    /* calc hash num */
-   for (ptr = (unsigned char *)key; *ptr; ptr++)
-     hash_num ^= (int)(*ptr);
+   for (i = 0, ptr = (unsigned char *)key; *ptr; ptr++, i++)
+     hash_num ^= ((int)(*ptr) | ((int)(*ptr) << 8)) >> (i % 8);
 
    /* mask it */
    hash_num &= masks[hash_size];
@@ -232,9 +223,10 @@ eet_hash_gen(char *key, int hash_size)
 static void
 eet_flush(Eet_File *ef)
 {
-   int i, j, count, size, num, offset;
+   int i, count, size, num, offset;
    int head[3];
    unsigned long int i1, i2;
+   Eet_File_Node *efn;
 
    /* check to see its' an eet file pointer */
    if ((!ef) || (ef->magic != EET_MAGIC_FILE))
@@ -250,11 +242,11 @@ eet_flush(Eet_File *ef)
    num = (1 << (ef->header->directory->size - 1));
    for (i = 0; i < num; i++)
      {
-       for (j = 0; j < ef->header->directory->hash[i].size; j++)
+       for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
          {
-            if (ef->header->directory->hash[i].node[j].compression >= 0)
+            if (efn->compression >= 0)
               {
-                 size += 20 + strlen(ef->header->directory->hash[i].node[j].name);
+                 size += 20 + strlen(efn->name);
                  count++;
               }
          }
@@ -263,12 +255,12 @@ eet_flush(Eet_File *ef)
    offset = 0;
    for (i = 0; i < num; i++)
      {
-       for (j = 0; j < ef->header->directory->hash[i].size; j++)
+       for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
          {
-             if (ef->header->directory->hash[i].node[j].compression >= 0)
+            if (efn->compression >= 0)
               {
-                 ef->header->directory->hash[i].node[j].offset = 12 + size + offset;
-                 offset += ef->header->directory->hash[i].node[j].size;
+                 efn->offset = 12 + size + offset;
+                 offset += efn->size;
               }
          }
      }
@@ -287,34 +279,34 @@ eet_flush(Eet_File *ef)
    offset = 12;
    for (i = 0; i < num; i++)
      {
-       for (j = 0; j < ef->header->directory->hash[i].size; j++)
+       for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
          {
             unsigned char *buf;
             int buf_size;
             int name_size;
 
-            if (ef->header->directory->hash[i].node[j].compression >= 0)
+            if (efn->compression >= 0)
               {
-                 name_size = strlen(ef->header->directory->hash[i].node[j].name);
+                 name_size = strlen(efn->name);
                  buf_size = 20 + name_size;
                  buf = malloc(buf_size);
                  if (!buf) return;
-                 i1 = (unsigned long int)ef->header->directory->hash[i].node[j].offset;
+                 i1 = (unsigned long int)efn->offset;
                  i2 = htonl(i1);
                  *((int *)(buf + 0)) = (int)i2;
-                 i1 = (unsigned long int)ef->header->directory->hash[i].node[j].compression;
+                 i1 = (unsigned long int)efn->compression;
                  i2 = htonl(i1);
                  *((int *)(buf + 4)) = (int)i2;
-                 i1 = (unsigned long int)ef->header->directory->hash[i].node[j].size;
+                 i1 = (unsigned long int)efn->size;
                  i2 = htonl(i1);
                  *((int *)(buf + 8)) = (int)i2;
-                 i1 = (unsigned long int)ef->header->directory->hash[i].node[j].data_size;
+                 i1 = (unsigned long int)efn->data_size;
                  i2 = htonl(i1);
                  *((int *)(buf + 12)) = (int)i2;
                  i1 = (unsigned long int)name_size;
                  i2 = htonl(i1);
                  *((int *)(buf + 16)) = (int)i2;
-                 memcpy(buf + 20, ef->header->directory->hash[i].node[j].name, name_size);
+                 memcpy(buf + 20, efn->name, name_size);
                  if (fwrite(buf, buf_size, 1, ef->fp) != 1)
                    {
                       free(buf);
@@ -328,13 +320,11 @@ eet_flush(Eet_File *ef)
    /* write data */
    for (i = 0; i < num; i++)
      {
-       for (j = 0; j < ef->header->directory->hash[i].size; j++)
+       for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
          {
-            if (ef->header->directory->hash[i].node[j].compression >= 0)
+            if (efn->compression >= 0)
               {
-                 if (fwrite(ef->header->directory->hash[i].node[j].data,
-                            ef->header->directory->hash[i].node[j].size,
-                            1, ef->fp) != 1)
+                 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
                    return;
               }
          }
@@ -378,7 +368,7 @@ eet_open(const char *file, Eet_File_Mode mode)
      }
 
    /* allocate struct for eet file and have it zero'd out */
-   ef = calloc(sizeof(Eet_File), 1);
+   ef = calloc(1, sizeof(Eet_File));
    if (!ef) return NULL;
 
    /* fill some of the members */
@@ -411,6 +401,7 @@ eet_open(const char *file, Eet_File_Mode mode)
      }
 
    /* if we opened for read or read-write */
+//   printf("OPEN!\n");
    if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
      {
        unsigned char buf[12];
@@ -462,7 +453,7 @@ eet_open(const char *file, Eet_File_Mode mode)
             return NULL;
          }
        /* allocate header */
-       ef->header = calloc(sizeof(Eet_File_Header), 1);
+       ef->header = calloc(1, sizeof(Eet_File_Header));
        if (!ef->header)
          {
             free(dyn_buf);
@@ -471,7 +462,7 @@ eet_open(const char *file, Eet_File_Mode mode)
          }
        ef->header->magic = EET_MAGIC_FILE_HEADER;
        /* allocate directory block in ram */
-       ef->header->directory = calloc(sizeof(Eet_File_Directory), 1);
+       ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
        if (!ef->header->directory)
          {
             free(dyn_buf);
@@ -481,8 +472,8 @@ eet_open(const char *file, Eet_File_Mode mode)
        /* 8 bit hash table (256 buckets) */
        ef->header->directory->size = 8;
        /* allocate base hash table */
-       ef->header->directory->hash = calloc(sizeof(Eet_File_Directory_Hash), (1 << (ef->header->directory->size - 1)));
-       if (!ef->header->directory->hash)
+       ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
+       if (!ef->header->directory->nodes)
          {
             free(dyn_buf);
             eet_close(ef);
@@ -498,6 +489,7 @@ eet_open(const char *file, Eet_File_Mode mode)
          }
        /* parse directory block */
        p = dyn_buf;
+//     printf("entries: %i\n", num_entries);
        for (i = 0; i < num_entries; i++)
          {
             int offset;
@@ -507,8 +499,7 @@ eet_open(const char *file, Eet_File_Mode mode)
             int name_size;
             char *name;
             int hash;
-            Eet_File_Node *node;
-            int node_size;
+            Eet_File_Node *efn;
             void *data = NULL;
 
             /* out directory block is inconsistent - we have oveerun our */
@@ -569,39 +560,31 @@ eet_open(const char *file, Eet_File_Mode mode)
             name[name_size] = 0;
             /* get hask bucket it should go in */
             hash = eet_hash_gen(name, ef->header->directory->size);
-            /* resize hask bucket */
-            node = realloc(ef->header->directory->hash[hash].node,
-                           (ef->header->directory->hash[hash].size  + 1) *
-                           sizeof(Eet_File_Node));
-            if (!node)
+            efn = calloc(1, sizeof(Eet_File_Node));
+            if (!efn)
               {
                  free(dyn_buf);
                  eet_close(ef);
                  return NULL;
               }
-            /* current node size */
-            node_size = ef->header->directory->hash[hash].size;
-            /* resized node list set up */
-            ef->header->directory->hash[hash].node = node;
-            /* new node at end */
-            ef->header->directory->hash[hash].node[node_size].name = name;
-            ef->header->directory->hash[hash].node[node_size].offset = offset;
-            ef->header->directory->hash[hash].node[node_size].compression = flags;
-            ef->header->directory->hash[hash].node[node_size].size = size;
-            ef->header->directory->hash[hash].node[node_size].data_size = data_size;
+            efn->next = ef->header->directory->nodes[hash];
+            ef->header->directory->nodes[hash] = efn;
+            efn->name = name;
+            efn->offset = offset;
+            efn->compression = flags;
+            efn->size = size;
+            efn->data_size = data_size;
 
             /* read-only mode, so currently we have no data loaded */
             if (mode == EET_FILE_MODE_READ)
-              {
-                 ef->header->directory->hash[hash].node[node_size].data = NULL;
-              }
+              efn->data = NULL;
             /* read-write mode - read everything into ram */
             else
               {
                  data = malloc(size);
                  if (data)
                    {
-                      if (fseek(ef->fp, ef->header->directory->hash[hash].node[node_size].offset, SEEK_SET) < 0)
+                      if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
                         {
                            free(data);
                            data = NULL;
@@ -616,12 +599,9 @@ eet_open(const char *file, Eet_File_Mode mode)
                            break;
                         }
                    }
-
-                  ef->header->directory->hash[hash].node[node_size].data = data;
+                  efn->data = data;
               }
 
-            /* increment number of nodes */
-            ef->header->directory->hash[hash].size++;
             /* advance */
             p += 20 + name_size;
          }
@@ -683,30 +663,24 @@ eet_close(Eet_File *ef)
      {
        if (ef->header->directory)
          {
-            if (ef->header->directory->hash)
+            if (ef->header->directory->nodes)
               {
                  int i, num;
 
-                 num = (1 << (ef->header->directory->size - 1));
+                 num = (1 << ef->header->directory->size);
                  for (i = 0; i < num; i++)
                    {
-                      if (ef->header->directory->hash[i].node)
+                      Eet_File_Node *efn;
+                      
+                      while ((efn = ef->header->directory->nodes[i]))
                         {
-                           int j;
-                           int num2;
-
-                           num2 = ef->header->directory->hash[i].size;
-                           for (j = 0; j < num2; j++)
-                             {
-                                if (ef->header->directory->hash[i].node[j].name)
-                                  free(ef->header->directory->hash[i].node[j].name);
-                                if (ef->header->directory->hash[i].node[j].data)
-                                  free(ef->header->directory->hash[i].node[j].data);
-                             }
-                           free(ef->header->directory->hash[i].node);
+                           if (efn->name) free(efn->name);
+                           if (efn->data) free(efn->data);
+                           ef->header->directory->nodes[i] = efn->next;
+                           free(efn);
                         }
                    }
-                 free(ef->header->directory->hash);
+                 free(ef->header->directory->nodes);
               }
             free(ef->header->directory);
          }
@@ -723,9 +697,10 @@ void *
 eet_read(Eet_File *ef, char *name, int *size_ret)
 {
    void *data = NULL;
-   int   size = 0, tmp_size;
-   int   hash, i, num;
-
+   int size = 0, tmp_size;
+   int hash;
+   Eet_File_Node *efn;
+   
    /* check to see its' an eet file pointer */
    if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) ||
        ((ef->mode != EET_FILE_MODE_READ) &&
@@ -742,31 +717,28 @@ eet_read(Eet_File *ef, char *name, int *size_ret)
    hash = eet_hash_gen(name, ef->header->directory->size);
 //   printf("read %s\n", name);
    /* hunt hash bucket */
-   num = ef->header->directory->hash[hash].size;
-   for (i = 0; i < num; i++)
+   for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
      {
        /* if it matches */
-       if (eet_string_match(ef->header->directory->hash[hash].node[i].name, name))
+       if (eet_string_match(efn->name, name))
          {
             /* uncompressed data */
-            if (ef->header->directory->hash[hash].node[i].compression == 0)
+            if (efn->compression == 0)
               {
                  /* get size */
-                 size = ef->header->directory->hash[hash].node[i].size;
+                 size = efn->size;
                  /* allocate data */
                  data = malloc(size);
                  if (data)
                    {
                       /* if we alreayd have the data in ram... copy that */
-                      if (ef->header->directory->hash[hash].node[i].data)
-                        memcpy(data,
-                               ef->header->directory->hash[hash].node[i].data,
-                               ef->header->directory->hash[hash].node[i].size);
+                      if (efn->data)
+                        memcpy(data, efn->data, efn->size);
                       /* or get data from disk */
                       else
                         {
                            /* seek to data location */
-                           if (fseek(ef->fp, ef->header->directory->hash[hash].node[i].offset, SEEK_SET) < 0)
+                           if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
                              {
                                 free(data);
                                 data = NULL;
@@ -789,11 +761,11 @@ eet_read(Eet_File *ef, char *name, int *size_ret)
                  void *tmp_data;
 
                  /* get size of data in file */
-                 tmp_size = ef->header->directory->hash[hash].node[i].size;
+                 tmp_size = efn->size;
                  tmp_data = malloc(tmp_size);
                  if (!tmp_data) break;
                  /* get size uncompressed */
-                 size = ef->header->directory->hash[hash].node[i].data_size;
+                 size = efn->data_size;
                  /* allocate data */
                  data = malloc(size);
                  if (data)
@@ -801,15 +773,13 @@ eet_read(Eet_File *ef, char *name, int *size_ret)
                       uLongf dlen;
 
                       /* if we already have the data in ram... copy that */
-                      if (ef->header->directory->hash[hash].node[i].data)
-                        memcpy(tmp_data,
-                               ef->header->directory->hash[hash].node[i].data,
-                               tmp_size);
+                      if (efn->data)
+                        memcpy(tmp_data, efn->data, tmp_size);
                       /* or get data from disk */
                       else
                         {
                            /* seek to data location */
-                           if (fseek(ef->fp, ef->header->directory->hash[hash].node[i].offset, SEEK_SET) < 0)
+                           if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
                              {
                                 free(tmp_data);
                                 free(data);
@@ -851,38 +821,35 @@ int
 eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
 {
    int data_size;
-   int hash, node_size;
-   Eet_File_Node *node;
+   int hash;
+   Eet_File_Node *efn;
    char *name2;
    void *data2;
    int exists_already = 0;
 
    /* check to see its' an eet file pointer */
-   if ((!ef) || (ef->magic != EET_MAGIC_FILE)
-       || (!name) || (!data) || (size <= 0) ||
-       ((ef->mode != EET_FILE_MODE_WRITE) &&
-        (ef->mode != EET_FILE_MODE_READ_WRITE)))
-
+   if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) || (!data) || 
+       (size <= 0) || ((ef->mode != EET_FILE_MODE_WRITE) &&
+                      (ef->mode != EET_FILE_MODE_READ_WRITE)))
      return 0;
 
    if (!ef->header)
      {
        /* allocate header */
-       ef->header = calloc(sizeof(Eet_File_Header), 1);
+       ef->header = calloc(1, sizeof(Eet_File_Header));
        if (!ef->header) return 0;
        ef->header->magic = EET_MAGIC_FILE_HEADER;
        /* allocate directory block in ram */
-       ef->header->directory = calloc(sizeof(Eet_File_Directory), 1);
+       ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
        if (!ef->header->directory) return 0;
        /* 8 bit hash table (256 buckets) */
        ef->header->directory->size = 8;
        /* allocate base hash table */
-       ef->header->directory->hash = calloc(sizeof(Eet_File_Directory_Hash), (1 << (ef->header->directory->size - 1)));
-       if (!ef->header->directory->hash) return 0;
+       ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
+       if (!ef->header->directory->nodes) return 0;
      }
    /* figure hash bucket */
    hash = eet_hash_gen(name, ef->header->directory->size);
-   node_size = ef->header->directory->hash[hash].size;
    /* dup name */
    name2 = strdup(name);
    if (!name2) return 0;
@@ -933,17 +900,16 @@ eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
    /* Does this node already exist? */
    if (ef->mode == EET_FILE_MODE_READ_WRITE)
      {
-       int i;
-       for (i = 0; i < node_size; i++)
+       for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
          {
             /* if it matches */
-            if (eet_string_match(ef->header->directory->hash[hash].node[i].name, name))
+            if (eet_string_match(efn->name, name))
               {
-                 free(ef->header->directory->hash[hash].node[i].data);
-                 ef->header->directory->hash[hash].node[i].compression = compress;
-                 ef->header->directory->hash[hash].node[i].size = data_size;
-                 ef->header->directory->hash[hash].node[i].data_size = size;
-                 ef->header->directory->hash[hash].node[i].data = data2;
+                 free(efn->data);
+                 efn->compression = compress;
+                 efn->size = data_size;
+                 efn->data_size = size;
+                 efn->data = data2;
                  exists_already = 1;
                  free(name2);
                  break;
@@ -952,25 +918,23 @@ eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
      }
    if (!exists_already)
      {
-       /* increase hash bucket size */
-       node = realloc(ef->header->directory->hash[hash].node,
-                      (node_size  + 1) * sizeof(Eet_File_Node));
-       if (!node)
+       efn = calloc(1, sizeof(Eet_File_Node));
+       if (!efn)
          {
             free(name2);
             free(data2);
             return 0;
          }
        /* resized node list set up */
-       ef->header->directory->hash[hash].node = node;
+       efn->next = ef->header->directory->nodes[hash];
+       ef->header->directory->nodes[hash] = efn;
        /* new node at end */
-       ef->header->directory->hash[hash].node[node_size].name = name2;
-       ef->header->directory->hash[hash].node[node_size].offset = 0;
-       ef->header->directory->hash[hash].node[node_size].compression = compress;
-       ef->header->directory->hash[hash].node[node_size].size = data_size;
-       ef->header->directory->hash[hash].node[node_size].data_size = size;
-       ef->header->directory->hash[hash].node[node_size].data = data2;
-       ef->header->directory->hash[hash].size++;
+       efn->name = name2;
+       efn->offset = 0;
+       efn->compression = compress;
+       efn->size = data_size;
+       efn->data_size = size;
+       efn->data = data2;
      }
 
    /* flags that writes are pending */
@@ -982,9 +946,10 @@ eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
 int
 eet_delete(Eet_File *ef, char *name)
 {
-   int hash, node_size, i;
+   int hash;
    int exists_already = 0;
-
+   Eet_File_Node *efn, *pefn;
+   
    /* check to see its' an eet file pointer */
    if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name))
      return 0;
@@ -996,19 +961,20 @@ eet_delete(Eet_File *ef, char *name)
 
    /* figure hash bucket */
    hash = eet_hash_gen(name, ef->header->directory->size);
-   node_size = ef->header->directory->hash[hash].size;
 
    /* Does this node already exist? */
-   for (i = 0; i < node_size; i++)
+   for (pefn = NULL, efn = ef->header->directory->nodes[hash]; efn; pefn = efn, efn = efn->next)
      {
        /* if it matches */
-       if (eet_string_match(ef->header->directory->hash[hash].node[i].name, name))
+       if (eet_string_match(efn->name, name))
          {
-            free(ef->header->directory->hash[hash].node[i].data);
-            ef->header->directory->hash[hash].node[i].compression = -1;
-            ef->header->directory->hash[hash].node[i].size = 0;
-            ef->header->directory->hash[hash].node[i].data_size = 0;
-            ef->header->directory->hash[hash].node[i].data = NULL;
+            if (efn->name) free(efn->name);
+            if (efn->data) free(efn->data);
+            if (efn == ef->header->directory->nodes[hash])
+              ef->header->directory->nodes[hash] = efn->next;
+            else
+              pefn->next = efn->next;
+            free(efn);
             exists_already = 1;
             break;
          }
@@ -1026,6 +992,7 @@ eet_list(Eet_File *ef, char *glob, int *count_ret)
    int list_count = 0;
    int list_count_alloc = 0;
    int i, j, num;
+   Eet_File_Node *efn;
 
    /* check to see its' an eet file pointer */
    if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!glob) ||
@@ -1037,13 +1004,13 @@ eet_list(Eet_File *ef, char *glob, int *count_ret)
        return NULL;
      }
    /* loop through all entries */
-   num = (1 << (ef->header->directory->size - 1));
+   num = (1 << ef->header->directory->size);
    for (i = 0; i < num; i++)
      {
-       for (j = 0; j < ef->header->directory->hash[i].size; j++)
+       for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
          {
             /* if the entry matches the input glob */
-            if (!fnmatch(glob, ef->header->directory->hash[i].node[j].name, 0))
+            if (!fnmatch(glob, efn->name, 0))
               {
                  char **new_list;
 
@@ -1063,7 +1030,7 @@ eet_list(Eet_File *ef, char *glob, int *count_ret)
                       list_ret = new_list;
                    }
                  /* put pointer of name string in */
-                 list_ret[list_count - 1] = ef->header->directory->hash[i].node[j].name;
+                 list_ret[list_count - 1] = efn->name;
               }
          }
      }