and lo-and-behold. eet gets faster! a lot faster for data chunk decoding

(used by edje and ecore_config and e_config) and just general eet archive
opening times...


SVN revision: 14943
This commit is contained in:
Carsten Haitzler 2005-05-26 03:57:57 +00:00
parent 526a8099fa
commit 67506e226f
3 changed files with 327 additions and 249 deletions

View File

@ -34,7 +34,7 @@ void _eet_memfile_write_close(FILE *f);
void _eet_memfile_shutdown(); void _eet_memfile_shutdown();
#ifndef PATH_MAX #ifndef PATH_MAX
#define PATH_MAX 4095 #define PATH_MAX 4096
#endif #endif
#endif #endif

View 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_Basic_Type_Decoder Eet_Data_Basic_Type_Decoder;
typedef struct _Eet_Data_Chunk Eet_Data_Chunk; typedef struct _Eet_Data_Chunk Eet_Data_Chunk;
typedef struct _Eet_Data_Stream Eet_Data_Stream; 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; int pos;
}; };
struct _Eet_Data_Descriptor_Hash
{
Eet_Data_Element *element;
Eet_Data_Descriptor_Hash *next;
};
struct _Eet_Data_Descriptor struct _Eet_Data_Descriptor
{ {
char *name; char *name;
@ -85,6 +92,10 @@ struct _Eet_Data_Descriptor
struct { struct {
int num; int num;
Eet_Data_Element *set; Eet_Data_Element *set;
struct {
int size;
Eet_Data_Descriptor_Hash *buckets;
} hash;
} elements; } 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 *
eet_data_descriptor_new(char *name, eet_data_descriptor_new(char *name,
int size, int size,
@ -599,6 +711,7 @@ eet_data_descriptor_free(Eet_Data_Descriptor *edd)
{ {
int i; int i;
_eet_descriptor_hash_free(edd);
if (edd->name) free(edd->name); if (edd->name) free(edd->name);
for (i = 0; i < edd->elements.num; i++) for (i = 0; i < edd->elements.num; i++)
{ {
@ -811,10 +924,11 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
} }
p = chnk->data; p = chnk->data;
size = size_in - (4 + 4 + strlen(chnk->name) + 1); size = size_in - (4 + 4 + strlen(chnk->name) + 1);
if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
while (size > 0) while (size > 0)
{ {
Eet_Data_Chunk *echnk; Eet_Data_Chunk *echnk;
int i; Eet_Data_Element *ede;
/* get next data chunk */ /* get next data chunk */
echnk = eet_data_chunk_get(p, size); echnk = eet_data_chunk_get(p, size);
@ -827,88 +941,77 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
eet_data_chunk_free(chnk); eet_data_chunk_free(chnk);
return NULL; 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; if (ede->group_type == EET_G_UNKNOWN)
ede = &(edd->elements.set[i]);
if (!strcmp(echnk->name, ede->name))
{ {
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; ret = eet_data_get_type(ede->type,
void *data_ret; echnk->data,
((char *)echnk->data) + echnk->size,
if ((ede->type >= EET_T_CHAR) && ((char *)data) + ede->offset);
(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)
{
_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 if (ede->subtype)
{ {
switch (ede->group_type) void **ptr;
data_ret = eet_data_descriptor_decode(ede->subtype,
echnk->data,
echnk->size);
if (!data_ret)
{ {
case EET_G_ARRAY: _eet_freelist_unref();
case EET_G_VAR_ARRAY: _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
{
switch (ede->group_type)
{
case EET_G_ARRAY:
case EET_G_VAR_ARRAY:
{
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))
{ {
printf("ARRAY TYPE NOT IMPLIMENTED YET!!!\n"); data_ret = calloc(1, eet_coder[ede->type].size);
} if (data_ret)
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))
{ {
data_ret = calloc(1, eet_coder[ede->type].size); _eet_freelist_add(data_ret);
if (data_ret) ret = eet_data_get_type(ede->type,
{ echnk->data,
_eet_freelist_add(data_ret); ((char *)echnk->data) + echnk->size,
ret = eet_data_get_type(ede->type, data_ret);
echnk->data, if (ret <= 0)
((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_unref(); _eet_freelist_unref();
_eet_freelist_list_unref(); _eet_freelist_list_unref();
@ -918,18 +1021,6 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
return NULL; 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 else
{ {
_eet_freelist_unref(); _eet_freelist_unref();
@ -940,15 +1031,35 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
return NULL; return NULL;
} }
} }
break; else if (ede->subtype)
case EET_G_HASH: {
printf("HASH TYPE NOT IMPLIMENTED YET!!!\n"); data_ret = eet_data_descriptor_decode(ede->subtype,
break; echnk->data,
default: echnk->size);
break; }
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 */ /* advance to next chunk */

View File

@ -11,14 +11,10 @@
#define EET_MAGIC_FILE 0x1ee7ff00 #define EET_MAGIC_FILE 0x1ee7ff00
#define EET_MAGIC_FILE_HEADER 0x1ee7ff01 #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_Header Eet_File_Header;
typedef struct _Eet_File_Node Eet_File_Node; typedef struct _Eet_File_Node Eet_File_Node;
typedef struct _Eet_File_Directory Eet_File_Directory; typedef struct _Eet_File_Directory Eet_File_Directory;
typedef struct _Eet_File_Directory_Hash Eet_File_Directory_Hash;
struct _Eet_File struct _Eet_File
{ {
@ -42,26 +38,21 @@ struct _Eet_File_Header
Eet_File_Directory *directory; 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 struct _Eet_File_Directory
{ {
int size; int size;
Eet_File_Directory_Hash *hash; Eet_File_Node **nodes;
}; };
struct _Eet_File_Directory_Hash struct _Eet_File_Node
{ {
char *name;
int offset;
int compression;
int size; int size;
Eet_File_Node *node; int data_size;
void *data;
Eet_File_Node *next; /* FIXME: make buckets linked lists */
}; };
#if 0 #if 0
@ -200,7 +191,7 @@ eet_string_match(char *s1, char *s2)
static int static int
eet_hash_gen(char *key, int hash_size) eet_hash_gen(char *key, int hash_size)
{ {
int hash_num = 0; int hash_num = 0, i;
unsigned char *ptr; unsigned char *ptr;
const int masks[9] = const int masks[9] =
{ {
@ -219,8 +210,8 @@ eet_hash_gen(char *key, int hash_size)
if (!key) return 0; if (!key) return 0;
/* calc hash num */ /* calc hash num */
for (ptr = (unsigned char *)key; *ptr; ptr++) for (i = 0, ptr = (unsigned char *)key; *ptr; ptr++, i++)
hash_num ^= (int)(*ptr); hash_num ^= ((int)(*ptr) | ((int)(*ptr) << 8)) >> (i % 8);
/* mask it */ /* mask it */
hash_num &= masks[hash_size]; hash_num &= masks[hash_size];
@ -232,9 +223,10 @@ eet_hash_gen(char *key, int hash_size)
static void static void
eet_flush(Eet_File *ef) eet_flush(Eet_File *ef)
{ {
int i, j, count, size, num, offset; int i, count, size, num, offset;
int head[3]; int head[3];
unsigned long int i1, i2; unsigned long int i1, i2;
Eet_File_Node *efn;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if ((!ef) || (ef->magic != EET_MAGIC_FILE)) if ((!ef) || (ef->magic != EET_MAGIC_FILE))
@ -250,11 +242,11 @@ eet_flush(Eet_File *ef)
num = (1 << (ef->header->directory->size - 1)); num = (1 << (ef->header->directory->size - 1));
for (i = 0; i < num; i++) 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++; count++;
} }
} }
@ -263,12 +255,12 @@ eet_flush(Eet_File *ef)
offset = 0; offset = 0;
for (i = 0; i < num; i++) 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; efn->offset = 12 + size + offset;
offset += ef->header->directory->hash[i].node[j].size; offset += efn->size;
} }
} }
} }
@ -287,34 +279,34 @@ eet_flush(Eet_File *ef)
offset = 12; offset = 12;
for (i = 0; i < num; i++) 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; unsigned char *buf;
int buf_size; int buf_size;
int name_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_size = 20 + name_size;
buf = malloc(buf_size); buf = malloc(buf_size);
if (!buf) return; if (!buf) return;
i1 = (unsigned long int)ef->header->directory->hash[i].node[j].offset; i1 = (unsigned long int)efn->offset;
i2 = htonl(i1); i2 = htonl(i1);
*((int *)(buf + 0)) = (int)i2; *((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); i2 = htonl(i1);
*((int *)(buf + 4)) = (int)i2; *((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); i2 = htonl(i1);
*((int *)(buf + 8)) = (int)i2; *((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); i2 = htonl(i1);
*((int *)(buf + 12)) = (int)i2; *((int *)(buf + 12)) = (int)i2;
i1 = (unsigned long int)name_size; i1 = (unsigned long int)name_size;
i2 = htonl(i1); i2 = htonl(i1);
*((int *)(buf + 16)) = (int)i2; *((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) if (fwrite(buf, buf_size, 1, ef->fp) != 1)
{ {
free(buf); free(buf);
@ -328,13 +320,11 @@ eet_flush(Eet_File *ef)
/* write data */ /* write data */
for (i = 0; i < num; i++) 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, if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
ef->header->directory->hash[i].node[j].size,
1, ef->fp) != 1)
return; 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 */ /* 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; if (!ef) return NULL;
/* fill some of the members */ /* 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 */ /* if we opened for read or read-write */
// printf("OPEN!\n");
if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
{ {
unsigned char buf[12]; unsigned char buf[12];
@ -462,7 +453,7 @@ eet_open(const char *file, Eet_File_Mode mode)
return NULL; return NULL;
} }
/* allocate header */ /* allocate header */
ef->header = calloc(sizeof(Eet_File_Header), 1); ef->header = calloc(1, sizeof(Eet_File_Header));
if (!ef->header) if (!ef->header)
{ {
free(dyn_buf); free(dyn_buf);
@ -471,7 +462,7 @@ eet_open(const char *file, Eet_File_Mode mode)
} }
ef->header->magic = EET_MAGIC_FILE_HEADER; ef->header->magic = EET_MAGIC_FILE_HEADER;
/* allocate directory block in ram */ /* 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) if (!ef->header->directory)
{ {
free(dyn_buf); free(dyn_buf);
@ -481,8 +472,8 @@ eet_open(const char *file, Eet_File_Mode mode)
/* 8 bit hash table (256 buckets) */ /* 8 bit hash table (256 buckets) */
ef->header->directory->size = 8; ef->header->directory->size = 8;
/* allocate base hash table */ /* allocate base hash table */
ef->header->directory->hash = calloc(sizeof(Eet_File_Directory_Hash), (1 << (ef->header->directory->size - 1))); ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
if (!ef->header->directory->hash) if (!ef->header->directory->nodes)
{ {
free(dyn_buf); free(dyn_buf);
eet_close(ef); eet_close(ef);
@ -498,6 +489,7 @@ eet_open(const char *file, Eet_File_Mode mode)
} }
/* parse directory block */ /* parse directory block */
p = dyn_buf; p = dyn_buf;
// printf("entries: %i\n", num_entries);
for (i = 0; i < num_entries; i++) for (i = 0; i < num_entries; i++)
{ {
int offset; int offset;
@ -507,8 +499,7 @@ eet_open(const char *file, Eet_File_Mode mode)
int name_size; int name_size;
char *name; char *name;
int hash; int hash;
Eet_File_Node *node; Eet_File_Node *efn;
int node_size;
void *data = NULL; void *data = NULL;
/* out directory block is inconsistent - we have oveerun our */ /* 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; name[name_size] = 0;
/* get hask bucket it should go in */ /* get hask bucket it should go in */
hash = eet_hash_gen(name, ef->header->directory->size); hash = eet_hash_gen(name, ef->header->directory->size);
/* resize hask bucket */ efn = calloc(1, sizeof(Eet_File_Node));
node = realloc(ef->header->directory->hash[hash].node, if (!efn)
(ef->header->directory->hash[hash].size + 1) *
sizeof(Eet_File_Node));
if (!node)
{ {
free(dyn_buf); free(dyn_buf);
eet_close(ef); eet_close(ef);
return NULL; return NULL;
} }
/* current node size */ efn->next = ef->header->directory->nodes[hash];
node_size = ef->header->directory->hash[hash].size; ef->header->directory->nodes[hash] = efn;
/* resized node list set up */ efn->name = name;
ef->header->directory->hash[hash].node = node; efn->offset = offset;
/* new node at end */ efn->compression = flags;
ef->header->directory->hash[hash].node[node_size].name = name; efn->size = size;
ef->header->directory->hash[hash].node[node_size].offset = offset; efn->data_size = data_size;
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;
/* read-only mode, so currently we have no data loaded */ /* read-only mode, so currently we have no data loaded */
if (mode == EET_FILE_MODE_READ) if (mode == EET_FILE_MODE_READ)
{ efn->data = NULL;
ef->header->directory->hash[hash].node[node_size].data = NULL;
}
/* read-write mode - read everything into ram */ /* read-write mode - read everything into ram */
else else
{ {
data = malloc(size); data = malloc(size);
if (data) 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); free(data);
data = NULL; data = NULL;
@ -616,12 +599,9 @@ eet_open(const char *file, Eet_File_Mode mode)
break; break;
} }
} }
efn->data = data;
ef->header->directory->hash[hash].node[node_size].data = data;
} }
/* increment number of nodes */
ef->header->directory->hash[hash].size++;
/* advance */ /* advance */
p += 20 + name_size; p += 20 + name_size;
} }
@ -683,30 +663,24 @@ eet_close(Eet_File *ef)
{ {
if (ef->header->directory) if (ef->header->directory)
{ {
if (ef->header->directory->hash) if (ef->header->directory->nodes)
{ {
int i, num; int i, num;
num = (1 << (ef->header->directory->size - 1)); num = (1 << ef->header->directory->size);
for (i = 0; i < num; i++) 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; if (efn->name) free(efn->name);
int num2; if (efn->data) free(efn->data);
ef->header->directory->nodes[i] = efn->next;
num2 = ef->header->directory->hash[i].size; free(efn);
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);
} }
} }
free(ef->header->directory->hash); free(ef->header->directory->nodes);
} }
free(ef->header->directory); free(ef->header->directory);
} }
@ -723,9 +697,10 @@ void *
eet_read(Eet_File *ef, char *name, int *size_ret) eet_read(Eet_File *ef, char *name, int *size_ret)
{ {
void *data = NULL; void *data = NULL;
int size = 0, tmp_size; int size = 0, tmp_size;
int hash, i, num; int hash;
Eet_File_Node *efn;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) || if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) ||
((ef->mode != EET_FILE_MODE_READ) && ((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); hash = eet_hash_gen(name, ef->header->directory->size);
// printf("read %s\n", name); // printf("read %s\n", name);
/* hunt hash bucket */ /* hunt hash bucket */
num = ef->header->directory->hash[hash].size; for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
for (i = 0; i < num; i++)
{ {
/* if it matches */ /* 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 */ /* uncompressed data */
if (ef->header->directory->hash[hash].node[i].compression == 0) if (efn->compression == 0)
{ {
/* get size */ /* get size */
size = ef->header->directory->hash[hash].node[i].size; size = efn->size;
/* allocate data */ /* allocate data */
data = malloc(size); data = malloc(size);
if (data) if (data)
{ {
/* if we alreayd have the data in ram... copy that */ /* if we alreayd have the data in ram... copy that */
if (ef->header->directory->hash[hash].node[i].data) if (efn->data)
memcpy(data, memcpy(data, efn->data, efn->size);
ef->header->directory->hash[hash].node[i].data,
ef->header->directory->hash[hash].node[i].size);
/* or get data from disk */ /* or get data from disk */
else else
{ {
/* seek to data location */ /* 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); free(data);
data = NULL; data = NULL;
@ -789,11 +761,11 @@ eet_read(Eet_File *ef, char *name, int *size_ret)
void *tmp_data; void *tmp_data;
/* get size of data in file */ /* 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); tmp_data = malloc(tmp_size);
if (!tmp_data) break; if (!tmp_data) break;
/* get size uncompressed */ /* get size uncompressed */
size = ef->header->directory->hash[hash].node[i].data_size; size = efn->data_size;
/* allocate data */ /* allocate data */
data = malloc(size); data = malloc(size);
if (data) if (data)
@ -801,15 +773,13 @@ eet_read(Eet_File *ef, char *name, int *size_ret)
uLongf dlen; uLongf dlen;
/* if we already have the data in ram... copy that */ /* if we already have the data in ram... copy that */
if (ef->header->directory->hash[hash].node[i].data) if (efn->data)
memcpy(tmp_data, memcpy(tmp_data, efn->data, tmp_size);
ef->header->directory->hash[hash].node[i].data,
tmp_size);
/* or get data from disk */ /* or get data from disk */
else else
{ {
/* seek to data location */ /* 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(tmp_data);
free(data); free(data);
@ -851,38 +821,35 @@ int
eet_write(Eet_File *ef, char *name, void *data, int size, int compress) eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
{ {
int data_size; int data_size;
int hash, node_size; int hash;
Eet_File_Node *node; Eet_File_Node *efn;
char *name2; char *name2;
void *data2; void *data2;
int exists_already = 0; int exists_already = 0;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if ((!ef) || (ef->magic != EET_MAGIC_FILE) if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) || (!data) ||
|| (!name) || (!data) || (size <= 0) || (size <= 0) || ((ef->mode != EET_FILE_MODE_WRITE) &&
((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE)))
(ef->mode != EET_FILE_MODE_READ_WRITE)))
return 0; return 0;
if (!ef->header) if (!ef->header)
{ {
/* allocate header */ /* allocate header */
ef->header = calloc(sizeof(Eet_File_Header), 1); ef->header = calloc(1, sizeof(Eet_File_Header));
if (!ef->header) return 0; if (!ef->header) return 0;
ef->header->magic = EET_MAGIC_FILE_HEADER; ef->header->magic = EET_MAGIC_FILE_HEADER;
/* allocate directory block in ram */ /* 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; if (!ef->header->directory) return 0;
/* 8 bit hash table (256 buckets) */ /* 8 bit hash table (256 buckets) */
ef->header->directory->size = 8; ef->header->directory->size = 8;
/* allocate base hash table */ /* allocate base hash table */
ef->header->directory->hash = calloc(sizeof(Eet_File_Directory_Hash), (1 << (ef->header->directory->size - 1))); ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
if (!ef->header->directory->hash) return 0; if (!ef->header->directory->nodes) return 0;
} }
/* figure hash bucket */ /* figure hash bucket */
hash = eet_hash_gen(name, ef->header->directory->size); hash = eet_hash_gen(name, ef->header->directory->size);
node_size = ef->header->directory->hash[hash].size;
/* dup name */ /* dup name */
name2 = strdup(name); name2 = strdup(name);
if (!name2) return 0; 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? */ /* Does this node already exist? */
if (ef->mode == EET_FILE_MODE_READ_WRITE) if (ef->mode == EET_FILE_MODE_READ_WRITE)
{ {
int i; for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
for (i = 0; i < node_size; i++)
{ {
/* if it matches */ /* 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); free(efn->data);
ef->header->directory->hash[hash].node[i].compression = compress; efn->compression = compress;
ef->header->directory->hash[hash].node[i].size = data_size; efn->size = data_size;
ef->header->directory->hash[hash].node[i].data_size = size; efn->data_size = size;
ef->header->directory->hash[hash].node[i].data = data2; efn->data = data2;
exists_already = 1; exists_already = 1;
free(name2); free(name2);
break; break;
@ -952,25 +918,23 @@ eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
} }
if (!exists_already) if (!exists_already)
{ {
/* increase hash bucket size */ efn = calloc(1, sizeof(Eet_File_Node));
node = realloc(ef->header->directory->hash[hash].node, if (!efn)
(node_size + 1) * sizeof(Eet_File_Node));
if (!node)
{ {
free(name2); free(name2);
free(data2); free(data2);
return 0; return 0;
} }
/* resized node list set up */ /* 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 */ /* new node at end */
ef->header->directory->hash[hash].node[node_size].name = name2; efn->name = name2;
ef->header->directory->hash[hash].node[node_size].offset = 0; efn->offset = 0;
ef->header->directory->hash[hash].node[node_size].compression = compress; efn->compression = compress;
ef->header->directory->hash[hash].node[node_size].size = data_size; efn->size = data_size;
ef->header->directory->hash[hash].node[node_size].data_size = size; efn->data_size = size;
ef->header->directory->hash[hash].node[node_size].data = data2; efn->data = data2;
ef->header->directory->hash[hash].size++;
} }
/* flags that writes are pending */ /* flags that writes are pending */
@ -982,9 +946,10 @@ eet_write(Eet_File *ef, char *name, void *data, int size, int compress)
int int
eet_delete(Eet_File *ef, char *name) eet_delete(Eet_File *ef, char *name)
{ {
int hash, node_size, i; int hash;
int exists_already = 0; int exists_already = 0;
Eet_File_Node *efn, *pefn;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name)) if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name))
return 0; return 0;
@ -996,19 +961,20 @@ eet_delete(Eet_File *ef, char *name)
/* figure hash bucket */ /* figure hash bucket */
hash = eet_hash_gen(name, ef->header->directory->size); hash = eet_hash_gen(name, ef->header->directory->size);
node_size = ef->header->directory->hash[hash].size;
/* Does this node already exist? */ /* 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 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); if (efn->name) free(efn->name);
ef->header->directory->hash[hash].node[i].compression = -1; if (efn->data) free(efn->data);
ef->header->directory->hash[hash].node[i].size = 0; if (efn == ef->header->directory->nodes[hash])
ef->header->directory->hash[hash].node[i].data_size = 0; ef->header->directory->nodes[hash] = efn->next;
ef->header->directory->hash[hash].node[i].data = NULL; else
pefn->next = efn->next;
free(efn);
exists_already = 1; exists_already = 1;
break; break;
} }
@ -1026,6 +992,7 @@ eet_list(Eet_File *ef, char *glob, int *count_ret)
int list_count = 0; int list_count = 0;
int list_count_alloc = 0; int list_count_alloc = 0;
int i, j, num; int i, j, num;
Eet_File_Node *efn;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!glob) || if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!glob) ||
@ -1037,13 +1004,13 @@ eet_list(Eet_File *ef, char *glob, int *count_ret)
return NULL; return NULL;
} }
/* loop through all entries */ /* loop through all entries */
num = (1 << (ef->header->directory->size - 1)); num = (1 << ef->header->directory->size);
for (i = 0; i < num; i++) 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 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; char **new_list;
@ -1063,7 +1030,7 @@ eet_list(Eet_File *ef, char *glob, int *count_ret)
list_ret = new_list; list_ret = new_list;
} }
/* put pointer of name string in */ /* 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;
} }
} }
} }