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();
#ifndef PATH_MAX
#define PATH_MAX 4095
#define PATH_MAX 4096
#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_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)
{
_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;
}
ret = eet_data_get_type(ede->type,
echnk->data,
((char *)echnk->data) + echnk->size,
((char *)data) + ede->offset);
}
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:
case EET_G_VAR_ARRAY:
_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
{
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");
}
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);
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 */

View File

@ -11,14 +11,10 @@
#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;
}
}
}