forked from enlightenment/efl
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:
parent
526a8099fa
commit
67506e226f
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue