summaryrefslogtreecommitdiff
path: root/src/lib/emile/emile_compress.c
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2015-03-17 08:50:02 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-03-17 09:58:17 +0100
commit0fa50a080428bb8c710603cb4208e1786f9365a9 (patch)
treea0ede091c745237e55a097c434d93c08781f475e /src/lib/emile/emile_compress.c
parenta7d7cae0c4bc92d7672d512136c85a3305aaf74f (diff)
emile: add compress/uncompress logic.
Diffstat (limited to '')
-rw-r--r--src/lib/emile/emile_compress.c136
1 files changed, 136 insertions, 0 deletions
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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif /* ifdef HAVE_CONFIG_H */
4
5#include <zlib.h>
6
7#include <Eina.h>
8#include "Emile.h"
9
10#ifdef ENABLE_LIBLZ4
11# include <lz4.h>
12# include <lz4hc.h>
13#else
14# include "lz4.h"
15# include "lz4hc.h"
16#endif
17
18static int
19emile_compress_buffer_size(const Eina_Binbuf *data, Emile_Compressor_Type t)
20{
21 switch (t)
22 {
23 case EMILE_ZLIB:
24 return 12 + ((eina_binbuf_length_get(data) * 101) / 100);
25 case EMILE_LZ4:
26 case EMILE_LZ4HC:
27 return LZ4_compressBound(eina_binbuf_length_get(data));
28 default:
29 return -1;
30 }
31}
32
33EAPI Eina_Binbuf *
34emile_binbuf_compress(const Eina_Binbuf *data, Emile_Compressor_Type t, int level)
35{
36 void *compact;
37 int length;
38 Eina_Bool ok = EINA_FALSE;
39
40 length = emile_compress_buffer_size(data, t);
41
42 compact = malloc(length);
43 if (!compact) return NULL;
44
45 switch (t)
46 {
47 case EMILE_LZ4:
48 length = LZ4_compress((const char *) eina_binbuf_string_get(data), compact, eina_binbuf_length_get(data));
49 if (length > 0) ok = EINA_TRUE;
50 compact = realloc(compact, length); // It is going to be smaller and should never fail, if it does you are in deep poo.
51 break;
52 case EMILE_LZ4HC:
53 length = LZ4_compressHC((const char *) eina_binbuf_string_get(data), compact, eina_binbuf_length_get(data));
54 if (length > 0) ok = EINA_TRUE;
55 compact = realloc(compact, length);
56 break;
57 case EMILE_ZLIB:
58 {
59 uLongf buflen = (uLongf) length;
60
61 if (compress2((Bytef *)compact, &buflen, (Bytef *) eina_binbuf_string_get(data),
62 (uLong) eina_binbuf_length_get(data), level) == Z_OK)
63 ok = EINA_TRUE;
64 length = (int) buflen;
65 }
66 }
67
68 if (!ok)
69 {
70 free(compact);
71 return NULL;
72 }
73
74 return eina_binbuf_manage_new_length(compact, length);
75}
76
77EAPI Eina_Bool
78emile_binbuf_expand(const Eina_Binbuf *in,
79 Eina_Binbuf *out,
80 Emile_Compressor_Type t)
81{
82 if (!in || !out) return EINA_FALSE;
83
84 switch (t)
85 {
86 case EMILE_LZ4:
87 case EMILE_LZ4HC:
88 {
89 int ret;
90
91 ret = LZ4_uncompress((const char*) eina_binbuf_string_get(in),
92 (char*) eina_binbuf_string_get(out),
93 eina_binbuf_length_get(out));
94 if ((unsigned int) ret != eina_binbuf_length_get(in))
95 return EINA_FALSE;
96 break;
97 }
98 case EMILE_ZLIB:
99 {
100 uLongf dlen = eina_binbuf_length_get(out);
101
102 if (uncompress((Bytef *) eina_binbuf_string_get(out), &dlen,
103 eina_binbuf_string_get(in),
104 (uLongf) eina_binbuf_length_get(in)) != Z_OK)
105 return EINA_FALSE;
106 break;
107 }
108 default:
109 return EINA_FALSE;
110 }
111
112 return EINA_TRUE;
113}
114
115EAPI Eina_Binbuf *
116emile_binbuf_uncompress(const Eina_Binbuf *data, Emile_Compressor_Type t, unsigned int dest_length)
117{
118 Eina_Binbuf *out;
119 void *expanded;
120
121 expanded = malloc(dest_length);
122 if (!expanded) return NULL;
123
124 out = eina_binbuf_manage_new_length(expanded, dest_length);
125 if (!out) goto on_error;
126
127 if (!emile_binbuf_expand(data, out, t))
128 goto on_error;
129
130 return out;
131
132 on_error:
133 if (!out) free(expanded);
134 if (out) eina_binbuf_free(out);
135 return NULL;
136}