eet: use Emile instead of Zlib and LZ4 directly.

This commit is contained in:
Cedric BAIL 2015-03-17 08:50:03 +01:00 committed by Cedric BAIL
parent 0fa50a0804
commit f9dd639a92
5 changed files with 229 additions and 536 deletions

View File

@ -1094,6 +1094,8 @@ EFL_LIB_START([Eet])
### Checks for libraries ### Checks for libraries
EFL_CHECK_LIBS([EET], [libjpeg])
## Compatibility layers ## Compatibility layers
EFL_PLATFORM_DEPEND([EET], [evil]) EFL_PLATFORM_DEPEND([EET], [evil])
@ -1106,8 +1108,6 @@ if test "$build_crypto" != "none" ; then
EFL_CRYPTO_DEPEND([EET]) EFL_CRYPTO_DEPEND([EET])
fi fi
EFL_CHECK_LIBS([EET], [libjpeg zlib])
EFL_INTERNAL_DEPEND_PKG([EET], [eina]) EFL_INTERNAL_DEPEND_PKG([EET], [eina])
EFL_INTERNAL_DEPEND_PKG([EET], [emile]) EFL_INTERNAL_DEPEND_PKG([EET], [emile])

View File

@ -2,6 +2,7 @@
#define _EET_PRIVATE_H #define _EET_PRIVATE_H
#include <Eina.h> #include <Eina.h>
#include <Emile.h>
typedef enum _Eet_Convert_Type Eet_Convert_Type; typedef enum _Eet_Convert_Type Eet_Convert_Type;
@ -298,6 +299,16 @@ Eet_Node *
void void
eet_node_free(Eet_Node *node); eet_node_free(Eet_Node *node);
static inline Emile_Compressor_Type
eet_2_emile_compressor(int comp)
{
switch (comp)
{
case EET_COMPRESSION_VERYFAST: return EMILE_LZ4HC;
case EET_COMPRESSION_SUPERFAST: return EMILE_LZ4HC;
default: return EMILE_ZLIB;
}
}
#define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \ #define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \
TYPE *Type##_malloc(unsigned int); \ TYPE *Type##_malloc(unsigned int); \

View File

@ -19,20 +19,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <setjmp.h> #include <setjmp.h>
#include <zlib.h>
#include <jpeglib.h> #include <jpeglib.h>
#include "Eet.h" #include "Eet.h"
#include "Eet_private.h" #include "Eet_private.h"
#ifdef ENABLE_LIBLZ4
# include <lz4.h>
# include <lz4hc.h>
#else
# include "lz4.h"
# include "lz4hc.h"
#endif
#include "rg_etc1.h" #include "rg_etc1.h"
#ifdef BUILD_NEON #ifdef BUILD_NEON
@ -1130,13 +1121,12 @@ eet_data_image_lossless_compressed_convert(int *size,
_eet_image_endian_check(); _eet_image_endian_check();
{ {
unsigned char *d, *comp; Eina_Binbuf *in;
int *header, *bigend_data = NULL, ret, ok = 1; Eina_Binbuf *out;
uLongf buflen = 0; unsigned char *result;
int *bigend_data = NULL;
buflen = (((w * h * 101) / 100) + 3) * 4; int header[8];
ret = LZ4_compressBound((w * h * 4)); unsigned int i;
if ((ret > 0) && ((uLongf)ret > buflen)) buflen = ret;
if (_eet_image_words_bigendian) if (_eet_image_words_bigendian)
{ {
@ -1149,51 +1139,27 @@ eet_data_image_lossless_compressed_convert(int *size,
data = (const char *) bigend_data; data = (const char *) bigend_data;
} }
comp = malloc(buflen); in = eina_binbuf_manage_read_only_new_length(data, w * h * 4);
if (!comp) if (!in)
{ {
free(bigend_data); free(bigend_data);
return NULL; return NULL;
} }
switch (compression) out = emile_binbuf_compress(in, eet_2_emile_compressor(compression), compression);
if (!out || (eina_binbuf_length_get(out) > eina_binbuf_length_get(in)))
{ {
case EET_COMPRESSION_VERYFAST: eina_binbuf_free(in);
ret = LZ4_compressHC((const char *)data, (char *)comp, eina_binbuf_free(out);
(w * h * 4));
if (ret <= 0) ok = 0;
buflen = ret;
break;
case EET_COMPRESSION_SUPERFAST:
ret = LZ4_compress((const char *)data, (char *)comp,
(w * h * 4));
if (ret <= 0) ok = 0;
buflen = ret;
break;
default: /* zlib etc. */
ret = compress2((Bytef *)comp, &buflen, (Bytef *)(data),
(uLong)(w * h * 4), compression);
if (ret != Z_OK) ok = 0;
break;
}
if ((!ok) || (buflen > (w * h * 4)))
{
free(comp);
free(bigend_data); free(bigend_data);
*size = -1; *size = -1;
return NULL; return NULL;
} }
d = malloc((8 * sizeof(int)) + buflen); eina_binbuf_free(in);
if (!d)
{
free(comp);
free(bigend_data);
return NULL;
}
header = (int *)d; memset(header, 0, 8 * sizeof(int));
memset(d, 0, 8 * sizeof(int));
header[0] = 0xac1dfeed; header[0] = 0xac1dfeed;
header[1] = w; header[1] = w;
header[2] = h; header[2] = h;
@ -1203,10 +1169,14 @@ eet_data_image_lossless_compressed_convert(int *size,
_eet_image_endian_swap(header, 8); _eet_image_endian_swap(header, 8);
free(bigend_data); free(bigend_data);
memcpy(d + (8 * sizeof(int)), comp, buflen); eina_binbuf_insert_length(out, (const unsigned char*) header, sizeof (header), 0);
*size = (8 * sizeof(int)) + buflen;
free(comp); *size = eina_binbuf_length_get(out);
return d; result = eina_binbuf_string_steal(out);
eina_binbuf_free(out);
return result;
} }
} }
@ -2337,7 +2307,7 @@ _eet_data_image_decode_inside(const void *data,
unsigned int src_x, unsigned int src_x,
unsigned int src_y, unsigned int src_y,
unsigned int src_w, unsigned int src_w,
unsigned int src_h, EINA_UNUSED unsigned int src_h, /* useful for fast path detection */
unsigned int *d, unsigned int *d,
unsigned int w, unsigned int w,
unsigned int h, unsigned int h,
@ -2360,75 +2330,42 @@ _eet_data_image_decode_inside(const void *data,
w, h, row_stride); w, h, row_stride);
else else
{ {
Eina_Binbuf *in;
Eina_Binbuf *out;
in = eina_binbuf_manage_read_only_new_length((const unsigned char *) body, size - 8 * sizeof (int));
if (!in) return 0;
if ((src_h == h) && (src_w == w) && (row_stride == src_w * 4)) if ((src_h == h) && (src_w == w) && (row_stride == src_w * 4))
{ {
switch (comp) out = eina_binbuf_manage_read_only_new_length((void*) d,
w * h * 4);
if (!emile_binbuf_expand(in, out,
eet_2_emile_compressor(comp)))
{ {
case EET_COMPRESSION_VERYFAST: eina_binbuf_free(in);
case EET_COMPRESSION_SUPERFAST: eina_binbuf_free(out);
if (LZ4_decompress_fast((const char *)body, return 0;
(char *)d, w * h * 4)
!= (size - 32)) return 0;
break;
default:
{
uLongf dlen = w * h * 4;
if (uncompress((Bytef *)d, &dlen, (Bytef *)body,
(uLongf)(size - 32)) != Z_OK)
return 0;
}
break;
} }
} }
else else
{ {
switch (comp) /* FIXME: This could create a huge alloc. So
{ compressed data and tile could not always work.*/
case EET_COMPRESSION_VERYFAST: out = emile_binbuf_uncompress(in,
case EET_COMPRESSION_SUPERFAST: eet_2_emile_compressor(comp),
{ w * h * 4);
char *dtmp; eina_binbuf_free(in);
if (!out) return 0;
dtmp = malloc(src_w * src_h * 4); _eet_data_image_copy_buffer((const unsigned int *) eina_binbuf_string_get(out),
if (!dtmp) return 0; src_x, src_y, src_w, d,
if (LZ4_decompress_fast((const char *)body, w, h, row_stride);
dtmp, w * h * 4)
!= (size - 32))
{
free(dtmp);
return 0;
}
_eet_data_image_copy_buffer((unsigned int *)dtmp,
src_x, src_y, src_w, d,
w, h, row_stride);
free(dtmp);
}
break;
default:
{
Bytef *dtmp;
uLongf dlen = src_w * src_h * 4;
/* FIXME: This could create a huge alloc. So eina_binbuf_free(out);
compressed data and tile could not always work.*/
dtmp = malloc(dlen);
if (!dtmp) return 0;
if (uncompress(dtmp, &dlen, (Bytef *)body,
(uLongf)(size - 32)) != Z_OK)
{
free(dtmp);
return 0;
}
_eet_data_image_copy_buffer((unsigned int *)dtmp,
src_x, src_y, src_w, d,
w, h, row_stride);
free(dtmp);
}
}
} }
} }
/* Fix swapiness. */ /* Fix swapiness. */
_eet_image_endian_swap(d, w * h); _eet_image_endian_swap(d, w * h);
} }

View File

@ -15,7 +15,6 @@
#include <unistd.h> #include <unistd.h>
#include <fnmatch.h> #include <fnmatch.h>
#include <fcntl.h> #include <fcntl.h>
#include <zlib.h>
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H
# include <netinet/in.h> # include <netinet/in.h>
@ -31,14 +30,6 @@
#include "Eet.h" #include "Eet.h"
#include "Eet_private.h" #include "Eet_private.h"
#ifdef ENABLE_LIBLZ4
# include <lz4.h>
# include <lz4hc.h>
#else
# include "lz4.h"
# include "lz4hc.h"
#endif
#ifndef O_BINARY #ifndef O_BINARY
# define O_BINARY 0 # define O_BINARY 0
#endif #endif
@ -93,11 +84,9 @@ static Eet_Error
static Eet_File_Node * static Eet_File_Node *
find_node_by_name(Eet_File *ef, find_node_by_name(Eet_File *ef,
const char *name); const char *name);
static int static Eina_Binbuf *
read_data_from_disk(Eet_File *ef, read_binbuf_from_disk(Eet_File *ef,
Eet_File_Node *efn, Eet_File_Node *efn);
void *buf,
int len);
static Eet_Error static Eet_Error
eet_internal_close(Eet_File *ef, eet_internal_close(Eet_File *ef,
@ -1847,8 +1836,8 @@ eet_read_cipher(Eet_File *ef,
const char *cipher_key) const char *cipher_key)
{ {
Eet_File_Node *efn; Eet_File_Node *efn;
char *data = NULL; Eina_Binbuf *in = NULL;
unsigned long int size = 0; unsigned char *data = NULL;
if (size_ret) if (size_ret)
*size_ret = 0; *size_ret = 0;
@ -1875,148 +1864,58 @@ eet_read_cipher(Eet_File *ef,
if (!efn) if (!efn)
goto on_error; goto on_error;
/* get size (uncompressed, if compressed at all) */ /* Get a binbuf attached to this efn */
size = efn->data_size; in = read_binbuf_from_disk(ef, efn);
if (!in) goto on_error;
/* allocate data */ /* First uncipher data */
data = malloc(size); if (efn->ciphered && cipher_key)
if (!data)
goto on_error;
/* uncompressed data */
if (efn->compression == 0)
{ {
void *data_deciphered = NULL; Eina_Binbuf *out;
unsigned int data_deciphered_sz = 0;
/* if we already have the data in ram... copy that */
if (efn->ciphered && efn->size > size) out = emile_binbuf_decipher(in, cipher_key, strlen(cipher_key));
{
size = efn->size;
data = realloc(data, efn->size);
}
if (efn->data) eina_binbuf_free(in);
memcpy(data, efn->data, size); if (!out) goto on_error;
else
if (!read_data_from_disk(ef, efn, data, size))
goto on_error;
if (efn->ciphered && cipher_key) in = out;
{
if (eet_decipher(data, efn->size, cipher_key, strlen(cipher_key),
&data_deciphered, &data_deciphered_sz))
{
if (data_deciphered)
free(data_deciphered);
goto on_error;
}
free(data);
data = data_deciphered;
size = data_deciphered_sz;
}
} }
/* compressed data */
else if (efn->compression)
{ {
void *tmp_data = NULL; Eina_Binbuf *out;
void *data_deciphered = NULL;
unsigned int data_deciphered_sz = 0;
int free_tmp = 0, ret;
int compr_size = efn->size;
uLongf dlen;
/* if we already have the data in ram... copy that */ out = emile_binbuf_uncompress(in,
if (efn->data) eet_2_emile_compressor(efn->compression_type),
tmp_data = efn->data; efn->data_size);
else
{
tmp_data = malloc(compr_size);
if (!tmp_data)
goto on_error;
free_tmp = 1; eina_binbuf_free(in);
if (!out) goto on_error;
if (!read_data_from_disk(ef, efn, tmp_data, compr_size)) in = out;
{
free(tmp_data);
goto on_error;
}
}
if (efn->ciphered && cipher_key)
{
if (eet_decipher(tmp_data, compr_size, cipher_key,
strlen(cipher_key), &data_deciphered,
&data_deciphered_sz))
{
if (free_tmp)
free(tmp_data);
if (data_deciphered)
free(data_deciphered);
goto on_error;
}
if (free_tmp)
free(tmp_data);
free_tmp = 1;
tmp_data = data_deciphered;
compr_size = data_deciphered_sz;
}
/* decompress it */
dlen = size;
switch (efn->compression_type)
{
case EET_COMPRESSION_VERYFAST:
case EET_COMPRESSION_SUPERFAST:
ret = LZ4_decompress_fast(tmp_data, data, dlen);
if (ret != compr_size)
{
if (free_tmp)
free(tmp_data);
goto on_error;
}
break;
default:
if (uncompress((Bytef *)data, &dlen,
tmp_data, (uLongf)compr_size) != Z_OK)
{
if (free_tmp)
free(tmp_data);
goto on_error;
}
break;
}
if (free_tmp)
free(tmp_data);
} }
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
if (size_ret)
*size_ret = eina_binbuf_length_get(in);
data = eina_binbuf_string_steal(in);
eina_binbuf_free(in);
/* handle alias */ /* handle alias */
if (efn->alias) if (efn->alias)
{ {
void *tmp; void *tmp;
if (data[size - 1] != '\0') if (data[efn->data_size - 1] != '\0')
goto on_error; goto on_error;
tmp = eet_read_cipher(ef, data, size_ret, cipher_key); tmp = eet_read_cipher(ef, (char*) data, size_ret, cipher_key);
free(data); free(data);
data = tmp; data = tmp;
} }
else
/* fill in return values */
if (size_ret)
*size_ret = size;
return data; return data;
@ -2041,7 +1940,7 @@ eet_read_direct(Eet_File *ef,
{ {
Eet_File_Node *efn; Eet_File_Node *efn;
const char *data = NULL; const char *data = NULL;
int size = 0, ret; int size = 0;
if (size_ret) if (size_ret)
*size_ret = 0; *size_ret = 0;
@ -2065,8 +1964,7 @@ eet_read_direct(Eet_File *ef,
/* hunt hash bucket */ /* hunt hash bucket */
efn = find_node_by_name(ef, name); efn = find_node_by_name(ef, name);
if (!efn) if (!efn) goto on_error;
goto on_error;
/* trick to detect data in memory instead of mmaped from disk */ /* trick to detect data in memory instead of mmaped from disk */
if (efn->offset > ef->data_size && !efn->data) if (efn->offset > ef->data_size && !efn->data)
@ -2075,57 +1973,42 @@ eet_read_direct(Eet_File *ef,
/* get size (uncompressed, if compressed at all) */ /* get size (uncompressed, if compressed at all) */
size = efn->data_size; size = efn->data_size;
/* handle alias case */
if (efn->alias) if (efn->alias)
{ {
data = efn->data ? efn->data : ef->data + efn->offset;
/* handle alias case */
if (efn->compression) if (efn->compression)
{ {
const void *retptr; Eina_Binbuf *in;
char *tmp; Eina_Binbuf *out;
int compr_size = efn->size; const unsigned char *tmp;
uLongf dlen; const char *retptr;
tmp = malloc(compr_size); in = read_binbuf_from_disk(ef, efn);
if (!tmp) goto on_error; if (!in) goto on_error;
switch (efn->compression_type)
out = emile_binbuf_uncompress(in,
eet_2_emile_compressor(efn->compression_type),
efn->data_size);
eina_binbuf_free(in);
if (!out) goto on_error;
tmp = eina_binbuf_string_get(out);
if (tmp[eina_binbuf_length_get(out) - 1] != '\0')
{ {
case EET_COMPRESSION_VERYFAST: eina_binbuf_free(out);
case EET_COMPRESSION_SUPERFAST:
ret = LZ4_decompress_fast(data, tmp, size);
if (ret != compr_size)
{
free(tmp);
goto on_error;
}
break;
default:
dlen = size;
if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
(uLongf)compr_size))
{
free(tmp);
goto on_error;
}
}
if (tmp[compr_size - 1] != '\0')
{
free(tmp);
goto on_error; goto on_error;
} }
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
retptr = eet_read_direct(ef, tmp, size_ret); retptr = eet_read_direct(ef, (const char *) tmp, size_ret);
free(tmp);
eina_binbuf_free(out);
return retptr; return retptr;
} }
if (!data) data = efn->data ? efn->data : ef->data + efn->offset;
goto on_error; if (!data) goto on_error;
if (data[size - 1] != '\0') if (data[size - 1] != '\0')
goto on_error; goto on_error;
@ -2160,7 +2043,7 @@ eet_alias_get(Eet_File *ef,
{ {
Eet_File_Node *efn; Eet_File_Node *efn;
const char *data = NULL; const char *data = NULL;
int size = 0, ret; int size = 0;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if (eet_check_pointer(ef)) if (eet_check_pointer(ef))
@ -2197,45 +2080,32 @@ eet_alias_get(Eet_File *ef,
/* handle alias case */ /* handle alias case */
if (efn->compression) if (efn->compression)
{ {
Eina_Binbuf *in;
Eina_Binbuf *out;
const unsigned char *tmp;
const char *retptr; const char *retptr;
char *tmp;
int compr_size = efn->size; in = read_binbuf_from_disk(ef, efn);
uLongf dlen; if (!in) goto on_error;
tmp = malloc(compr_size); out = emile_binbuf_uncompress(in,
if (!tmp) goto on_error; eet_2_emile_compressor(efn->compression_type),
switch (efn->compression_type) efn->data_size);
eina_binbuf_free(in);
if (!out) goto on_error;
tmp = eina_binbuf_string_get(out);
if (tmp[eina_binbuf_length_get(out) - 1] != '\0')
{ {
case EET_COMPRESSION_VERYFAST: eina_binbuf_free(out);
case EET_COMPRESSION_SUPERFAST:
ret = LZ4_decompress_fast(data, tmp, size);
if (ret != compr_size)
{
free(tmp);
goto on_error;
}
break;
default:
dlen = size;
if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
(uLongf)compr_size))
{
free(tmp);
goto on_error;
}
}
if (tmp[compr_size - 1] != '\0')
{
free(tmp);
goto on_error; goto on_error;
} }
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
retptr = eina_stringshare_add(tmp); retptr = eina_stringshare_add((const char *) tmp);
free(tmp);
eina_binbuf_free(out);
return retptr; return retptr;
} }
@ -2254,6 +2124,21 @@ on_error:
return NULL; return NULL;
} }
static void
eet_define_data(Eet_File *ef, Eet_File_Node *efn, Eina_Binbuf *data, int original_size, int comp, Eina_Bool ciphered)
{
free(efn->data);
efn->alias = 0;
efn->ciphered = ciphered;
efn->compression = !!comp;
efn->compression_type = comp;
efn->size = eina_binbuf_length_get(data);
efn->data_size = original_size;
efn->data = efn->size ? eina_binbuf_string_steal(data) : NULL;
/* Put the offset above the limit to avoid direct access */
efn->offset = ef->data_size + 1;
}
EAPI Eina_Bool EAPI Eina_Bool
eet_alias(Eet_File *ef, eet_alias(Eet_File *ef,
const char *name, const char *name,
@ -2261,9 +2146,10 @@ eet_alias(Eet_File *ef,
int comp) int comp)
{ {
Eet_File_Node *efn; Eet_File_Node *efn;
void *data2; Eina_Binbuf *in;
Eina_Bool exists_already = EINA_FALSE; Eina_Bool exists_already = EINA_FALSE;
int data_size, ret, hash, slen; int hash;
Eina_Bool success = EINA_FALSE;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if (eet_check_pointer(ef)) if (eet_check_pointer(ef))
@ -2312,78 +2198,22 @@ eet_alias(Eet_File *ef,
/* figure hash bucket */ /* figure hash bucket */
hash = _eet_hash_gen(name, ef->header->directory->size); hash = _eet_hash_gen(name, ef->header->directory->size);
slen = strlen(destination) + 1; in = eina_binbuf_manage_read_only_new_length((unsigned char*) destination, strlen(destination) + 1);
data_size = comp ? if (!in) goto on_error;
12 + ((slen * 101) / 100)
: slen;
if (comp)
{
ret = LZ4_compressBound(slen);
if ((ret > 0) && (ret > data_size)) data_size = ret;
}
data2 = malloc(data_size);
if (!data2) goto on_error;
/* if we want to compress */ /* if we want to compress */
if (comp) if (comp)
{ {
switch (comp) Eina_Binbuf *out;
{
case EET_COMPRESSION_VERYFAST:
ret = LZ4_compressHC((const char *)destination, (char *)data2,
slen);
if (ret <= 0)
{
free(data2);
goto on_error;
}
data_size = ret;
break;
case EET_COMPRESSION_SUPERFAST:
ret = LZ4_compress((const char *)destination, (char *)data2,
slen);
if (ret <= 0)
{
free(data2);
goto on_error;
}
data_size = ret;
break;
default:
{
uLongf buflen;
/* compress the data with max compression */
buflen = (uLongf)data_size;
if (compress2((Bytef *)data2, &buflen,
(const Bytef *)destination,
(uLong)slen, Z_BEST_COMPRESSION) != Z_OK)
{
free(data2);
goto on_error;
}
/* record compressed chunk size */
data_size = (int)buflen;
}
break;
}
if ((data_size < 0) ||
(data_size >= (int)(strlen(destination) + 1)))
{
comp = 0;
data_size = strlen(destination) + 1;
}
else
{
void *data3;
data3 = realloc(data2, data_size); out = emile_binbuf_compress(in,
if (data3) data2 = data3; eet_2_emile_compressor(comp),
} EMILE_BEST_COMPRESSION);
eina_binbuf_free(in);
if (!out) goto on_error;
in = out;
} }
if (!comp) memcpy(data2, destination, data_size);
/* Does this node already exist? */ /* Does this node already exist? */
for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
@ -2391,16 +2221,7 @@ eet_alias(Eet_File *ef,
/* if it matches */ /* if it matches */
if ((efn->name) && (eet_string_match(efn->name, name))) if ((efn->name) && (eet_string_match(efn->name, name)))
{ {
free(efn->data); eet_define_data(ef, efn, in, strlen(destination) + 1, comp, 0);
efn->alias = 1;
efn->ciphered = 0;
efn->compression = !!comp;
efn->compression_type = comp;
efn->size = data_size;
efn->data_size = strlen(destination) + 1;
efn->data = data2;
/* Put the offset above the limit to avoid direct access */
efn->offset = ef->data_size + 1;
exists_already = EINA_TRUE; exists_already = EINA_TRUE;
break; break;
} }
@ -2410,36 +2231,32 @@ eet_alias(Eet_File *ef,
efn = eet_file_node_malloc(1); efn = eet_file_node_malloc(1);
if (!efn) if (!efn)
{ {
free(data2); eina_binbuf_free(in);
goto on_error; goto on_error;
} }
efn->name = strdup(name); efn->name = strdup(name);
efn->name_size = strlen(efn->name) + 1; efn->name_size = strlen(efn->name) + 1;
efn->free_name = 1; efn->free_name = 1;
efn->data = NULL;
efn->next = ef->header->directory->nodes[hash]; efn->next = ef->header->directory->nodes[hash];
ef->header->directory->nodes[hash] = efn; ef->header->directory->nodes[hash] = efn;
/* Put the offset above the limit to avoid direct access */
efn->offset = ef->data_size + 1; eet_define_data(ef, efn, in, strlen(destination) + 1, comp, 0);
efn->alias = 1;
efn->ciphered = 0;
efn->compression = !!comp;
efn->compression_type = comp;
efn->size = data_size;
efn->data_size = strlen(destination) + 1;
efn->data = data2;
} }
efn->alias = 1;
eina_binbuf_free(in);
/* flags that writes are pending */ /* flags that writes are pending */
ef->writes_pending = 1; ef->writes_pending = 1;
UNLOCK_FILE(ef); success = EINA_TRUE;
return EINA_TRUE;
on_error: on_error:
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
return EINA_FALSE; return success;
} }
EAPI int EAPI int
@ -2450,9 +2267,10 @@ eet_write_cipher(Eet_File *ef,
int comp, int comp,
const char *cipher_key) const char *cipher_key)
{ {
Eina_Binbuf *in;
Eet_File_Node *efn; Eet_File_Node *efn;
void *data2 = NULL; int exists_already = 0;
int exists_already = 0, data_size, hash, ret; int hash;
/* check to see its' an eet file pointer */ /* check to see its' an eet file pointer */
if (eet_check_pointer(ef)) if (eet_check_pointer(ef))
@ -2502,157 +2320,86 @@ eet_write_cipher(Eet_File *ef,
hash = _eet_hash_gen(name, ef->header->directory->size); hash = _eet_hash_gen(name, ef->header->directory->size);
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
data_size = comp ? 12 + ((size * 101) / 100) : size; in = eina_binbuf_manage_read_only_new_length(data, size);
if (comp) if (comp)
{ {
ret = LZ4_compressBound(size); Eina_Binbuf *out;
if ((ret > 0) && (ret > data_size)) data_size = ret;
}
if (comp || !cipher_key)
{
data2 = malloc(data_size);
if (!data2)
goto on_error;
}
/* if we want to compress */ out = emile_binbuf_compress(in, eet_2_emile_compressor(comp), EMILE_BEST_COMPRESSION);
if (comp) if (out)
{
switch (comp)
{ {
case EET_COMPRESSION_VERYFAST: if (eina_binbuf_length_get(out) < eina_binbuf_length_get(in))
ret = LZ4_compressHC((const char *)data, (char *)data2, size);
if (ret <= 0)
{ {
free(data2); eina_binbuf_free(in);
LOCK_FILE(ef); in = out;
goto on_error;
} }
data_size = ret; else
break;
case EET_COMPRESSION_SUPERFAST:
ret = LZ4_compress((const char *)data, (char *)data2, size);
if (ret <= 0)
{ {
free(data2); eina_binbuf_free(out);
LOCK_FILE(ef); comp = 0;
goto on_error;
} }
data_size = ret;
break;
default:
{
uLongf buflen;
/* compress the data with max compression */
buflen = (uLongf)data_size;
if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
(uLong)size, Z_BEST_COMPRESSION) != Z_OK)
{
free(data2);
LOCK_FILE(ef);
goto on_error;
}
/* record compressed chunk size */
data_size = (int)buflen;
}
}
if ((data_size < 0) || (data_size >= size))
{
comp = 0;
data_size = size;
} }
else else
{ {
void *data3; // There is a change of behavior here, in case of memory pressure,
// we will try to keep the uncompressed buffer.
data3 = realloc(data2, data_size); comp = 0;
if (data3)
data2 = data3;
} }
} }
if (cipher_key) if (cipher_key)
{ {
void *data_ciphered = NULL; Eina_Binbuf *out;
unsigned int data_ciphered_sz = 0;
const void *tmp;
tmp = comp ? data2 : data; out = emile_binbuf_cipher(in, cipher_key, strlen(cipher_key));
if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), // Old behaviour was to not fail if the cipher where not built in
&data_ciphered, &data_ciphered_sz)) if (out)
{ {
if (data2) eina_binbuf_free(in);
free(data2); in = out;
data2 = data_ciphered;
data_size = data_ciphered_sz;
}
else
{
if (data_ciphered)
free(data_ciphered);
cipher_key = NULL;
} }
} }
else
if (!comp)
memcpy(data2, data, size);
LOCK_FILE(ef); LOCK_FILE(ef);
/* Does this node already exist? */ /* Does this node already exist? */
for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
{ {
/* if it matches */ /* if it matches */
if ((efn->name) && (eet_string_match(efn->name, name))) if ((efn->name) && (eet_string_match(efn->name, name)))
{ {
free(efn->data); eet_define_data(ef, efn, in, size, comp, !!cipher_key);
efn->alias = 0; exists_already = 1;
efn->ciphered = cipher_key ? 1 : 0; break;
efn->compression = !!comp; }
efn->compression_type = comp;
efn->size = data_size;
efn->data_size = size;
efn->data = data2;
/* Put the offset above the limit to avoid direct access */
efn->offset = ef->data_size + 1;
exists_already = 1;
break;
}
} }
if (!exists_already) if (!exists_already)
{ {
efn = eet_file_node_malloc(1); efn = eet_file_node_malloc(1);
if (!efn) if (!efn)
{ {
free(data2); eina_binbuf_free(in);
goto on_error; goto on_error;
} }
efn->name = strdup(name); efn->name = strdup(name);
efn->name_size = strlen(efn->name) + 1; efn->name_size = strlen(efn->name) + 1;
efn->free_name = 1; efn->free_name = 1;
efn->data = NULL;
efn->next = ef->header->directory->nodes[hash]; efn->next = ef->header->directory->nodes[hash];
ef->header->directory->nodes[hash] = efn; ef->header->directory->nodes[hash] = efn;
/* Put the offset above the limit to avoid direct access */
efn->offset = ef->data_size + 1; eet_define_data(ef, efn, in, size, comp, !!cipher_key);
efn->alias = 0;
efn->ciphered = cipher_key ? 1 : 0;
efn->compression = !!comp;
efn->compression_type = comp;
efn->size = data_size;
efn->data_size = size;
efn->data = data2;
} }
/* flags that writes are pending */ /* flags that writes are pending */
ef->writes_pending = 1; ef->writes_pending = 1;
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
return data_size;
eina_binbuf_free(in);
return efn->size;
on_error: on_error:
UNLOCK_FILE(ef); UNLOCK_FILE(ef);
@ -2986,23 +2733,21 @@ find_node_by_name(Eet_File *ef,
return NULL; return NULL;
} }
static int static Eina_Binbuf *
read_data_from_disk(Eet_File *ef, read_binbuf_from_disk(Eet_File *ef,
Eet_File_Node *efn, Eet_File_Node *efn)
void *buf,
int len)
{ {
if (efn->data)
return eina_binbuf_manage_read_only_new_length(efn->data, efn->size);
if (efn->offset > ef->data_size) if (efn->offset > ef->data_size)
return 0; return 0;
if (!ef->data) if (!ef->data)
return 0; return 0;
if ((efn->offset + len) > ef->data_size) if ((efn->offset + efn->size) > ef->data_size)
return 0; return 0;
memcpy(buf, ef->data + efn->offset, len); return eina_binbuf_manage_read_only_new_length(ef->data + efn->offset, efn->size);
return len;
} }

View File

@ -88,9 +88,9 @@ emile_binbuf_expand(const Eina_Binbuf *in,
{ {
int ret; int ret;
ret = LZ4_uncompress((const char*) eina_binbuf_string_get(in), ret = LZ4_decompress_fast((const char*) eina_binbuf_string_get(in),
(char*) eina_binbuf_string_get(out), (char*) eina_binbuf_string_get(out),
eina_binbuf_length_get(out)); eina_binbuf_length_get(out));
if ((unsigned int) ret != eina_binbuf_length_get(in)) if ((unsigned int) ret != eina_binbuf_length_get(in))
return EINA_FALSE; return EINA_FALSE;
break; break;