Use a pre-allocated buffer on the stack for storing temporary chunks.

SVN revision: 18669
This commit is contained in:
rbdpngn 2005-11-27 18:54:02 +00:00 committed by rbdpngn
parent 40ae019495
commit dfa6c0196c
1 changed files with 41 additions and 45 deletions

View File

@ -132,7 +132,7 @@ static void *eet_data_put_string(void *src, int *size_ret);
static int eet_data_get_type(int type, void *src, void *src_end, void *dest); static int eet_data_get_type(int type, void *src, void *src_end, void *dest);
static void *eet_data_put_type(int type, void *src, int *size_ret); static void *eet_data_put_type(int type, void *src, int *size_ret);
static Eet_Data_Chunk *eet_data_chunk_get(void *src, int size); static void eet_data_chunk_get(Eet_Data_Chunk *chnk, void *src, int size);
static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, char *name); static Eet_Data_Chunk *eet_data_chunk_new(void *data, int size, char *name);
static void eet_data_chunk_free(Eet_Data_Chunk *chnk); static void eet_data_chunk_free(Eet_Data_Chunk *chnk);
@ -466,45 +466,39 @@ eet_data_put_type(int type, void *src, int *size_ret)
* *
*/ */
static Eet_Data_Chunk * static void
eet_data_chunk_get(void *src, int size) eet_data_chunk_get(Eet_Data_Chunk *chnk, void *src, int size)
{ {
Eet_Data_Chunk *chnk;
char *s; char *s;
int ret1, ret2; int ret1, ret2;
if (!src) return NULL; if (!src) return;
if (size <= 8) return NULL; if (size <= 8) return;
chnk = calloc(1, sizeof(Eet_Data_Chunk)); if (!chnk) return;
if (!chnk) return NULL;
s = src; s = src;
if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K')) if ((s[0] != 'C') || (s[1] != 'H') || (s[2] != 'n') || (s[3] != 'K'))
{ {
free(chnk); return;
return NULL;
} }
ret1 = eet_data_get_type(EET_T_INT, (void *)(s + 4), (void *)(s + size), &(chnk->size)); ret1 = eet_data_get_type(EET_T_INT, (void *)(s + 4), (void *)(s + size), &(chnk->size));
if (ret1 <= 0) if (ret1 <= 0)
{ {
free(chnk); return;
return NULL;
} }
if ((chnk->size < 0) || ((chnk->size + 8) > size)) if ((chnk->size < 0) || ((chnk->size + 8) > size))
{ {
free(chnk); return;
return NULL;
} }
ret2 = eet_data_get_type(EET_T_STRING, (void *)(s + 8), (void *)(s + size), &(chnk->name)); ret2 = eet_data_get_type(EET_T_STRING, (void *)(s + 8), (void *)(s + size), &(chnk->name));
if (ret2 <= 0) if (ret2 <= 0)
{ {
free(chnk); return;
return NULL;
} }
chnk->data = (char *)src + 4 + ret1 + ret2; chnk->data = (char *)src + 4 + ret1 + ret2;
chnk->size -= ret2; chnk->size -= ret2;
return chnk; return;
} }
static Eet_Data_Chunk * static Eet_Data_Chunk *
@ -940,7 +934,7 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
void *data; void *data;
char *p; char *p;
int size; int size;
Eet_Data_Chunk *chnk; Eet_Data_Chunk chnk;
if (words_bigendian == -1) if (words_bigendian == -1)
{ {
@ -956,8 +950,9 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
_eet_freelist_ref(); _eet_freelist_ref();
_eet_freelist_list_ref(); _eet_freelist_list_ref();
_eet_freelist_add(data); _eet_freelist_add(data);
chnk = eet_data_chunk_get(data_in, size_in); memset(&chnk, 0, sizeof(Eet_Data_Chunk));
if (!chnk) eet_data_chunk_get(&chnk, data_in, size_in);
if (!chnk.name)
{ {
_eet_freelist_unref(); _eet_freelist_unref();
_eet_freelist_list_unref(); _eet_freelist_list_unref();
@ -965,38 +960,39 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
return NULL; return NULL;
} }
if (strcmp(chnk->name, edd->name)) if (strcmp(chnk.name, edd->name))
{ {
eet_data_chunk_free(chnk); free(chnk.name);
_eet_freelist_unref(); _eet_freelist_unref();
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_free(); _eet_freelist_free();
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
return NULL; return NULL;
} }
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); if (!edd->elements.hash.buckets) _eet_descriptor_hash_new(edd);
while (size > 0) while (size > 0)
{ {
Eet_Data_Chunk *echnk; Eet_Data_Chunk echnk;
Eet_Data_Element *ede; Eet_Data_Element *ede;
/* get next data chunk */ /* get next data chunk */
echnk = eet_data_chunk_get(p, size); memset(&echnk, 0, sizeof(Eet_Data_Chunk));
if (!echnk) eet_data_chunk_get(&echnk, p, size);
if (!echnk.name)
{ {
_eet_freelist_unref(); _eet_freelist_unref();
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_free(); _eet_freelist_free();
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk); free(chnk.name);
return NULL; return NULL;
} }
/* FIXME: this is a linear search/match - speed up by putting in a /* FIXME: this is a linear search/match - speed up by putting in a
* hash lookup * hash lookup
*/ */
ede = _eet_descriptor_hash_find(edd, echnk->name); ede = _eet_descriptor_hash_find(edd, echnk.name);
if (ede) if (ede)
{ {
if (ede->group_type == EET_G_UNKNOWN) if (ede->group_type == EET_G_UNKNOWN)
@ -1008,8 +1004,8 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
(ede->type <= EET_T_STRING)) (ede->type <= EET_T_STRING))
{ {
ret = eet_data_get_type(ede->type, ret = eet_data_get_type(ede->type,
echnk->data, echnk.data,
((char *)echnk->data) + echnk->size, ((char *)echnk.data) + echnk.size,
((char *)data) + ede->offset); ((char *)data) + ede->offset);
} }
else if (ede->subtype) else if (ede->subtype)
@ -1017,15 +1013,15 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
void **ptr; void **ptr;
data_ret = eet_data_descriptor_decode(ede->subtype, data_ret = eet_data_descriptor_decode(ede->subtype,
echnk->data, echnk.data,
echnk->size); echnk.size);
if (!data_ret) if (!data_ret)
{ {
_eet_freelist_unref(); _eet_freelist_unref();
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_free(); _eet_freelist_free();
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk); free(chnk.name);
return NULL; return NULL;
} }
ptr = (void **)(((char *)data) + ede->offset); ptr = (void **)(((char *)data) + ede->offset);
@ -1060,8 +1056,8 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
{ {
_eet_freelist_add(data_ret); _eet_freelist_add(data_ret);
ret = eet_data_get_type(ede->type, ret = eet_data_get_type(ede->type,
echnk->data, echnk.data,
((char *)echnk->data) + echnk->size, ((char *)echnk.data) + echnk.size,
data_ret); data_ret);
if (ret <= 0) if (ret <= 0)
{ {
@ -1069,7 +1065,7 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_free(); _eet_freelist_free();
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk); free(chnk.name);
return NULL; return NULL;
} }
} }
@ -1079,15 +1075,15 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_free(); _eet_freelist_free();
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk); free(chnk.name);
return NULL; return NULL;
} }
} }
else if (ede->subtype) else if (ede->subtype)
{ {
data_ret = eet_data_descriptor_decode(ede->subtype, data_ret = eet_data_descriptor_decode(ede->subtype,
echnk->data, echnk.data,
echnk->size); echnk.size);
} }
if (data_ret) if (data_ret)
{ {
@ -1101,7 +1097,7 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_free(); _eet_freelist_free();
_eet_freelist_list_free(edd); _eet_freelist_list_free(edd);
eet_data_chunk_free(chnk); free(chnk.name);
return NULL; return NULL;
} }
} }
@ -1115,11 +1111,11 @@ eet_data_descriptor_decode(Eet_Data_Descriptor *edd,
} }
} }
/* advance to next chunk */ /* advance to next chunk */
p += (4 + 4 + strlen(echnk->name) + 1 + echnk->size); p += (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
size -= (4 + 4 + strlen(echnk->name) + 1 + echnk->size); size -= (4 + 4 + strlen(echnk.name) + 1 + echnk.size);
eet_data_chunk_free(echnk); free(echnk.name);
} }
eet_data_chunk_free(chnk); free(chnk.name);
_eet_freelist_unref(); _eet_freelist_unref();
_eet_freelist_list_unref(); _eet_freelist_list_unref();
_eet_freelist_reset(); _eet_freelist_reset();