From 0fa50a080428bb8c710603cb4208e1786f9365a9 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Tue, 17 Mar 2015 08:50:02 +0100 Subject: [PATCH] emile: add compress/uncompress logic. --- src/Makefile_Emile.am | 27 ++++++- src/lib/emile/Emile.h | 24 ++++++ src/lib/emile/emile_compress.c | 136 +++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 src/lib/emile/emile_compress.c diff --git a/src/Makefile_Emile.am b/src/Makefile_Emile.am index e93b594905..067eb988ca 100644 --- a/src/Makefile_Emile.am +++ b/src/Makefile_Emile.am @@ -9,19 +9,40 @@ dist_installed_emilemainheaders_DATA = lib/emile/Emile.h lib_emile_libemile_la_SOURCES = \ lib/emile/emile_private.h \ lib/emile/emile_main.c \ -lib/emile/emile_cipher.c +lib/emile/emile_compress.c + +if ! ENABLE_LIBLZ4 +lib_emile_libemile_la_SOURCES += \ +static_libs/lz4/lz4.c \ +static_libs/lz4/lz4.h \ +static_libs/lz4/lz4hc.c \ +static_libs/lz4/lz4hc.h +endif lib_emile_libemile_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ --I$(top_srcdir)/src/static_libs/lz4 \ -DPACKAGE_BIN_DIR=\"$(bindir)\" \ -DPACKAGE_LIB_DIR=\"$(libdir)\" \ -DPACKAGE_DATA_DIR=\"$(datadir)/emile\" \ @EMILE_CFLAGS@ + +if ! ENABLE_LIBLZ4 +lib_emile_libemile_la_CPPFLAGS += \ +-I$(top_srcdir)/src/static_libs/lz4 +endif + lib_emile_libemile_la_LIBADD = @EMILE_LIBS@ lib_emile_libemile_la_DEPENDENCIES = @EMILE_INTERNAL_LIBS@ lib_emile_libemile_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ -EXTRA_DIST += static_libs/lz4/README +if ! ENABLE_LIBLZ4 +lib_emile_libemile_la_LIBADD += @LIBLZ4_LIBS@ +endif + +EXTRA_DIST += static_libs/lz4/README \ +static_libs/lz4/lz4.c \ +static_libs/lz4/lz4.h \ +static_libs/lz4/lz4hc.c \ +static_libs/lz4/lz4hc.h ### Binary diff --git a/src/lib/emile/Emile.h b/src/lib/emile/Emile.h index 28f84aa53c..c82af0af91 100644 --- a/src/lib/emile/Emile.h +++ b/src/lib/emile/Emile.h @@ -112,6 +112,30 @@ EAPI Eina_Binbuf *emile_binbuf_cipher(const Eina_Binbuf *in, EAPI Eina_Binbuf *emile_binbuf_decipher(const Eina_Binbuf *in, const char *key, unsigned int length); +typedef enum +{ + EMILE_ZLIB, + EMILE_LZ4, + EMILE_LZ4HC +} Emile_Compressor_Type; + +typedef enum +{ + EMILE_DEFAULT = -1, + EMILE_NO_COMPRESSION = 0, + EMILE_FAST_COMPRESSION = 1, + EMILE_BEST_COMPRESSION = 9 +} Emile_Compressor_Level; + +EAPI Eina_Binbuf *emile_binbuf_compress(const Eina_Binbuf *in, + Emile_Compressor_Type t, int level); +EAPI Eina_Binbuf *emile_binbuf_uncompress(const Eina_Binbuf *in, + Emile_Compressor_Type t, + unsigned int dest_length); +EAPI Eina_Bool emile_binbuf_expand(const Eina_Binbuf *in, + Eina_Binbuf *out, + Emile_Compressor_Type t); + #ifdef __cplusplus } #endif /* ifdef __cplusplus */ diff --git a/src/lib/emile/emile_compress.c b/src/lib/emile/emile_compress.c new file mode 100644 index 0000000000..4db0ed7bc1 --- /dev/null +++ b/src/lib/emile/emile_compress.c @@ -0,0 +1,136 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#include + +#include +#include "Emile.h" + +#ifdef ENABLE_LIBLZ4 +# include +# include +#else +# include "lz4.h" +# include "lz4hc.h" +#endif + +static int +emile_compress_buffer_size(const Eina_Binbuf *data, Emile_Compressor_Type t) +{ + switch (t) + { + case EMILE_ZLIB: + return 12 + ((eina_binbuf_length_get(data) * 101) / 100); + case EMILE_LZ4: + case EMILE_LZ4HC: + return LZ4_compressBound(eina_binbuf_length_get(data)); + default: + return -1; + } +} + +EAPI Eina_Binbuf * +emile_binbuf_compress(const Eina_Binbuf *data, Emile_Compressor_Type t, int level) +{ + void *compact; + int length; + Eina_Bool ok = EINA_FALSE; + + length = emile_compress_buffer_size(data, t); + + compact = malloc(length); + if (!compact) return NULL; + + switch (t) + { + case EMILE_LZ4: + length = LZ4_compress((const char *) eina_binbuf_string_get(data), compact, eina_binbuf_length_get(data)); + if (length > 0) ok = EINA_TRUE; + compact = realloc(compact, length); // It is going to be smaller and should never fail, if it does you are in deep poo. + break; + case EMILE_LZ4HC: + length = LZ4_compressHC((const char *) eina_binbuf_string_get(data), compact, eina_binbuf_length_get(data)); + if (length > 0) ok = EINA_TRUE; + compact = realloc(compact, length); + break; + case EMILE_ZLIB: + { + uLongf buflen = (uLongf) length; + + if (compress2((Bytef *)compact, &buflen, (Bytef *) eina_binbuf_string_get(data), + (uLong) eina_binbuf_length_get(data), level) == Z_OK) + ok = EINA_TRUE; + length = (int) buflen; + } + } + + if (!ok) + { + free(compact); + return NULL; + } + + return eina_binbuf_manage_new_length(compact, length); +} + +EAPI Eina_Bool +emile_binbuf_expand(const Eina_Binbuf *in, + Eina_Binbuf *out, + Emile_Compressor_Type t) +{ + if (!in || !out) return EINA_FALSE; + + switch (t) + { + case EMILE_LZ4: + case EMILE_LZ4HC: + { + int ret; + + ret = LZ4_uncompress((const char*) eina_binbuf_string_get(in), + (char*) eina_binbuf_string_get(out), + eina_binbuf_length_get(out)); + if ((unsigned int) ret != eina_binbuf_length_get(in)) + return EINA_FALSE; + break; + } + case EMILE_ZLIB: + { + uLongf dlen = eina_binbuf_length_get(out); + + if (uncompress((Bytef *) eina_binbuf_string_get(out), &dlen, + eina_binbuf_string_get(in), + (uLongf) eina_binbuf_length_get(in)) != Z_OK) + return EINA_FALSE; + break; + } + default: + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Binbuf * +emile_binbuf_uncompress(const Eina_Binbuf *data, Emile_Compressor_Type t, unsigned int dest_length) +{ + Eina_Binbuf *out; + void *expanded; + + expanded = malloc(dest_length); + if (!expanded) return NULL; + + out = eina_binbuf_manage_new_length(expanded, dest_length); + if (!out) goto on_error; + + if (!emile_binbuf_expand(data, out, t)) + goto on_error; + + return out; + + on_error: + if (!out) free(expanded); + if (out) eina_binbuf_free(out); + return NULL; +}