Updated version number to 1.5.6
[deark.git] / src / fmtutil-miniz.c
blob3c851cc5ad460a5b557d1e177e7292f3f9bd5803
1 // This file is part of Deark.
2 // Copyright (C) 2016-2019 Jason Summers
3 // See the file COPYING for terms of use.
5 // Compression and decompression of Deflate and zlib
7 #define DE_NOT_IN_MODULE
8 #include "deark-config.h"
9 #include "deark-private.h"
10 #include "deark-fmtutil.h"
12 #define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
13 #define MINIZ_NO_STDIO
14 #define MINIZ_NO_ARCHIVE_APIS
15 #include "../foreign/miniz.h"
17 void fmtutil_inflate_codectype1(deark *c, struct de_dfilter_in_params *dcmpri,
18 struct de_dfilter_out_params *dcmpro, struct de_dfilter_results *dres,
19 void *codec_private_params)
21 struct de_inflate_params *inflparams = (struct de_inflate_params*)codec_private_params;
22 mz_stream strm;
23 int ret;
24 int ok = 0;
25 #define DE_DFL_INBUF_SIZE 32768
26 #define DE_DFL_OUTBUF_SIZE (DE_DFL_INBUF_SIZE*4)
27 u8 *inbuf = NULL;
28 u8 *outbuf = NULL;
29 i64 inbuf_num_valid_bytes; // Number of valid bytes in inbuf, starting with [0].
30 i64 inbuf_num_consumed_bytes; // Of inbuf_num_valid_bytes, the number that have been consumed.
31 i64 inbuf_num_consumed_bytes_this_time;
32 unsigned int orig_avail_in;
33 i64 input_cur_pos;
34 i64 output_bytes_this_time;
35 i64 nbytes_to_read;
36 i64 nbytes_to_write;
37 i64 nbytes_written_total = 0;
38 int stream_open_flag = 0;
39 static const char *modname = "inflate";
41 dres->bytes_consumed = 0;
42 if(dcmpri->len<0) {
43 de_dfilter_set_errorf(c, dres, modname, "Internal error");
44 goto done;
47 inbuf = de_malloc(c, DE_DFL_INBUF_SIZE);
48 outbuf = de_malloc(c, DE_DFL_OUTBUF_SIZE);
50 de_zeromem(&strm, sizeof(strm));
51 if(inflparams->flags&DE_DEFLATEFLAG_ISZLIB) {
52 ret = mz_inflateInit(&strm);
54 else {
55 ret = mz_inflateInit2(&strm, -MZ_DEFAULT_WINDOW_BITS);
57 if(ret!=MZ_OK) {
58 de_dfilter_set_errorf(c, dres, modname, "Inflate error");
59 goto done;
62 if(inflparams->starting_dict) {
63 inflate_state *pDecomp = (inflate_state *)strm.state;
65 de_memcpy(pDecomp->m_dict, inflparams->starting_dict, 32768);
68 stream_open_flag = 1;
70 input_cur_pos = dcmpri->pos;
72 inbuf_num_valid_bytes = 0;
73 inbuf_num_consumed_bytes = 0;
75 de_dbg2(c, "inflating up to %d bytes", (int)dcmpri->len);
77 while(1) {
78 de_dbg3(c, "input remaining: %d", (int)(dcmpri->pos+dcmpri->len-input_cur_pos));
80 // If we have written enough bytes, stop.
81 if((dcmpro->len_known) && (nbytes_written_total >= dcmpro->expected_len)) {
82 break;
85 if(inbuf_num_consumed_bytes>0) {
86 if(inbuf_num_valid_bytes>inbuf_num_consumed_bytes) {
87 // Move unconsumed bytes to the beginning of the input buffer
88 de_memmove(inbuf, &inbuf[inbuf_num_consumed_bytes], (size_t)(inbuf_num_valid_bytes-inbuf_num_consumed_bytes));
89 inbuf_num_valid_bytes -= inbuf_num_consumed_bytes;
90 inbuf_num_consumed_bytes = 0;
92 else {
93 inbuf_num_valid_bytes = 0;
94 inbuf_num_consumed_bytes = 0;
98 nbytes_to_read = dcmpri->pos+dcmpri->len-input_cur_pos;
99 if(nbytes_to_read>DE_DFL_INBUF_SIZE-inbuf_num_valid_bytes) {
100 nbytes_to_read = DE_DFL_INBUF_SIZE-inbuf_num_valid_bytes;
103 // top off input buffer
104 dbuf_read(dcmpri->f, &inbuf[inbuf_num_valid_bytes], input_cur_pos, nbytes_to_read);
105 input_cur_pos += nbytes_to_read;
106 inbuf_num_valid_bytes += nbytes_to_read;
108 strm.next_in = inbuf;
109 strm.avail_in = (unsigned int)inbuf_num_valid_bytes;
110 orig_avail_in = strm.avail_in;
112 strm.next_out = outbuf;
113 strm.avail_out = DE_DFL_OUTBUF_SIZE;
115 ret = mz_inflate(&strm, MZ_SYNC_FLUSH);
117 if(ret!=MZ_STREAM_END && ret!=MZ_OK) {
118 de_dfilter_set_errorf(c, dres, modname, "Inflate error (%d)", (int)ret);
119 goto done;
122 output_bytes_this_time = DE_DFL_OUTBUF_SIZE - strm.avail_out;
123 de_dbg3(c, "got %d output bytes", (int)output_bytes_this_time);
125 nbytes_to_write = output_bytes_this_time;
126 if((dcmpro->len_known) &&
127 (nbytes_to_write > dcmpro->expected_len - nbytes_written_total))
129 nbytes_to_write = dcmpro->expected_len - nbytes_written_total;
131 dbuf_write(dcmpro->f, outbuf, nbytes_to_write);
132 nbytes_written_total += nbytes_to_write;
134 if(ret==MZ_STREAM_END) {
135 de_dbg2(c, "inflate finished normally");
136 ok = 1;
137 goto done;
140 inbuf_num_consumed_bytes_this_time = (i64)(orig_avail_in - strm.avail_in);
141 if(inbuf_num_consumed_bytes_this_time<1 && output_bytes_this_time<1) {
142 de_dfilter_set_errorf(c, dres, modname, "Inflate error");
143 goto done;
145 inbuf_num_consumed_bytes += inbuf_num_consumed_bytes_this_time;
148 done:
149 if(ok) {
150 dres->bytes_consumed = (i64)strm.total_in;
151 dres->bytes_consumed_valid = 1;
152 de_dbg2(c, "inflated %u to %u bytes", (unsigned int)strm.total_in,
153 (unsigned int)strm.total_out);
155 if(stream_open_flag) {
156 mz_inflateEnd(&strm);
158 de_free(c, inbuf);
159 de_free(c, outbuf);
162 // flags:
163 // DE_DEFLATEFLAG_ISZLIB
164 // DE_DEFLATEFLAG_USEMAXUNCMPRSIZE
165 int fmtutil_decompress_deflate(dbuf *inf, i64 inputstart, i64 inputsize, dbuf *outf,
166 i64 maxuncmprsize, i64 *bytes_consumed, unsigned int flags)
168 deark *c = inf->c;
169 struct de_dfilter_results dres;
170 struct de_dfilter_in_params dcmpri;
171 struct de_dfilter_out_params dcmpro;
172 struct de_inflate_params inflparams;
174 de_dfilter_init_objects(c, &dcmpri, &dcmpro, &dres);
175 if(bytes_consumed) *bytes_consumed = 0;
177 dcmpri.f = inf;
178 dcmpri.pos = inputstart;
179 dcmpri.len = inputsize;
181 dcmpro.f = outf;
182 if(flags & DE_DEFLATEFLAG_USEMAXUNCMPRSIZE) {
183 dcmpro.len_known = 1;
184 dcmpro.expected_len = maxuncmprsize;
185 flags -= DE_DEFLATEFLAG_USEMAXUNCMPRSIZE;
188 de_zeromem(&inflparams, sizeof(struct de_inflate_params));
189 inflparams.flags = flags;
190 fmtutil_inflate_codectype1(c, &dcmpri, &dcmpro, &dres, (void*)&inflparams);
192 if(bytes_consumed && dres.bytes_consumed_valid) {
193 *bytes_consumed = dres.bytes_consumed;
196 if(dres.errcode != 0) {
197 de_err(c, "%s", de_dfilter_get_errmsg(c, &dres));
198 return 0;
200 return 1;
203 // flags:
204 // DE_DEFLATEFLAG_ISZLIB
205 void fmtutil_decompress_deflate_ex(deark *c, struct de_dfilter_in_params *dcmpri,
206 struct de_dfilter_out_params *dcmpro, struct de_dfilter_results *dres,
207 unsigned int flags)
209 struct de_inflate_params inflparams;
211 de_zeromem(&inflparams, sizeof(struct de_inflate_params));
212 inflparams.flags = flags;
213 fmtutil_inflate_codectype1(c, dcmpri, dcmpro, dres, (void*)&inflparams);
216 struct fmtutil_tdefl_ctx {
217 deark *c;
218 tdefl_compressor pComp;
221 static mz_bool my_fmtutil_tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
223 dbuf *f = (dbuf*)pUser;
225 dbuf_write(f, (const u8*)pBuf, (i64)len);
226 return MZ_TRUE;
229 struct fmtutil_tdefl_ctx *fmtutil_tdefl_create(deark *c, dbuf *outf, int flags)
231 struct fmtutil_tdefl_ctx *tdctx = NULL;
233 tdctx = de_malloc(c, sizeof(struct fmtutil_tdefl_ctx));
234 tdctx->c = c;
235 tdefl_init(&tdctx->pComp, my_fmtutil_tdefl_output_buffer_putter, (void*)outf,
236 flags);
237 return tdctx;
240 static enum fmtutil_tdefl_status tdefl_status_to_fmtutil(tdefl_status n)
242 switch(n) {
243 case TDEFL_STATUS_BAD_PARAM: return FMTUTIL_TDEFL_STATUS_BAD_PARAM;
244 case TDEFL_STATUS_PUT_BUF_FAILED: return FMTUTIL_TDEFL_STATUS_PUT_BUF_FAILED;
245 case TDEFL_STATUS_OKAY: return FMTUTIL_TDEFL_STATUS_OKAY;
246 case TDEFL_STATUS_DONE: return FMTUTIL_TDEFL_STATUS_DONE;
248 return FMTUTIL_TDEFL_STATUS_PUT_BUF_FAILED;
251 static tdefl_flush fmtutil_flush_to_tdefl(enum fmtutil_tdefl_flush n)
253 switch(n) {
254 case FMTUTIL_TDEFL_NO_FLUSH: return TDEFL_NO_FLUSH;
255 case FMTUTIL_TDEFL_SYNC_FLUSH: return TDEFL_SYNC_FLUSH;
256 case FMTUTIL_TDEFL_FULL_FLUSH: return TDEFL_FULL_FLUSH;
257 case FMTUTIL_TDEFL_FINISH: return TDEFL_FINISH ;
259 return TDEFL_NO_FLUSH;
262 enum fmtutil_tdefl_status fmtutil_tdefl_compress_buffer(struct fmtutil_tdefl_ctx *tdctx,
263 const void *pIn_buf, size_t in_buf_size, enum fmtutil_tdefl_flush flush)
265 tdefl_status st;
267 st = tdefl_compress_buffer(&tdctx->pComp, pIn_buf, in_buf_size,
268 fmtutil_flush_to_tdefl(flush));
269 return tdefl_status_to_fmtutil(st);
272 void fmtutil_tdefl_destroy(struct fmtutil_tdefl_ctx *tdctx)
274 deark *c;
276 if(!tdctx) return;
277 c = tdctx->c;
278 de_free(c, tdctx);
281 unsigned int fmtutil_tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
282 int strategy)
284 return (unsigned int)tdefl_create_comp_flags_from_zip_params(level, window_bits,
285 strategy);