PeriDyno 0.8.2
miniz.c
Go to the documentation of this file.
1/**************************************************************************
2 *
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#include "miniz.h"
28
29typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
30typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
31typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37/* ------------------- zlib-style API's */
38
39mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
40{
41 mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
42 size_t block_len = buf_len % 5552;
43 if (!ptr)
44 return MZ_ADLER32_INIT;
45 while (buf_len)
46 {
47 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
48 {
49 s1 += ptr[0], s2 += s1;
50 s1 += ptr[1], s2 += s1;
51 s1 += ptr[2], s2 += s1;
52 s1 += ptr[3], s2 += s1;
53 s1 += ptr[4], s2 += s1;
54 s1 += ptr[5], s2 += s1;
55 s1 += ptr[6], s2 += s1;
56 s1 += ptr[7], s2 += s1;
57 }
58 for (; i < block_len; ++i)
59 s1 += *ptr++, s2 += s1;
60 s1 %= 65521U, s2 %= 65521U;
61 buf_len -= block_len;
62 block_len = 5552;
63 }
64 return (s2 << 16) + s1;
65}
66
67/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
68#if 0
69 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
70 {
71 static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
72 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
73 mz_uint32 crcu32 = (mz_uint32)crc;
74 if (!ptr)
75 return MZ_CRC32_INIT;
76 crcu32 = ~crcu32;
77 while (buf_len--)
78 {
79 mz_uint8 b = *ptr++;
80 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
81 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
82 }
83 return ~crcu32;
84 }
85#else
86/* Faster, but larger CPU cache footprint.
87 */
88mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
89{
90 static const mz_uint32 s_crc_table[256] =
91 {
92 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
93 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
94 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
95 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
96 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
97 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
98 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
99 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
100 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
101 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
102 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
103 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
104 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
105 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
106 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
107 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
108 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
109 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
110 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
111 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
112 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
113 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
114 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
115 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
116 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
117 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
118 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
119 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
120 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
121 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
122 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
123 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
124 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
125 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
126 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
127 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
128 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
129 };
130
131 mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
132 const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
133
134 while (buf_len >= 4)
135 {
136 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
137 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
138 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
139 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
140 pByte_buf += 4;
141 buf_len -= 4;
142 }
143
144 while (buf_len)
145 {
146 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
147 ++pByte_buf;
148 --buf_len;
149 }
150
151 return ~crc32;
152}
153#endif
154
155void mz_free(void *p)
156{
157 MZ_FREE(p);
158}
159
160void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
161{
162 (void)opaque, (void)items, (void)size;
163 return MZ_MALLOC(items * size);
164}
165void miniz_def_free_func(void *opaque, void *address)
166{
167 (void)opaque, (void)address;
168 MZ_FREE(address);
169}
170void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
171{
172 (void)opaque, (void)address, (void)items, (void)size;
173 return MZ_REALLOC(address, items * size);
174}
175
176const char *mz_version(void)
177{
178 return MZ_VERSION;
179}
180
181#ifndef MINIZ_NO_ZLIB_APIS
182
183int mz_deflateInit(mz_streamp pStream, int level)
184{
186}
187
188int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
189{
190 tdefl_compressor *pComp;
191 mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
192
193 if (!pStream)
194 return MZ_STREAM_ERROR;
195 if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
196 return MZ_PARAM_ERROR;
197
198 pStream->data_type = 0;
199 pStream->adler = MZ_ADLER32_INIT;
200 pStream->msg = NULL;
201 pStream->reserved = 0;
202 pStream->total_in = 0;
203 pStream->total_out = 0;
204 if (!pStream->zalloc)
205 pStream->zalloc = miniz_def_alloc_func;
206 if (!pStream->zfree)
207 pStream->zfree = miniz_def_free_func;
208
209 pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
210 if (!pComp)
211 return MZ_MEM_ERROR;
212
213 pStream->state = (struct mz_internal_state *)pComp;
214
215 if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
216 {
217 mz_deflateEnd(pStream);
218 return MZ_PARAM_ERROR;
219 }
220
221 return MZ_OK;
222}
223
225{
226 if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
227 return MZ_STREAM_ERROR;
228 pStream->total_in = pStream->total_out = 0;
229 tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
230 return MZ_OK;
231}
232
233int mz_deflate(mz_streamp pStream, int flush)
234{
235 size_t in_bytes, out_bytes;
236 mz_ulong orig_total_in, orig_total_out;
237 int mz_status = MZ_OK;
238
239 if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
240 return MZ_STREAM_ERROR;
241 if (!pStream->avail_out)
242 return MZ_BUF_ERROR;
243
244 if (flush == MZ_PARTIAL_FLUSH)
245 flush = MZ_SYNC_FLUSH;
246
247 if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
248 return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
249
250 orig_total_in = pStream->total_in;
251 orig_total_out = pStream->total_out;
252 for (;;)
253 {
254 tdefl_status defl_status;
255 in_bytes = pStream->avail_in;
256 out_bytes = pStream->avail_out;
257
258 defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
259 pStream->next_in += (mz_uint)in_bytes;
260 pStream->avail_in -= (mz_uint)in_bytes;
261 pStream->total_in += (mz_uint)in_bytes;
262 pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
263
264 pStream->next_out += (mz_uint)out_bytes;
265 pStream->avail_out -= (mz_uint)out_bytes;
266 pStream->total_out += (mz_uint)out_bytes;
267
268 if (defl_status < 0)
269 {
270 mz_status = MZ_STREAM_ERROR;
271 break;
272 }
273 else if (defl_status == TDEFL_STATUS_DONE)
274 {
275 mz_status = MZ_STREAM_END;
276 break;
277 }
278 else if (!pStream->avail_out)
279 break;
280 else if ((!pStream->avail_in) && (flush != MZ_FINISH))
281 {
282 if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
283 break;
284 return MZ_BUF_ERROR; /* Can't make forward progress without some input.
285 */
286 }
287 }
288 return mz_status;
289}
290
292{
293 if (!pStream)
294 return MZ_STREAM_ERROR;
295 if (pStream->state)
296 {
297 pStream->zfree(pStream->opaque, pStream->state);
298 pStream->state = NULL;
299 }
300 return MZ_OK;
301}
302
304{
305 (void)pStream;
306 /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
307 return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
308}
309
310int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
311{
312 int status;
313 mz_stream stream;
314 memset(&stream, 0, sizeof(stream));
315
316 /* In case mz_ulong is 64-bits (argh I hate longs). */
317 if ((source_len | *pDest_len) > 0xFFFFFFFFU)
318 return MZ_PARAM_ERROR;
319
320 stream.next_in = pSource;
321 stream.avail_in = (mz_uint32)source_len;
322 stream.next_out = pDest;
323 stream.avail_out = (mz_uint32) * pDest_len;
324
325 status = mz_deflateInit(&stream, level);
326 if (status != MZ_OK)
327 return status;
328
329 status = mz_deflate(&stream, MZ_FINISH);
330 if (status != MZ_STREAM_END)
331 {
332 mz_deflateEnd(&stream);
333 return (status == MZ_OK) ? MZ_BUF_ERROR : status;
334 }
335
336 *pDest_len = stream.total_out;
337 return mz_deflateEnd(&stream);
338}
339
340int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
341{
342 return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
343}
344
346{
347 return mz_deflateBound(NULL, source_len);
348}
349
350typedef struct
351{
353 mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
358
359int mz_inflateInit2(mz_streamp pStream, int window_bits)
360{
361 inflate_state *pDecomp;
362 if (!pStream)
363 return MZ_STREAM_ERROR;
364 if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
365 return MZ_PARAM_ERROR;
366
367 pStream->data_type = 0;
368 pStream->adler = 0;
369 pStream->msg = NULL;
370 pStream->total_in = 0;
371 pStream->total_out = 0;
372 pStream->reserved = 0;
373 if (!pStream->zalloc)
374 pStream->zalloc = miniz_def_alloc_func;
375 if (!pStream->zfree)
376 pStream->zfree = miniz_def_free_func;
377
378 pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
379 if (!pDecomp)
380 return MZ_MEM_ERROR;
381
382 pStream->state = (struct mz_internal_state *)pDecomp;
383
384 tinfl_init(&pDecomp->m_decomp);
385 pDecomp->m_dict_ofs = 0;
386 pDecomp->m_dict_avail = 0;
388 pDecomp->m_first_call = 1;
389 pDecomp->m_has_flushed = 0;
390 pDecomp->m_window_bits = window_bits;
391
392 return MZ_OK;
393}
394
396{
398}
399
400int mz_inflate(mz_streamp pStream, int flush)
401{
402 inflate_state *pState;
403 mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
404 size_t in_bytes, out_bytes, orig_avail_in;
405 tinfl_status status;
406
407 if ((!pStream) || (!pStream->state))
408 return MZ_STREAM_ERROR;
409 if (flush == MZ_PARTIAL_FLUSH)
410 flush = MZ_SYNC_FLUSH;
411 if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
412 return MZ_STREAM_ERROR;
413
414 pState = (inflate_state *)pStream->state;
415 if (pState->m_window_bits > 0)
416 decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
417 orig_avail_in = pStream->avail_in;
418
419 first_call = pState->m_first_call;
420 pState->m_first_call = 0;
421 if (pState->m_last_status < 0)
422 return MZ_DATA_ERROR;
423
424 if (pState->m_has_flushed && (flush != MZ_FINISH))
425 return MZ_STREAM_ERROR;
426 pState->m_has_flushed |= (flush == MZ_FINISH);
427
428 if ((flush == MZ_FINISH) && (first_call))
429 {
430 /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
432 in_bytes = pStream->avail_in;
433 out_bytes = pStream->avail_out;
434 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
435 pState->m_last_status = status;
436 pStream->next_in += (mz_uint)in_bytes;
437 pStream->avail_in -= (mz_uint)in_bytes;
438 pStream->total_in += (mz_uint)in_bytes;
439 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
440 pStream->next_out += (mz_uint)out_bytes;
441 pStream->avail_out -= (mz_uint)out_bytes;
442 pStream->total_out += (mz_uint)out_bytes;
443
444 if (status < 0)
445 return MZ_DATA_ERROR;
446 else if (status != TINFL_STATUS_DONE)
447 {
449 return MZ_BUF_ERROR;
450 }
451 return MZ_STREAM_END;
452 }
453 /* flush != MZ_FINISH then we must assume there's more input. */
454 if (flush != MZ_FINISH)
455 decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
456
457 if (pState->m_dict_avail)
458 {
459 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
460 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
461 pStream->next_out += n;
462 pStream->avail_out -= n;
463 pStream->total_out += n;
464 pState->m_dict_avail -= n;
465 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
466 return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
467 }
468
469 for (;;)
470 {
471 in_bytes = pStream->avail_in;
472 out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
473
474 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
475 pState->m_last_status = status;
476
477 pStream->next_in += (mz_uint)in_bytes;
478 pStream->avail_in -= (mz_uint)in_bytes;
479 pStream->total_in += (mz_uint)in_bytes;
480 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
481
482 pState->m_dict_avail = (mz_uint)out_bytes;
483
484 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
485 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
486 pStream->next_out += n;
487 pStream->avail_out -= n;
488 pStream->total_out += n;
489 pState->m_dict_avail -= n;
490 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
491
492 if (status < 0)
493 return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
494 else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
495 return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
496 else if (flush == MZ_FINISH)
497 {
498 /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
499 if (status == TINFL_STATUS_DONE)
500 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
501 /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
502 else if (!pStream->avail_out)
503 return MZ_BUF_ERROR;
504 }
505 else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
506 break;
507 }
508
509 return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
510}
511
513{
514 if (!pStream)
515 return MZ_STREAM_ERROR;
516 if (pStream->state)
517 {
518 pStream->zfree(pStream->opaque, pStream->state);
519 pStream->state = NULL;
520 }
521 return MZ_OK;
522}
523
524int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
525{
526 mz_stream stream;
527 int status;
528 memset(&stream, 0, sizeof(stream));
529
530 /* In case mz_ulong is 64-bits (argh I hate longs). */
531 if ((source_len | *pDest_len) > 0xFFFFFFFFU)
532 return MZ_PARAM_ERROR;
533
534 stream.next_in = pSource;
535 stream.avail_in = (mz_uint32)source_len;
536 stream.next_out = pDest;
537 stream.avail_out = (mz_uint32) * pDest_len;
538
539 status = mz_inflateInit(&stream);
540 if (status != MZ_OK)
541 return status;
542
543 status = mz_inflate(&stream, MZ_FINISH);
544 if (status != MZ_STREAM_END)
545 {
546 mz_inflateEnd(&stream);
547 return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
548 }
549 *pDest_len = stream.total_out;
550
551 return mz_inflateEnd(&stream);
552}
553
554const char *mz_error(int err)
555{
556 static struct
557 {
558 int m_err;
559 const char *m_pDesc;
560 } s_error_descs[] =
561 {
562 { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
563 { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
564 };
565 mz_uint i;
566 for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
567 if (s_error_descs[i].m_err == err)
568 return s_error_descs[i].m_pDesc;
569 return NULL;
570}
571
572#endif /*MINIZ_NO_ZLIB_APIS */
573
574#ifdef __cplusplus
575}
576#endif
577
578/*
579 This is free and unencumbered software released into the public domain.
580
581 Anyone is free to copy, modify, publish, use, compile, sell, or
582 distribute this software, either in source code form or as a compiled
583 binary, for any purpose, commercial or non-commercial, and by any
584 means.
585
586 In jurisdictions that recognize copyright laws, the author or authors
587 of this software dedicate any and all copyright interest in the
588 software to the public domain. We make this dedication for the benefit
589 of the public at large and to the detriment of our heirs and
590 successors. We intend this dedication to be an overt act of
591 relinquishment in perpetuity of all present and future rights to this
592 software under copyright law.
593
594 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
595 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
596 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
597 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
598 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
599 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
600 OTHER DEALINGS IN THE SOFTWARE.
601
602 For more information, please refer to <http://unlicense.org/>
603*/
604/**************************************************************************
605 *
606 * Copyright 2013-2014 RAD Game Tools and Valve Software
607 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
608 * All Rights Reserved.
609 *
610 * Permission is hereby granted, free of charge, to any person obtaining a copy
611 * of this software and associated documentation files (the "Software"), to deal
612 * in the Software without restriction, including without limitation the rights
613 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
614 * copies of the Software, and to permit persons to whom the Software is
615 * furnished to do so, subject to the following conditions:
616 *
617 * The above copyright notice and this permission notice shall be included in
618 * all copies or substantial portions of the Software.
619 *
620 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
621 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
622 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
623 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
624 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
625 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
626 * THE SOFTWARE.
627 *
628 **************************************************************************/
629
630
631
632
633#ifdef __cplusplus
634extern "C" {
635#endif
636
637/* ------------------- Low-level Compression (independent from all decompression API's) */
638
639/* Purposely making these tables static for faster init and thread safety. */
640static const mz_uint16 s_tdefl_len_sym[256] =
641 {
642 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
643 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
644 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
645 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
646 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
647 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
648 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
649 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285
650 };
651
652static const mz_uint8 s_tdefl_len_extra[256] =
653 {
654 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
655 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
656 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
657 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0
658 };
659
661 {
662 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
663 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
664 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
665 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
666 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
667 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
668 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
669 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
670 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
671 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
672 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
673 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
674 };
675
677 {
678 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
679 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
680 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
681 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
682 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
683 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
684 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
685 7, 7, 7, 7, 7, 7, 7, 7
686 };
687
689 {
690 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
691 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
692 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
693 };
694
696 {
697 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
698 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
699 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
700 };
701
702/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
703typedef struct
704{
705 mz_uint16 m_key, m_sym_index;
708{
709 mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
710 tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
711 MZ_CLEAR_OBJ(hist);
712 for (i = 0; i < num_syms; i++)
713 {
714 mz_uint freq = pSyms0[i].m_key;
715 hist[freq & 0xFF]++;
716 hist[256 + ((freq >> 8) & 0xFF)]++;
717 }
718 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
719 total_passes--;
720 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
721 {
722 const mz_uint32 *pHist = &hist[pass << 8];
723 mz_uint offsets[256], cur_ofs = 0;
724 for (i = 0; i < 256; i++)
725 {
726 offsets[i] = cur_ofs;
727 cur_ofs += pHist[i];
728 }
729 for (i = 0; i < num_syms; i++)
730 pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
731 {
732 tdefl_sym_freq *t = pCur_syms;
733 pCur_syms = pNew_syms;
734 pNew_syms = t;
735 }
736 }
737 return pCur_syms;
738}
739
740/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
742{
743 int root, leaf, next, avbl, used, dpth;
744 if (n == 0)
745 return;
746 else if (n == 1)
747 {
748 A[0].m_key = 1;
749 return;
750 }
751 A[0].m_key += A[1].m_key;
752 root = 0;
753 leaf = 2;
754 for (next = 1; next < n - 1; next++)
755 {
756 if (leaf >= n || A[root].m_key < A[leaf].m_key)
757 {
758 A[next].m_key = A[root].m_key;
759 A[root++].m_key = (mz_uint16)next;
760 }
761 else
762 A[next].m_key = A[leaf++].m_key;
763 if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
764 {
765 A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
766 A[root++].m_key = (mz_uint16)next;
767 }
768 else
769 A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
770 }
771 A[n - 2].m_key = 0;
772 for (next = n - 3; next >= 0; next--)
773 A[next].m_key = A[A[next].m_key].m_key + 1;
774 avbl = 1;
775 used = dpth = 0;
776 root = n - 2;
777 next = n - 1;
778 while (avbl > 0)
779 {
780 while (root >= 0 && (int)A[root].m_key == dpth)
781 {
782 used++;
783 root--;
784 }
785 while (avbl > used)
786 {
787 A[next--].m_key = (mz_uint16)(dpth);
788 avbl--;
789 }
790 avbl = 2 * used;
791 dpth++;
792 used = 0;
793 }
794}
795
796/* Limits canonical Huffman code table's max code size. */
797enum
798{
801static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
802{
803 int i;
804 mz_uint32 total = 0;
805 if (code_list_len <= 1)
806 return;
807 for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
808 pNum_codes[max_code_size] += pNum_codes[i];
809 for (i = max_code_size; i > 0; i--)
810 total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
811 while (total != (1UL << max_code_size))
812 {
813 pNum_codes[max_code_size]--;
814 for (i = max_code_size - 1; i > 0; i--)
815 if (pNum_codes[i])
816 {
817 pNum_codes[i]--;
818 pNum_codes[i + 1] += 2;
819 break;
820 }
821 total--;
822 }
823}
824
825static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
826{
827 int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
829 MZ_CLEAR_OBJ(num_codes);
830 if (static_table)
831 {
832 for (i = 0; i < table_len; i++)
833 num_codes[d->m_huff_code_sizes[table_num][i]]++;
834 }
835 else
836 {
838 int num_used_syms = 0;
839 const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
840 for (i = 0; i < table_len; i++)
841 if (pSym_count[i])
842 {
843 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
844 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
845 }
846
847 pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
848 tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
849
850 for (i = 0; i < num_used_syms; i++)
851 num_codes[pSyms[i].m_key]++;
852
853 tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
854
855 MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
856 MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
857 for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
858 for (l = num_codes[i]; l > 0; l--)
859 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
860 }
861
862 next_code[1] = 0;
863 for (j = 0, i = 2; i <= code_size_limit; i++)
864 next_code[i] = j = ((j + num_codes[i - 1]) << 1);
865
866 for (i = 0; i < table_len; i++)
867 {
868 mz_uint rev_code = 0, code, code_size;
869 if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
870 continue;
871 code = next_code[code_size]++;
872 for (l = code_size; l > 0; l--, code >>= 1)
873 rev_code = (rev_code << 1) | (code & 1);
874 d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
875 }
876}
877
878#define TDEFL_PUT_BITS(b, l) \
879 do \
880 { \
881 mz_uint bits = b; \
882 mz_uint len = l; \
883 MZ_ASSERT(bits <= ((1U << len) - 1U)); \
884 d->m_bit_buffer |= (bits << d->m_bits_in); \
885 d->m_bits_in += len; \
886 while (d->m_bits_in >= 8) \
887 { \
888 if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
889 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
890 d->m_bit_buffer >>= 8; \
891 d->m_bits_in -= 8; \
892 } \
893 } \
894 MZ_MACRO_END
895
896#define TDEFL_RLE_PREV_CODE_SIZE() \
897 { \
898 if (rle_repeat_count) \
899 { \
900 if (rle_repeat_count < 3) \
901 { \
902 d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
903 while (rle_repeat_count--) \
904 packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
905 } \
906 else \
907 { \
908 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
909 packed_code_sizes[num_packed_code_sizes++] = 16; \
910 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
911 } \
912 rle_repeat_count = 0; \
913 } \
914 }
915
916#define TDEFL_RLE_ZERO_CODE_SIZE() \
917 { \
918 if (rle_z_count) \
919 { \
920 if (rle_z_count < 3) \
921 { \
922 d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \
923 while (rle_z_count--) \
924 packed_code_sizes[num_packed_code_sizes++] = 0; \
925 } \
926 else if (rle_z_count <= 10) \
927 { \
928 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \
929 packed_code_sizes[num_packed_code_sizes++] = 17; \
930 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
931 } \
932 else \
933 { \
934 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \
935 packed_code_sizes[num_packed_code_sizes++] = 18; \
936 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
937 } \
938 rle_z_count = 0; \
939 } \
940 }
941
942static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
943
945{
946 int num_lit_codes, num_dist_codes, num_bit_lengths;
947 mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
948 mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
949
950 d->m_huff_count[0][256] = 1;
951
954
955 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
956 if (d->m_huff_code_sizes[0][num_lit_codes - 1])
957 break;
958 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
959 if (d->m_huff_code_sizes[1][num_dist_codes - 1])
960 break;
961
962 memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
963 memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
964 total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
965 num_packed_code_sizes = 0;
966 rle_z_count = 0;
967 rle_repeat_count = 0;
968
969 memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
970 for (i = 0; i < total_code_sizes_to_pack; i++)
971 {
972 mz_uint8 code_size = code_sizes_to_pack[i];
973 if (!code_size)
974 {
976 if (++rle_z_count == 138)
977 {
979 }
980 }
981 else
982 {
984 if (code_size != prev_code_size)
985 {
987 d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
988 packed_code_sizes[num_packed_code_sizes++] = code_size;
989 }
990 else if (++rle_repeat_count == 6)
991 {
993 }
994 }
995 prev_code_size = code_size;
996 }
997 if (rle_repeat_count)
998 {
1000 }
1001 else
1002 {
1004 }
1005
1007
1008 TDEFL_PUT_BITS(2, 2);
1009
1010 TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1011 TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1012
1013 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1014 if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1015 break;
1016 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1017 TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1018 for (i = 0; (int)i < num_bit_lengths; i++)
1020
1021 for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1022 {
1023 mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1025 TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1026 if (code >= 16)
1027 TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1028 }
1029}
1030
1032{
1033 mz_uint i;
1034 mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1035
1036 for (i = 0; i <= 143; ++i)
1037 *p++ = 8;
1038 for (; i <= 255; ++i)
1039 *p++ = 9;
1040 for (; i <= 279; ++i)
1041 *p++ = 7;
1042 for (; i <= 287; ++i)
1043 *p++ = 8;
1044
1045 memset(d->m_huff_code_sizes[1], 5, 32);
1046
1047 tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1049
1050 TDEFL_PUT_BITS(1, 2);
1051}
1052
1053static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1054
1055#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN &&MINIZ_HAS_64BIT_REGISTERS
1057{
1058 mz_uint flags;
1059 mz_uint8 *pLZ_codes;
1060 mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1061 mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1062 mz_uint64 bit_buffer = d->m_bit_buffer;
1063 mz_uint bits_in = d->m_bits_in;
1064
1065#define TDEFL_PUT_BITS_FAST(b, l) \
1066 { \
1067 bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1068 bits_in += (l); \
1069 }
1070
1071 flags = 1;
1072 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1073 {
1074 if (flags == 1)
1075 flags = *pLZ_codes++ | 0x100;
1076
1077 if (flags & 1)
1078 {
1079 mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1080 mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
1081 pLZ_codes += 3;
1082
1083 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1084 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1085 TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1086
1087 /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
1088 s0 = s_tdefl_small_dist_sym[match_dist & 511];
1089 n0 = s_tdefl_small_dist_extra[match_dist & 511];
1090 s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1091 n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1092 sym = (match_dist < 512) ? s0 : s1;
1093 num_extra_bits = (match_dist < 512) ? n0 : n1;
1094
1095 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1096 TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1097 TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1098 }
1099 else
1100 {
1101 mz_uint lit = *pLZ_codes++;
1102 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1103 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1104
1105 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1106 {
1107 flags >>= 1;
1108 lit = *pLZ_codes++;
1109 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1110 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1111
1112 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1113 {
1114 flags >>= 1;
1115 lit = *pLZ_codes++;
1116 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1117 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1118 }
1119 }
1120 }
1121
1122 if (pOutput_buf >= d->m_pOutput_buf_end)
1123 return MZ_FALSE;
1124
1125 *(mz_uint64 *)pOutput_buf = bit_buffer;
1126 pOutput_buf += (bits_in >> 3);
1127 bit_buffer >>= (bits_in & ~7);
1128 bits_in &= 7;
1129 }
1130
1131#undef TDEFL_PUT_BITS_FAST
1132
1133 d->m_pOutput_buf = pOutput_buf;
1134 d->m_bits_in = 0;
1135 d->m_bit_buffer = 0;
1136
1137 while (bits_in)
1138 {
1139 mz_uint32 n = MZ_MIN(bits_in, 16);
1140 TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1141 bit_buffer >>= n;
1142 bits_in -= n;
1143 }
1144
1145 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1146
1147 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1148}
1149#else
1151{
1152 mz_uint flags;
1153 mz_uint8 *pLZ_codes;
1154
1155 flags = 1;
1156 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1157 {
1158 if (flags == 1)
1159 flags = *pLZ_codes++ | 0x100;
1160 if (flags & 1)
1161 {
1162 mz_uint sym, num_extra_bits;
1163 mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1164 pLZ_codes += 3;
1165
1166 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1167 TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1168 TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1169
1170 if (match_dist < 512)
1171 {
1172 sym = s_tdefl_small_dist_sym[match_dist];
1173 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1174 }
1175 else
1176 {
1177 sym = s_tdefl_large_dist_sym[match_dist >> 8];
1178 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1179 }
1180 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1181 TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1182 TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1183 }
1184 else
1185 {
1186 mz_uint lit = *pLZ_codes++;
1187 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1188 TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1189 }
1190 }
1191
1192 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1193
1194 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1195}
1196#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
1197
1199{
1200 if (static_block)
1202 else
1204 return tdefl_compress_lz_codes(d);
1205}
1206
1207static int tdefl_flush_block(tdefl_compressor *d, int flush)
1208{
1209 mz_uint saved_bit_buf, saved_bits_in;
1210 mz_uint8 *pSaved_output_buf;
1211 mz_bool comp_block_succeeded = MZ_FALSE;
1212 int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
1213 mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
1214
1215 d->m_pOutput_buf = pOutput_buf_start;
1217
1219 d->m_output_flush_ofs = 0;
1221
1223 d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1224
1225 if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1226 {
1227 TDEFL_PUT_BITS(0x78, 8);
1228 TDEFL_PUT_BITS(0x01, 8);
1229 }
1230
1231 TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1232
1233 pSaved_output_buf = d->m_pOutput_buf;
1234 saved_bit_buf = d->m_bit_buffer;
1235 saved_bits_in = d->m_bits_in;
1236
1237 if (!use_raw_block)
1238 comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1239
1240 /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
1241 if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1243 {
1244 mz_uint i;
1245 d->m_pOutput_buf = pSaved_output_buf;
1246 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1247 TDEFL_PUT_BITS(0, 2);
1248 if (d->m_bits_in)
1249 {
1250 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1251 }
1252 for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1253 {
1254 TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1255 }
1256 for (i = 0; i < d->m_total_lz_bytes; ++i)
1257 {
1259 }
1260 }
1261 /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
1262 else if (!comp_block_succeeded)
1263 {
1264 d->m_pOutput_buf = pSaved_output_buf;
1265 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1267 }
1268
1269 if (flush)
1270 {
1271 if (flush == TDEFL_FINISH)
1272 {
1273 if (d->m_bits_in)
1274 {
1275 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1276 }
1278 {
1279 mz_uint i, a = d->m_adler32;
1280 for (i = 0; i < 4; i++)
1281 {
1282 TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1283 a <<= 8;
1284 }
1285 }
1286 }
1287 else
1288 {
1289 mz_uint i, z = 0;
1290 TDEFL_PUT_BITS(0, 3);
1291 if (d->m_bits_in)
1292 {
1293 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1294 }
1295 for (i = 2; i; --i, z ^= 0xFFFF)
1296 {
1297 TDEFL_PUT_BITS(z & 0xFFFF, 16);
1298 }
1299 }
1300 }
1301
1303
1304 memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1305 memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1306
1307 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1308 d->m_pLZ_flags = d->m_lz_code_buf;
1309 d->m_num_flags_left = 8;
1311 d->m_total_lz_bytes = 0;
1312 d->m_block_index++;
1313
1314 if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1315 {
1316 if (d->m_pPut_buf_func)
1317 {
1318 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1321 }
1322 else if (pOutput_buf_start == d->m_output_buf)
1323 {
1324 int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1325 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1326 d->m_out_buf_ofs += bytes_to_copy;
1327 if ((n -= bytes_to_copy) != 0)
1328 {
1329 d->m_output_flush_ofs = bytes_to_copy;
1331 }
1332 }
1333 else
1334 {
1335 d->m_out_buf_ofs += n;
1336 }
1337 }
1338
1339 return d->m_output_flush_remaining;
1340}
1341
1342#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1343#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1344static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1345{
1346 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1347 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1348 const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
1349 mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
1350 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1351 if (max_match_len <= match_len)
1352 return;
1353 for (;;)
1354 {
1355 for (;;)
1356 {
1357 if (--num_probes_left == 0)
1358 return;
1359#define TDEFL_PROBE \
1360 next_probe_pos = d->m_next[probe_pos]; \
1361 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1362 return; \
1363 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1364 if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
1365 break;
1369 }
1370 if (!dist)
1371 break;
1372 q = (const mz_uint16 *)(d->m_dict + probe_pos);
1373 if (TDEFL_READ_UNALIGNED_WORD(q) != s01)
1374 continue;
1375 p = s;
1376 probe_len = 32;
1377 do
1378 {
1379 } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
1380 (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0));
1381 if (!probe_len)
1382 {
1383 *pMatch_dist = dist;
1384 *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1385 break;
1386 }
1387 else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
1388 {
1389 *pMatch_dist = dist;
1390 if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1391 break;
1392 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1393 }
1394 }
1395}
1396#else
1397static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1398{
1399 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1400 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1401 const mz_uint8 *s = d->m_dict + pos, *p, *q;
1402 mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1403 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1404 if (max_match_len <= match_len)
1405 return;
1406 for (;;)
1407 {
1408 for (;;)
1409 {
1410 if (--num_probes_left == 0)
1411 return;
1412#define TDEFL_PROBE \
1413 next_probe_pos = d->m_next[probe_pos]; \
1414 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1415 return; \
1416 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1417 if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1418 break;
1422 }
1423 if (!dist)
1424 break;
1425 p = s;
1426 q = d->m_dict + probe_pos;
1427 for (probe_len = 0; probe_len < max_match_len; probe_len++)
1428 if (*p++ != *q++)
1429 break;
1430 if (probe_len > match_len)
1431 {
1432 *pMatch_dist = dist;
1433 if ((*pMatch_len = match_len = probe_len) == max_match_len)
1434 return;
1435 c0 = d->m_dict[pos + match_len];
1436 c1 = d->m_dict[pos + match_len - 1];
1437 }
1438 }
1439}
1440#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
1441
1442#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN
1443static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1444{
1445 /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
1446 mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
1447 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1448 mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1449
1450 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1451 {
1452 const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1453 mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1454 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1455 d->m_src_buf_left -= num_bytes_to_process;
1456 lookahead_size += num_bytes_to_process;
1457
1458 while (num_bytes_to_process)
1459 {
1460 mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1461 memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1462 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1463 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1464 d->m_pSrc += n;
1465 dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1466 num_bytes_to_process -= n;
1467 }
1468
1469 dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1470 if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1471 break;
1472
1473 while (lookahead_size >= 4)
1474 {
1475 mz_uint cur_match_dist, cur_match_len = 1;
1476 mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1477 mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
1478 mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1479 mz_uint probe_pos = d->m_hash[hash];
1480 d->m_hash[hash] = (mz_uint16)lookahead_pos;
1481
1482 if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1483 {
1484 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1485 const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1486 mz_uint32 probe_len = 32;
1487 do
1488 {
1489 } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
1490 (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0));
1491 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1492 if (!probe_len)
1493 cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1494
1495 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1496 {
1497 cur_match_len = 1;
1498 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1499 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1500 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1501 }
1502 else
1503 {
1504 mz_uint32 s0, s1;
1505 cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1506
1507 MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1508
1509 cur_match_dist--;
1510
1511 pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1512 *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1513 pLZ_code_buf += 3;
1514 *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1515
1516 s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1517 s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1518 d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1519
1520 d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1521 }
1522 }
1523 else
1524 {
1525 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1526 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1527 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1528 }
1529
1530 if (--num_flags_left == 0)
1531 {
1532 num_flags_left = 8;
1533 pLZ_flags = pLZ_code_buf++;
1534 }
1535
1536 total_lz_bytes += cur_match_len;
1537 lookahead_pos += cur_match_len;
1538 dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1539 cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1540 MZ_ASSERT(lookahead_size >= cur_match_len);
1541 lookahead_size -= cur_match_len;
1542
1543 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1544 {
1545 int n;
1546 d->m_lookahead_pos = lookahead_pos;
1547 d->m_lookahead_size = lookahead_size;
1548 d->m_dict_size = dict_size;
1549 d->m_total_lz_bytes = total_lz_bytes;
1550 d->m_pLZ_code_buf = pLZ_code_buf;
1551 d->m_pLZ_flags = pLZ_flags;
1552 d->m_num_flags_left = num_flags_left;
1553 if ((n = tdefl_flush_block(d, 0)) != 0)
1554 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1555 total_lz_bytes = d->m_total_lz_bytes;
1556 pLZ_code_buf = d->m_pLZ_code_buf;
1557 pLZ_flags = d->m_pLZ_flags;
1558 num_flags_left = d->m_num_flags_left;
1559 }
1560 }
1561
1562 while (lookahead_size)
1563 {
1564 mz_uint8 lit = d->m_dict[cur_pos];
1565
1566 total_lz_bytes++;
1567 *pLZ_code_buf++ = lit;
1568 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1569 if (--num_flags_left == 0)
1570 {
1571 num_flags_left = 8;
1572 pLZ_flags = pLZ_code_buf++;
1573 }
1574
1575 d->m_huff_count[0][lit]++;
1576
1577 lookahead_pos++;
1578 dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1579 cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1580 lookahead_size--;
1581
1582 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1583 {
1584 int n;
1585 d->m_lookahead_pos = lookahead_pos;
1586 d->m_lookahead_size = lookahead_size;
1587 d->m_dict_size = dict_size;
1588 d->m_total_lz_bytes = total_lz_bytes;
1589 d->m_pLZ_code_buf = pLZ_code_buf;
1590 d->m_pLZ_flags = pLZ_flags;
1591 d->m_num_flags_left = num_flags_left;
1592 if ((n = tdefl_flush_block(d, 0)) != 0)
1593 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1594 total_lz_bytes = d->m_total_lz_bytes;
1595 pLZ_code_buf = d->m_pLZ_code_buf;
1596 pLZ_flags = d->m_pLZ_flags;
1597 num_flags_left = d->m_num_flags_left;
1598 }
1599 }
1600 }
1601
1602 d->m_lookahead_pos = lookahead_pos;
1603 d->m_lookahead_size = lookahead_size;
1604 d->m_dict_size = dict_size;
1605 d->m_total_lz_bytes = total_lz_bytes;
1606 d->m_pLZ_code_buf = pLZ_code_buf;
1607 d->m_pLZ_flags = pLZ_flags;
1608 d->m_num_flags_left = num_flags_left;
1609 return MZ_TRUE;
1610}
1611#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1612
1614{
1615 d->m_total_lz_bytes++;
1616 *d->m_pLZ_code_buf++ = lit;
1617 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1618 if (--d->m_num_flags_left == 0)
1619 {
1620 d->m_num_flags_left = 8;
1621 d->m_pLZ_flags = d->m_pLZ_code_buf++;
1622 }
1623 d->m_huff_count[0][lit]++;
1624}
1625
1627{
1628 mz_uint32 s0, s1;
1629
1630 MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1631
1632 d->m_total_lz_bytes += match_len;
1633
1634 d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1635
1636 match_dist -= 1;
1637 d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1638 d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1639 d->m_pLZ_code_buf += 3;
1640
1641 *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1642 if (--d->m_num_flags_left == 0)
1643 {
1644 d->m_num_flags_left = 8;
1645 d->m_pLZ_flags = d->m_pLZ_code_buf++;
1646 }
1647
1648 s0 = s_tdefl_small_dist_sym[match_dist & 511];
1649 s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1650 d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1651
1652 if (match_len >= TDEFL_MIN_MATCH_LEN)
1653 d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1654}
1655
1657{
1658 const mz_uint8 *pSrc = d->m_pSrc;
1659 size_t src_buf_left = d->m_src_buf_left;
1660 tdefl_flush flush = d->m_flush;
1661
1662 while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1663 {
1664 mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1665 /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
1666 if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1667 {
1669 mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
1670 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1671 const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1672 src_buf_left -= num_bytes_to_process;
1673 d->m_lookahead_size += num_bytes_to_process;
1674 while (pSrc != pSrc_end)
1675 {
1676 mz_uint8 c = *pSrc++;
1677 d->m_dict[dst_pos] = c;
1678 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1679 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1680 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1681 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1682 d->m_hash[hash] = (mz_uint16)(ins_pos);
1683 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1684 ins_pos++;
1685 }
1686 }
1687 else
1688 {
1689 while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1690 {
1691 mz_uint8 c = *pSrc++;
1693 src_buf_left--;
1694 d->m_dict[dst_pos] = c;
1695 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1696 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1698 {
1699 mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1700 mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1701 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1702 d->m_hash[hash] = (mz_uint16)(ins_pos);
1703 }
1704 }
1705 }
1707 if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1708 break;
1709
1710 /* Simple lazy/greedy parsing state machine. */
1711 len_to_move = 1;
1712 cur_match_dist = 0;
1713 cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1716 {
1717 if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1718 {
1719 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1720 cur_match_len = 0;
1721 while (cur_match_len < d->m_lookahead_size)
1722 {
1723 if (d->m_dict[cur_pos + cur_match_len] != c)
1724 break;
1725 cur_match_len++;
1726 }
1727 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1728 cur_match_len = 0;
1729 else
1730 cur_match_dist = 1;
1731 }
1732 }
1733 else
1734 {
1735 tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1736 }
1737 if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
1738 {
1739 cur_match_dist = cur_match_len = 0;
1740 }
1741 if (d->m_saved_match_len)
1742 {
1743 if (cur_match_len > d->m_saved_match_len)
1744 {
1746 if (cur_match_len >= 128)
1747 {
1748 tdefl_record_match(d, cur_match_len, cur_match_dist);
1749 d->m_saved_match_len = 0;
1750 len_to_move = cur_match_len;
1751 }
1752 else
1753 {
1754 d->m_saved_lit = d->m_dict[cur_pos];
1755 d->m_saved_match_dist = cur_match_dist;
1756 d->m_saved_match_len = cur_match_len;
1757 }
1758 }
1759 else
1760 {
1762 len_to_move = d->m_saved_match_len - 1;
1763 d->m_saved_match_len = 0;
1764 }
1765 }
1766 else if (!cur_match_dist)
1767 tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1768 else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1769 {
1770 tdefl_record_match(d, cur_match_len, cur_match_dist);
1771 len_to_move = cur_match_len;
1772 }
1773 else
1774 {
1775 d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1776 d->m_saved_match_dist = cur_match_dist;
1777 d->m_saved_match_len = cur_match_len;
1778 }
1779 /* Move the lookahead forward by len_to_move bytes. */
1780 d->m_lookahead_pos += len_to_move;
1781 MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1782 d->m_lookahead_size -= len_to_move;
1783 d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1784 /* Check if it's time to flush the current LZ codes to the internal output buffer. */
1786 ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))))
1787 {
1788 int n;
1789 d->m_pSrc = pSrc;
1790 d->m_src_buf_left = src_buf_left;
1791 if ((n = tdefl_flush_block(d, 0)) != 0)
1792 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1793 }
1794 }
1795
1796 d->m_pSrc = pSrc;
1797 d->m_src_buf_left = src_buf_left;
1798 return MZ_TRUE;
1799}
1800
1802{
1803 if (d->m_pIn_buf_size)
1804 {
1805 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1806 }
1807
1808 if (d->m_pOut_buf_size)
1809 {
1811 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1812 d->m_output_flush_ofs += (mz_uint)n;
1814 d->m_out_buf_ofs += n;
1815
1817 }
1818
1820}
1821
1822tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
1823{
1824 if (!d)
1825 {
1826 if (pIn_buf_size)
1827 *pIn_buf_size = 0;
1828 if (pOut_buf_size)
1829 *pOut_buf_size = 0;
1831 }
1832
1833 d->m_pIn_buf = pIn_buf;
1834 d->m_pIn_buf_size = pIn_buf_size;
1835 d->m_pOut_buf = pOut_buf;
1836 d->m_pOut_buf_size = pOut_buf_size;
1837 d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1838 d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1839 d->m_out_buf_ofs = 0;
1840 d->m_flush = flush;
1841
1842 if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1843 (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1844 {
1845 if (pIn_buf_size)
1846 *pIn_buf_size = 0;
1847 if (pOut_buf_size)
1848 *pOut_buf_size = 0;
1850 }
1851 d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1852
1853 if ((d->m_output_flush_remaining) || (d->m_finished))
1855
1856#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES &&MINIZ_LITTLE_ENDIAN
1857 if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1858 ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1860 {
1861 if (!tdefl_compress_fast(d))
1862 return d->m_prev_return_status;
1863 }
1864 else
1865#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1866 {
1867 if (!tdefl_compress_normal(d))
1868 return d->m_prev_return_status;
1869 }
1870
1871 if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1872 d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1873
1874 if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1875 {
1876 if (tdefl_flush_block(d, flush) < 0)
1877 return d->m_prev_return_status;
1878 d->m_finished = (flush == TDEFL_FINISH);
1879 if (flush == TDEFL_FULL_FLUSH)
1880 {
1881 MZ_CLEAR_OBJ(d->m_hash);
1882 MZ_CLEAR_OBJ(d->m_next);
1883 d->m_dict_size = 0;
1884 }
1885 }
1886
1888}
1889
1890tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1891{
1893 return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1894}
1895
1896tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1897{
1898 d->m_pPut_buf_func = pPut_buf_func;
1899 d->m_pPut_buf_user = pPut_buf_user;
1900 d->m_flags = (mz_uint)(flags);
1901 d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
1902 d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
1903 d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
1905 MZ_CLEAR_OBJ(d->m_hash);
1908 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1909 d->m_pLZ_flags = d->m_lz_code_buf;
1910 d->m_num_flags_left = 8;
1915 d->m_adler32 = 1;
1916 d->m_pIn_buf = NULL;
1917 d->m_pOut_buf = NULL;
1918 d->m_pIn_buf_size = NULL;
1919 d->m_pOut_buf_size = NULL;
1921 d->m_pSrc = NULL;
1922 d->m_src_buf_left = 0;
1923 d->m_out_buf_ofs = 0;
1924 memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1925 memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1926 return TDEFL_STATUS_OKAY;
1927}
1928
1930{
1931 return d->m_prev_return_status;
1932}
1933
1935{
1936 return d->m_adler32;
1937}
1938
1939mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1940{
1941 tdefl_compressor *pComp;
1942 mz_bool succeeded;
1943 if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
1944 return MZ_FALSE;
1945 pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
1946 if (!pComp)
1947 return MZ_FALSE;
1948 succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
1949 succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
1950 MZ_FREE(pComp);
1951 return succeeded;
1952}
1953
1954typedef struct
1955{
1956 size_t m_size, m_capacity;
1960
1961static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
1962{
1964 size_t new_size = p->m_size + len;
1965 if (new_size > p->m_capacity)
1966 {
1967 size_t new_capacity = p->m_capacity;
1968 mz_uint8 *pNew_buf;
1969 if (!p->m_expandable)
1970 return MZ_FALSE;
1971 do
1972 {
1973 new_capacity = MZ_MAX(128U, new_capacity << 1U);
1974 } while (new_size > new_capacity);
1975 pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
1976 if (!pNew_buf)
1977 return MZ_FALSE;
1978 p->m_pBuf = pNew_buf;
1979 p->m_capacity = new_capacity;
1980 }
1981 memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
1982 p->m_size = new_size;
1983 return MZ_TRUE;
1984}
1985
1986void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
1987{
1988 tdefl_output_buffer out_buf;
1989 MZ_CLEAR_OBJ(out_buf);
1990 if (!pOut_len)
1991 return MZ_FALSE;
1992 else
1993 *pOut_len = 0;
1994 out_buf.m_expandable = MZ_TRUE;
1995 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
1996 return NULL;
1997 *pOut_len = out_buf.m_size;
1998 return out_buf.m_pBuf;
1999}
2000
2001size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2002{
2003 tdefl_output_buffer out_buf;
2004 MZ_CLEAR_OBJ(out_buf);
2005 if (!pOut_buf)
2006 return 0;
2007 out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2008 out_buf.m_capacity = out_buf_len;
2009 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2010 return 0;
2011 return out_buf.m_size;
2012}
2013
2014static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2015
2016/* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
2017mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2018{
2019 mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2020 if (window_bits > 0)
2021 comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2022
2023 if (!level)
2024 comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2025 else if (strategy == MZ_FILTERED)
2026 comp_flags |= TDEFL_FILTER_MATCHES;
2027 else if (strategy == MZ_HUFFMAN_ONLY)
2028 comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2029 else if (strategy == MZ_FIXED)
2030 comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2031 else if (strategy == MZ_RLE)
2032 comp_flags |= TDEFL_RLE_MATCHES;
2033
2034 return comp_flags;
2035}
2036
2037#ifdef _MSC_VER
2038#pragma warning(push)
2039#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
2040#endif
2041
2042/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2043 http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2044 This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
2045void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2046{
2047 /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2048 static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2050 tdefl_output_buffer out_buf;
2051 int i, bpl = w * num_chans, y, z;
2052 mz_uint32 c;
2053 *pLen_out = 0;
2054 if (!pComp)
2055 return NULL;
2056 MZ_CLEAR_OBJ(out_buf);
2057 out_buf.m_expandable = MZ_TRUE;
2058 out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2059 if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2060 {
2061 MZ_FREE(pComp);
2062 return NULL;
2063 }
2064 /* write dummy header */
2065 for (z = 41; z; --z)
2066 tdefl_output_buffer_putter(&z, 1, &out_buf);
2067 /* compress image data */
2068 tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2069 for (y = 0; y < h; ++y)
2070 {
2072 tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2073 }
2075 {
2076 MZ_FREE(pComp);
2077 MZ_FREE(out_buf.m_pBuf);
2078 return NULL;
2079 }
2080 /* write real header */
2081 *pLen_out = out_buf.m_size - 41;
2082 {
2083 static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2084 mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2085 0x0a, 0x1a, 0x0a, 0x00, 0x00,
2086 0x00, 0x0d, 0x49, 0x48, 0x44,
2087 0x52, 0x00, 0x00, 0x00, 0x00,
2088 0x00, 0x00, 0x00, 0x00, 0x08,
2089 0x00, 0x00, 0x00, 0x00, 0x00,
2090 0x00, 0x00, 0x00, 0x00, 0x00,
2091 0x00, 0x00, 0x49, 0x44, 0x41,
2092 0x54 };
2093 pnghdr[18] = (mz_uint8)(w >> 8);
2094 pnghdr[19] = (mz_uint8)w;
2095 pnghdr[22] = (mz_uint8)(h >> 8);
2096 pnghdr[22] = (mz_uint8)h;
2097 pnghdr[25] = chans[num_chans];
2098 pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2099 pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2100 pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2101 pnghdr[36] = (mz_uint8)*pLen_out;
2102 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2103 for (i = 0; i < 4; ++i, c <<= 8)
2104 ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2105 memcpy(out_buf.m_pBuf, pnghdr, 41);
2106 }
2107 /* write footer (IDAT CRC-32, followed by IEND chunk) */
2108 if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2109 {
2110 *pLen_out = 0;
2111 MZ_FREE(pComp);
2112 MZ_FREE(out_buf.m_pBuf);
2113 return NULL;
2114 }
2115 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2116 for (i = 0; i < 4; ++i, c <<= 8)
2117 (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2118 /* compute final size of file, grab compressed data buffer and return */
2119 *pLen_out += 57;
2120 MZ_FREE(pComp);
2121 return out_buf.m_pBuf;
2122}
2123void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2124{
2125 /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */
2126 return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2127}
2128
2129/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
2130/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
2131/* structure size and allocation mechanism. */
2133{
2134 return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2135}
2136
2138{
2139 MZ_FREE(pComp);
2140}
2141
2142#ifdef _MSC_VER
2143#pragma warning(pop)
2144#endif
2145
2146#ifdef __cplusplus
2147}
2148#endif
2149/**************************************************************************
2150 *
2151 * Copyright 2013-2014 RAD Game Tools and Valve Software
2152 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2153 * All Rights Reserved.
2154 *
2155 * Permission is hereby granted, free of charge, to any person obtaining a copy
2156 * of this software and associated documentation files (the "Software"), to deal
2157 * in the Software without restriction, including without limitation the rights
2158 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2159 * copies of the Software, and to permit persons to whom the Software is
2160 * furnished to do so, subject to the following conditions:
2161 *
2162 * The above copyright notice and this permission notice shall be included in
2163 * all copies or substantial portions of the Software.
2164 *
2165 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2166 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2167 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2168 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2169 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2170 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2171 * THE SOFTWARE.
2172 *
2173 **************************************************************************/
2174
2175
2176
2177#ifdef __cplusplus
2178extern "C" {
2179#endif
2180
2181/* ------------------- Low-level Decompression (completely independent from all compression API's) */
2182
2183#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2184#define TINFL_MEMSET(p, c, l) memset(p, c, l)
2185
2186#define TINFL_CR_BEGIN \
2187 switch (r->m_state) \
2188 { \
2189 case 0:
2190#define TINFL_CR_RETURN(state_index, result) \
2191 do \
2192 { \
2193 status = result; \
2194 r->m_state = state_index; \
2195 goto common_exit; \
2196 case state_index: \
2197 ; \
2198 } \
2199 MZ_MACRO_END
2200#define TINFL_CR_RETURN_FOREVER(state_index, result) \
2201 do \
2202 { \
2203 for (;;) \
2204 { \
2205 TINFL_CR_RETURN(state_index, result); \
2206 } \
2207 } \
2208 MZ_MACRO_END
2209#define TINFL_CR_FINISH }
2210
2211#define TINFL_GET_BYTE(state_index, c) \
2212 do \
2213 { \
2214 while (pIn_buf_cur >= pIn_buf_end) \
2215 { \
2216 TINFL_CR_RETURN(state_index, (decomp_flags &TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2217 } \
2218 c = *pIn_buf_cur++; \
2219 } \
2220 MZ_MACRO_END
2221
2222#define TINFL_NEED_BITS(state_index, n) \
2223 do \
2224 { \
2225 mz_uint c; \
2226 TINFL_GET_BYTE(state_index, c); \
2227 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2228 num_bits += 8; \
2229 } while (num_bits < (mz_uint)(n))
2230#define TINFL_SKIP_BITS(state_index, n) \
2231 do \
2232 { \
2233 if (num_bits < (mz_uint)(n)) \
2234 { \
2235 TINFL_NEED_BITS(state_index, n); \
2236 } \
2237 bit_buf >>= (n); \
2238 num_bits -= (n); \
2239 } \
2240 MZ_MACRO_END
2241#define TINFL_GET_BITS(state_index, b, n) \
2242 do \
2243 { \
2244 if (num_bits < (mz_uint)(n)) \
2245 { \
2246 TINFL_NEED_BITS(state_index, n); \
2247 } \
2248 b = bit_buf & ((1 << (n)) - 1); \
2249 bit_buf >>= (n); \
2250 num_bits -= (n); \
2251 } \
2252 MZ_MACRO_END
2253
2254/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
2255/* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */
2256/* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */
2257/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
2258#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
2259 do \
2260 { \
2261 temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
2262 if (temp >= 0) \
2263 { \
2264 code_len = temp >> 9; \
2265 if ((code_len) && (num_bits >= code_len)) \
2266 break; \
2267 } \
2268 else if (num_bits > TINFL_FAST_LOOKUP_BITS) \
2269 { \
2270 code_len = TINFL_FAST_LOOKUP_BITS; \
2271 do \
2272 { \
2273 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2274 } while ((temp < 0) && (num_bits >= (code_len + 1))); \
2275 if (temp >= 0) \
2276 break; \
2277 } \
2278 TINFL_GET_BYTE(state_index, c); \
2279 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2280 num_bits += 8; \
2281 } while (num_bits < 15);
2282
2283/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
2284/* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */
2285/* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */
2286/* The slow path is only executed at the very end of the input buffer. */
2287/* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */
2288/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
2289#define TINFL_HUFF_DECODE(state_index, sym, pHuff) \
2290 do \
2291 { \
2292 int temp; \
2293 mz_uint code_len, c; \
2294 if (num_bits < 15) \
2295 { \
2296 if ((pIn_buf_end - pIn_buf_cur) < 2) \
2297 { \
2298 TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
2299 } \
2300 else \
2301 { \
2302 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2303 pIn_buf_cur += 2; \
2304 num_bits += 16; \
2305 } \
2306 } \
2307 if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
2308 code_len = temp >> 9, temp &= 511; \
2309 else \
2310 { \
2311 code_len = TINFL_FAST_LOOKUP_BITS; \
2312 do \
2313 { \
2314 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2315 } while (temp < 0); \
2316 } \
2317 sym = temp; \
2318 bit_buf >>= code_len; \
2319 num_bits -= code_len; \
2320 } \
2321 MZ_MACRO_END
2322
2323tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
2324{
2325 static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
2326 static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
2327 static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
2328 static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
2329 static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
2330 static const int s_min_table_sizes[3] = { 257, 1, 4 };
2331
2333 mz_uint32 num_bits, dist, counter, num_extra;
2334 tinfl_bit_buf_t bit_buf;
2335 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2336 mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
2337 size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t) - 1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
2338
2339 /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */
2340 if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2341 {
2342 *pIn_buf_size = *pOut_buf_size = 0;
2344 }
2345
2346 num_bits = r->m_num_bits;
2347 bit_buf = r->m_bit_buf;
2348 dist = r->m_dist;
2349 counter = r->m_counter;
2350 num_extra = r->m_num_extra;
2351 dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2353
2354 bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2355 r->m_z_adler32 = r->m_check_adler32 = 1;
2356 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2357 {
2358 TINFL_GET_BYTE(1, r->m_zhdr0);
2359 TINFL_GET_BYTE(2, r->m_zhdr1);
2360 counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2361 if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2362 counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2363 if (counter)
2364 {
2366 }
2367 }
2368
2369 do
2370 {
2371 TINFL_GET_BITS(3, r->m_final, 3);
2372 r->m_type = r->m_final >> 1;
2373 if (r->m_type == 0)
2374 {
2375 TINFL_SKIP_BITS(5, num_bits & 7);
2376 for (counter = 0; counter < 4; ++counter)
2377 {
2378 if (num_bits)
2379 TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2380 else
2381 TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2382 }
2383 if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8))))
2384 {
2386 }
2387 while ((counter) && (num_bits))
2388 {
2389 TINFL_GET_BITS(51, dist, 8);
2390 while (pOut_buf_cur >= pOut_buf_end)
2391 {
2393 }
2394 *pOut_buf_cur++ = (mz_uint8)dist;
2395 counter--;
2396 }
2397 while (counter)
2398 {
2399 size_t n;
2400 while (pOut_buf_cur >= pOut_buf_end)
2401 {
2403 }
2404 while (pIn_buf_cur >= pIn_buf_end)
2405 {
2407 }
2408 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2409 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2410 pIn_buf_cur += n;
2411 pOut_buf_cur += n;
2412 counter -= (mz_uint)n;
2413 }
2414 }
2415 else if (r->m_type == 3)
2416 {
2418 }
2419 else
2420 {
2421 if (r->m_type == 1)
2422 {
2423 mz_uint8 *p = r->m_tables[0].m_code_size;
2424 mz_uint i;
2425 r->m_table_sizes[0] = 288;
2426 r->m_table_sizes[1] = 32;
2427 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2428 for (i = 0; i <= 143; ++i)
2429 *p++ = 8;
2430 for (; i <= 255; ++i)
2431 *p++ = 9;
2432 for (; i <= 279; ++i)
2433 *p++ = 7;
2434 for (; i <= 287; ++i)
2435 *p++ = 8;
2436 }
2437 else
2438 {
2439 for (counter = 0; counter < 3; counter++)
2440 {
2441 TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2442 r->m_table_sizes[counter] += s_min_table_sizes[counter];
2443 }
2445 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2446 {
2447 mz_uint s;
2448 TINFL_GET_BITS(14, s, 3);
2449 r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2450 }
2451 r->m_table_sizes[2] = 19;
2452 }
2453 for (; (int)r->m_type >= 0; r->m_type--)
2454 {
2455 int tree_next, tree_cur;
2456 tinfl_huff_table *pTable;
2457 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2458 pTable = &r->m_tables[r->m_type];
2459 MZ_CLEAR_OBJ(total_syms);
2460 MZ_CLEAR_OBJ(pTable->m_look_up);
2461 MZ_CLEAR_OBJ(pTable->m_tree);
2462 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2463 total_syms[pTable->m_code_size[i]]++;
2464 used_syms = 0, total = 0;
2465 next_code[0] = next_code[1] = 0;
2466 for (i = 1; i <= 15; ++i)
2467 {
2468 used_syms += total_syms[i];
2469 next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2470 }
2471 if ((65536 != total) && (used_syms > 1))
2472 {
2474 }
2475 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2476 {
2477 mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
2478 if (!code_size)
2479 continue;
2480 cur_code = next_code[code_size]++;
2481 for (l = code_size; l > 0; l--, cur_code >>= 1)
2482 rev_code = (rev_code << 1) | (cur_code & 1);
2483 if (code_size <= TINFL_FAST_LOOKUP_BITS)
2484 {
2485 mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2486 while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2487 {
2488 pTable->m_look_up[rev_code] = k;
2489 rev_code += (1 << code_size);
2490 }
2491 continue;
2492 }
2493 if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2494 {
2495 pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2496 tree_cur = tree_next;
2497 tree_next -= 2;
2498 }
2499 rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2500 for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2501 {
2502 tree_cur -= ((rev_code >>= 1) & 1);
2503 if (!pTable->m_tree[-tree_cur - 1])
2504 {
2505 pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2506 tree_cur = tree_next;
2507 tree_next -= 2;
2508 }
2509 else
2510 tree_cur = pTable->m_tree[-tree_cur - 1];
2511 }
2512 tree_cur -= ((rev_code >>= 1) & 1);
2513 pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2514 }
2515 if (r->m_type == 2)
2516 {
2517 for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2518 {
2519 mz_uint s;
2520 TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2521 if (dist < 16)
2522 {
2523 r->m_len_codes[counter++] = (mz_uint8)dist;
2524 continue;
2525 }
2526 if ((dist == 16) && (!counter))
2527 {
2529 }
2530 num_extra = "\02\03\07"[dist - 16];
2531 TINFL_GET_BITS(18, s, num_extra);
2532 s += "\03\03\013"[dist - 16];
2533 TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2534 counter += s;
2535 }
2536 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2537 {
2539 }
2542 }
2543 }
2544 for (;;)
2545 {
2546 mz_uint8 *pSrc;
2547 for (;;)
2548 {
2549 if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2550 {
2551 TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2552 if (counter >= 256)
2553 break;
2554 while (pOut_buf_cur >= pOut_buf_end)
2555 {
2557 }
2558 *pOut_buf_cur++ = (mz_uint8)counter;
2559 }
2560 else
2561 {
2562 int sym2;
2563 mz_uint code_len;
2564#if TINFL_USE_64BIT_BITBUF
2565 if (num_bits < 30)
2566 {
2567 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2568 pIn_buf_cur += 4;
2569 num_bits += 32;
2570 }
2571#else
2572 if (num_bits < 15)
2573 {
2574 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2575 pIn_buf_cur += 2;
2576 num_bits += 16;
2577 }
2578#endif
2579 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2580 code_len = sym2 >> 9;
2581 else
2582 {
2583 code_len = TINFL_FAST_LOOKUP_BITS;
2584 do
2585 {
2586 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2587 } while (sym2 < 0);
2588 }
2589 counter = sym2;
2590 bit_buf >>= code_len;
2591 num_bits -= code_len;
2592 if (counter & 256)
2593 break;
2594
2595#if !TINFL_USE_64BIT_BITBUF
2596 if (num_bits < 15)
2597 {
2598 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2599 pIn_buf_cur += 2;
2600 num_bits += 16;
2601 }
2602#endif
2603 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2604 code_len = sym2 >> 9;
2605 else
2606 {
2607 code_len = TINFL_FAST_LOOKUP_BITS;
2608 do
2609 {
2610 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2611 } while (sym2 < 0);
2612 }
2613 bit_buf >>= code_len;
2614 num_bits -= code_len;
2615
2616 pOut_buf_cur[0] = (mz_uint8)counter;
2617 if (sym2 & 256)
2618 {
2619 pOut_buf_cur++;
2620 counter = sym2;
2621 break;
2622 }
2623 pOut_buf_cur[1] = (mz_uint8)sym2;
2624 pOut_buf_cur += 2;
2625 }
2626 }
2627 if ((counter &= 511) == 256)
2628 break;
2629
2630 num_extra = s_length_extra[counter - 257];
2631 counter = s_length_base[counter - 257];
2632 if (num_extra)
2633 {
2634 mz_uint extra_bits;
2635 TINFL_GET_BITS(25, extra_bits, num_extra);
2636 counter += extra_bits;
2637 }
2638
2639 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2640 num_extra = s_dist_extra[dist];
2641 dist = s_dist_base[dist];
2642 if (num_extra)
2643 {
2644 mz_uint extra_bits;
2645 TINFL_GET_BITS(27, extra_bits, num_extra);
2646 dist += extra_bits;
2647 }
2648
2649 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2650 if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2651 {
2653 }
2654
2655 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2656
2657 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2658 {
2659 while (counter--)
2660 {
2661 while (pOut_buf_cur >= pOut_buf_end)
2662 {
2664 }
2665 *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2666 }
2667 continue;
2668 }
2669#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2670 else if ((counter >= 9) && (counter <= dist))
2671 {
2672 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2673 do
2674 {
2675 ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2676 ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2677 pOut_buf_cur += 8;
2678 } while ((pSrc += 8) < pSrc_end);
2679 if ((counter &= 7) < 3)
2680 {
2681 if (counter)
2682 {
2683 pOut_buf_cur[0] = pSrc[0];
2684 if (counter > 1)
2685 pOut_buf_cur[1] = pSrc[1];
2686 pOut_buf_cur += counter;
2687 }
2688 continue;
2689 }
2690 }
2691#endif
2692 do
2693 {
2694 pOut_buf_cur[0] = pSrc[0];
2695 pOut_buf_cur[1] = pSrc[1];
2696 pOut_buf_cur[2] = pSrc[2];
2697 pOut_buf_cur += 3;
2698 pSrc += 3;
2699 } while ((int)(counter -= 3) > 2);
2700 if ((int)counter > 0)
2701 {
2702 pOut_buf_cur[0] = pSrc[0];
2703 if ((int)counter > 1)
2704 pOut_buf_cur[1] = pSrc[1];
2705 pOut_buf_cur += counter;
2706 }
2707 }
2708 }
2709 } while (!(r->m_final & 1));
2710
2711 /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2712 /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */
2713 TINFL_SKIP_BITS(32, num_bits & 7);
2714 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2715 {
2716 --pIn_buf_cur;
2717 num_bits -= 8;
2718 }
2719 bit_buf &= (tinfl_bit_buf_t)(( ((mz_uint64)1) << num_bits) - (mz_uint64)1);
2720 MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */
2721
2722 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2723 {
2724 for (counter = 0; counter < 4; ++counter)
2725 {
2726 mz_uint s;
2727 if (num_bits)
2728 TINFL_GET_BITS(41, s, 8);
2729 else
2730 TINFL_GET_BYTE(42, s);
2731 r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2732 }
2733 }
2735
2737
2738common_exit:
2739 /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
2740 /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2741 /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */
2743 {
2744 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2745 {
2746 --pIn_buf_cur;
2747 num_bits -= 8;
2748 }
2749 }
2750 r->m_num_bits = num_bits;
2751 r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)(( ((mz_uint64)1) << num_bits) - (mz_uint64)1);
2752 r->m_dist = dist;
2753 r->m_counter = counter;
2754 r->m_num_extra = num_extra;
2755 r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2756 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2757 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2758 if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2759 {
2760 const mz_uint8 *ptr = pOut_buf_next;
2761 size_t buf_len = *pOut_buf_size;
2762 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2763 size_t block_len = buf_len % 5552;
2764 while (buf_len)
2765 {
2766 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2767 {
2768 s1 += ptr[0], s2 += s1;
2769 s1 += ptr[1], s2 += s1;
2770 s1 += ptr[2], s2 += s1;
2771 s1 += ptr[3], s2 += s1;
2772 s1 += ptr[4], s2 += s1;
2773 s1 += ptr[5], s2 += s1;
2774 s1 += ptr[6], s2 += s1;
2775 s1 += ptr[7], s2 += s1;
2776 }
2777 for (; i < block_len; ++i)
2778 s1 += *ptr++, s2 += s1;
2779 s1 %= 65521U, s2 %= 65521U;
2780 buf_len -= block_len;
2781 block_len = 5552;
2782 }
2783 r->m_check_adler32 = (s2 << 16) + s1;
2784 if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2786 }
2787 return status;
2788}
2789
2790/* Higher level helper functions. */
2791void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2792{
2793 tinfl_decompressor decomp;
2794 void *pBuf = NULL, *pNew_buf;
2795 size_t src_buf_ofs = 0, out_buf_capacity = 0;
2796 *pOut_len = 0;
2797 tinfl_init(&decomp);
2798 for (;;)
2799 {
2800 size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2801 tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size,
2803 if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2804 {
2805 MZ_FREE(pBuf);
2806 *pOut_len = 0;
2807 return NULL;
2808 }
2809 src_buf_ofs += src_buf_size;
2810 *pOut_len += dst_buf_size;
2811 if (status == TINFL_STATUS_DONE)
2812 break;
2813 new_out_buf_capacity = out_buf_capacity * 2;
2814 if (new_out_buf_capacity < 128)
2815 new_out_buf_capacity = 128;
2816 pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2817 if (!pNew_buf)
2818 {
2819 MZ_FREE(pBuf);
2820 *pOut_len = 0;
2821 return NULL;
2822 }
2823 pBuf = pNew_buf;
2824 out_buf_capacity = new_out_buf_capacity;
2825 }
2826 return pBuf;
2827}
2828
2829size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2830{
2831 tinfl_decompressor decomp;
2832 tinfl_status status;
2833 tinfl_init(&decomp);
2834 status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2835 return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2836}
2837
2838int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2839{
2840 int result = 0;
2841 tinfl_decompressor decomp;
2843 size_t in_buf_ofs = 0, dict_ofs = 0;
2844 if (!pDict)
2845 return TINFL_STATUS_FAILED;
2846 tinfl_init(&decomp);
2847 for (;;)
2848 {
2849 size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2850 tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2852 in_buf_ofs += in_buf_size;
2853 if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2854 break;
2855 if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2856 {
2857 result = (status == TINFL_STATUS_DONE);
2858 break;
2859 }
2860 dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2861 }
2862 MZ_FREE(pDict);
2863 *pIn_buf_size = in_buf_ofs;
2864 return result;
2865}
2866
2868{
2870 if (pDecomp)
2871 tinfl_init(pDecomp);
2872 return pDecomp;
2873}
2874
2876{
2877 MZ_FREE(pDecomp);
2878}
2879
2880#ifdef __cplusplus
2881}
2882#endif
2883/**************************************************************************
2884 *
2885 * Copyright 2013-2014 RAD Game Tools and Valve Software
2886 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2887 * Copyright 2016 Martin Raiber
2888 * All Rights Reserved.
2889 *
2890 * Permission is hereby granted, free of charge, to any person obtaining a copy
2891 * of this software and associated documentation files (the "Software"), to deal
2892 * in the Software without restriction, including without limitation the rights
2893 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2894 * copies of the Software, and to permit persons to whom the Software is
2895 * furnished to do so, subject to the following conditions:
2896 *
2897 * The above copyright notice and this permission notice shall be included in
2898 * all copies or substantial portions of the Software.
2899 *
2900 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2901 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2902 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2903 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2904 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2905 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2906 * THE SOFTWARE.
2907 *
2908 **************************************************************************/
2909
2910
2911#ifndef MINIZ_NO_ARCHIVE_APIS
2912
2913#ifdef __cplusplus
2914extern "C" {
2915#endif
2916
2917/* ------------------- .ZIP archive reading */
2918
2919#ifdef MINIZ_NO_STDIO
2920#define MZ_FILE void *
2921#else
2922#include <sys/stat.h>
2923
2924#if defined(_MSC_VER) || defined(__MINGW64__)
2925static FILE *mz_fopen(const char *pFilename, const char *pMode)
2926{
2927 FILE *pFile = NULL;
2928 fopen_s(&pFile, pFilename, pMode);
2929 return pFile;
2930}
2931static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
2932{
2933 FILE *pFile = NULL;
2934 if (freopen_s(&pFile, pPath, pMode, pStream))
2935 return NULL;
2936 return pFile;
2937}
2938#ifndef MINIZ_NO_TIME
2939#include <sys/utime.h>
2940#endif
2941#define MZ_FOPEN mz_fopen
2942#define MZ_FCLOSE fclose
2943#define MZ_FREAD fread
2944#define MZ_FWRITE fwrite
2945#define MZ_FTELL64 _ftelli64
2946#define MZ_FSEEK64 _fseeki64
2947#define MZ_FILE_STAT_STRUCT _stat
2948#define MZ_FILE_STAT _stat
2949#define MZ_FFLUSH fflush
2950#define MZ_FREOPEN mz_freopen
2951#define MZ_DELETE_FILE remove
2952#elif defined(__MINGW32__)
2953#ifndef MINIZ_NO_TIME
2954#include <sys/utime.h>
2955#endif
2956#define MZ_FOPEN(f, m) fopen(f, m)
2957#define MZ_FCLOSE fclose
2958#define MZ_FREAD fread
2959#define MZ_FWRITE fwrite
2960#define MZ_FTELL64 ftello64
2961#define MZ_FSEEK64 fseeko64
2962#define MZ_FILE_STAT_STRUCT _stat
2963#define MZ_FILE_STAT _stat
2964#define MZ_FFLUSH fflush
2965#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2966#define MZ_DELETE_FILE remove
2967#elif defined(__TINYC__)
2968#ifndef MINIZ_NO_TIME
2969#include <sys/utime.h>
2970#endif
2971#define MZ_FOPEN(f, m) fopen(f, m)
2972#define MZ_FCLOSE fclose
2973#define MZ_FREAD fread
2974#define MZ_FWRITE fwrite
2975#define MZ_FTELL64 ftell
2976#define MZ_FSEEK64 fseek
2977#define MZ_FILE_STAT_STRUCT stat
2978#define MZ_FILE_STAT stat
2979#define MZ_FFLUSH fflush
2980#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2981#define MZ_DELETE_FILE remove
2982#elif defined(__GNUC__) && _LARGEFILE64_SOURCE
2983#ifndef MINIZ_NO_TIME
2984#include <utime.h>
2985#endif
2986#define MZ_FOPEN(f, m) fopen64(f, m)
2987#define MZ_FCLOSE fclose
2988#define MZ_FREAD fread
2989#define MZ_FWRITE fwrite
2990#define MZ_FTELL64 ftello64
2991#define MZ_FSEEK64 fseeko64
2992#define MZ_FILE_STAT_STRUCT stat64
2993#define MZ_FILE_STAT stat64
2994#define MZ_FFLUSH fflush
2995#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
2996#define MZ_DELETE_FILE remove
2997#elif defined(__APPLE__) && _LARGEFILE64_SOURCE
2998#ifndef MINIZ_NO_TIME
2999#include <utime.h>
3000#endif
3001#define MZ_FOPEN(f, m) fopen(f, m)
3002#define MZ_FCLOSE fclose
3003#define MZ_FREAD fread
3004#define MZ_FWRITE fwrite
3005#define MZ_FTELL64 ftello
3006#define MZ_FSEEK64 fseeko
3007#define MZ_FILE_STAT_STRUCT stat
3008#define MZ_FILE_STAT stat
3009#define MZ_FFLUSH fflush
3010#define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3011#define MZ_DELETE_FILE remove
3012
3013#else
3014#pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3015#ifndef MINIZ_NO_TIME
3016#include <utime.h>
3017#endif
3018#define MZ_FOPEN(f, m) fopen(f, m)
3019#define MZ_FCLOSE fclose
3020#define MZ_FREAD fread
3021#define MZ_FWRITE fwrite
3022#ifdef __STRICT_ANSI__
3023#define MZ_FTELL64 ftell
3024#define MZ_FSEEK64 fseek
3025#else
3026#define MZ_FTELL64 ftello
3027#define MZ_FSEEK64 fseeko
3028#endif
3029#define MZ_FILE_STAT_STRUCT stat
3030#define MZ_FILE_STAT stat
3031#define MZ_FFLUSH fflush
3032#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3033#define MZ_DELETE_FILE remove
3034#endif /* #ifdef _MSC_VER */
3035#endif /* #ifdef MINIZ_NO_STDIO */
3036
3037#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3038
3039/* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */
3040enum
3041{
3042 /* ZIP archive identifiers and record sizes */
3049
3050 /* ZIP64 archive identifier and record sizes */
3059
3060 /* Central directory header record offsets */
3078
3079 /* Local directory header offsets */
3092
3093 /* End of central directory offsets */
3102
3103 /* ZIP64 End of central directory locator offsets */
3104 MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
3108
3109 /* ZIP64 End of central directory header offsets */
3110 MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
3119 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
3128
3129typedef struct
3130{
3131 void *m_p;
3132 size_t m_size, m_capacity;
3134} mz_zip_array;
3135
3137{
3141
3142 /* The flags passed in when the archive is initially opened. */
3144
3145 /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3147
3148 /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */
3150
3151 /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3154
3155 void *m_pMem;
3158};
3159
3160#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3161
3162#if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
3163static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3164{
3165 MZ_ASSERT(index < pArray->m_size);
3166 return index;
3167}
3168#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3169#else
3170#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3171#endif
3172
3173static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3174{
3175 memset(pArray, 0, sizeof(mz_zip_array));
3176 pArray->m_element_size = element_size;
3177}
3178
3180{
3181 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3182 memset(pArray, 0, sizeof(mz_zip_array));
3183}
3184
3185static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3186{
3187 void *pNew_p;
3188 size_t new_capacity = min_new_capacity;
3189 MZ_ASSERT(pArray->m_element_size);
3190 if (pArray->m_capacity >= min_new_capacity)
3191 return MZ_TRUE;
3192 if (growing)
3193 {
3194 new_capacity = MZ_MAX(1, pArray->m_capacity);
3195 while (new_capacity < min_new_capacity)
3196 new_capacity *= 2;
3197 }
3198 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3199 return MZ_FALSE;
3200 pArray->m_p = pNew_p;
3201 pArray->m_capacity = new_capacity;
3202 return MZ_TRUE;
3203}
3204
3205static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3206{
3207 if (new_capacity > pArray->m_capacity)
3208 {
3209 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3210 return MZ_FALSE;
3211 }
3212 return MZ_TRUE;
3213}
3214
3215static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3216{
3217 if (new_size > pArray->m_capacity)
3218 {
3219 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3220 return MZ_FALSE;
3221 }
3222 pArray->m_size = new_size;
3223 return MZ_TRUE;
3224}
3225
3227{
3228 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3229}
3230
3231static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3232{
3233 size_t orig_size = pArray->m_size;
3234 if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3235 return MZ_FALSE;
3236 memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3237 return MZ_TRUE;
3238}
3239
3240#ifndef MINIZ_NO_TIME
3241static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3242{
3243 struct tm tm;
3244 memset(&tm, 0, sizeof(tm));
3245 tm.tm_isdst = -1;
3246 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3247 tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3248 tm.tm_mday = dos_date & 31;
3249 tm.tm_hour = (dos_time >> 11) & 31;
3250 tm.tm_min = (dos_time >> 5) & 63;
3251 tm.tm_sec = (dos_time << 1) & 62;
3252 return mktime(&tm);
3253}
3254
3255#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3256static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3257{
3258#ifdef _MSC_VER
3259 struct tm tm_struct;
3260 struct tm *tm = &tm_struct;
3261 errno_t err = localtime_s(tm, &time);
3262 if (err)
3263 {
3264 *pDOS_date = 0;
3265 *pDOS_time = 0;
3266 return;
3267 }
3268#else
3269 struct tm *tm = localtime(&time);
3270#endif /* #ifdef _MSC_VER */
3271
3272 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3273 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3274}
3275#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3276
3277#ifndef MINIZ_NO_STDIO
3278#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3279static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3280{
3281 struct MZ_FILE_STAT_STRUCT file_stat;
3282
3283 /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3284 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3285 return MZ_FALSE;
3286
3287 *pTime = file_stat.st_mtime;
3288
3289 return MZ_TRUE;
3290}
3291#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3292
3293static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3294{
3295 struct utimbuf t;
3296
3297 memset(&t, 0, sizeof(t));
3298 t.actime = access_time;
3299 t.modtime = modified_time;
3300
3301 return !utime(pFilename, &t);
3302}
3303#endif /* #ifndef MINIZ_NO_STDIO */
3304#endif /* #ifndef MINIZ_NO_TIME */
3305
3307{
3308 if (pZip)
3309 pZip->m_last_error = err_num;
3310 return MZ_FALSE;
3311}
3312
3314{
3315 (void)flags;
3316 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3318
3319 if (!pZip->m_pAlloc)
3321 if (!pZip->m_pFree)
3323 if (!pZip->m_pRealloc)
3325
3326 pZip->m_archive_size = 0;
3328 pZip->m_total_files = 0;
3330
3331 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3333
3334 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3338 pZip->m_pState->m_init_flags = flags;
3339 pZip->m_pState->m_zip64 = MZ_FALSE;
3341
3343
3344 return MZ_TRUE;
3345}
3346
3347static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3348{
3349 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3350 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3352 mz_uint8 l = 0, r = 0;
3355 pE = pL + MZ_MIN(l_len, r_len);
3356 while (pL < pE)
3357 {
3358 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3359 break;
3360 pL++;
3361 pR++;
3362 }
3363 return (pL == pE) ? (l_len < r_len) : (l < r);
3364}
3365
3366#define MZ_SWAP_UINT32(a, b) \
3367 do \
3368 { \
3369 mz_uint32 t = a; \
3370 a = b; \
3371 b = t; \
3372 } \
3373 MZ_MACRO_END
3374
3375/* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */
3377{
3378 mz_zip_internal_state *pState = pZip->m_pState;
3379 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3380 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3381 mz_uint32 *pIndices;
3382 mz_uint32 start, end;
3383 const mz_uint32 size = pZip->m_total_files;
3384
3385 if (size <= 1U)
3386 return;
3387
3389
3390 start = (size - 2U) >> 1U;
3391 for (;;)
3392 {
3393 mz_uint64 child, root = start;
3394 for (;;)
3395 {
3396 if ((child = (root << 1U) + 1U) >= size)
3397 break;
3398 child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3399 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3400 break;
3401 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3402 root = child;
3403 }
3404 if (!start)
3405 break;
3406 start--;
3407 }
3408
3409 end = size - 1;
3410 while (end > 0)
3411 {
3412 mz_uint64 child, root = 0;
3413 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3414 for (;;)
3415 {
3416 if ((child = (root << 1U) + 1U) >= end)
3417 break;
3418 child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3419 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3420 break;
3421 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3422 root = child;
3423 }
3424 end--;
3425 }
3426}
3427
3429{
3430 mz_int64 cur_file_ofs;
3431 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3432 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3433
3434 /* Basic sanity checks - reject files which are too small */
3435 if (pZip->m_archive_size < record_size)
3436 return MZ_FALSE;
3437
3438 /* Find the record by scanning the file from the end towards the beginning. */
3439 cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3440 for (;;)
3441 {
3442 int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3443
3444 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3445 return MZ_FALSE;
3446
3447 for (i = n - 4; i >= 0; --i)
3448 {
3449 mz_uint s = MZ_READ_LE32(pBuf + i);
3450 if (s == record_sig)
3451 {
3452 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3453 break;
3454 }
3455 }
3456
3457 if (i >= 0)
3458 {
3459 cur_file_ofs += i;
3460 break;
3461 }
3462
3463 /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3464 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3465 return MZ_FALSE;
3466
3467 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3468 }
3469
3470 *pOfs = cur_file_ofs;
3471 return MZ_TRUE;
3472}
3473
3475{
3476 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3477 mz_uint64 cdir_ofs = 0;
3478 mz_int64 cur_file_ofs = 0;
3479 const mz_uint8 *p;
3480
3481 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3482 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3483 mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3484 mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3485 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3486
3487 mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3488 mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3489
3490 mz_uint64 zip64_end_of_central_dir_ofs = 0;
3491
3492 /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */
3495
3498
3499 /* Read and verify the end of central directory record. */
3502
3505
3507 {
3509 {
3511 {
3512 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3513 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3515
3516 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
3517 {
3519 {
3520 pZip->m_pState->m_zip64 = MZ_TRUE;
3521 }
3522 }
3523 }
3524 }
3525 }
3526
3528 cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3529 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3530 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3531 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3532 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3533
3534 if (pZip->m_pState->m_zip64)
3535 {
3536 mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3537 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3538 mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3539 mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
3540 mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3541
3542 if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3544
3545 if (zip64_total_num_of_disks != 1U)
3547
3548 /* Check for miniz's practical limits */
3549 if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3551
3552 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3553
3554 if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3556
3557 cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3558
3559 /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3560 if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3562
3563 cdir_size = (mz_uint32)zip64_size_of_central_directory;
3564
3565 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3566
3567 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3568
3569 cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3570 }
3571
3572 if (pZip->m_total_files != cdir_entries_on_this_disk)
3574
3575 if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3577
3578 if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3580
3581 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3583
3584 pZip->m_central_directory_file_ofs = cdir_ofs;
3585
3586 if (pZip->m_total_files)
3587 {
3588 mz_uint i, n;
3589 /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */
3590 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3593
3594 if (sort_central_dir)
3595 {
3598 }
3599
3600 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3602
3603 /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3604 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3605 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3606 {
3607 mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3608 mz_uint64 comp_size, decomp_size, local_header_ofs;
3609
3612
3614
3615 if (sort_central_dir)
3617
3620 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3621 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3622 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3623
3625 (ext_data_size) &&
3626 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3627 {
3628 /* Attempt to find zip64 extended information field in the entry's extra data */
3629 mz_uint32 extra_size_remaining = ext_data_size;
3630
3631 if (extra_size_remaining)
3632 {
3633 const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3634
3635 do
3636 {
3637 mz_uint32 field_id;
3638 mz_uint32 field_data_size;
3639
3640 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3642
3643 field_id = MZ_READ_LE16(pExtra_data);
3644 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3645
3646 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3648
3650 {
3651 /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */
3652 pZip->m_pState->m_zip64 = MZ_TRUE;
3654 break;
3655 }
3656
3657 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3658 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3659 } while (extra_size_remaining);
3660 }
3661 }
3662
3663 /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3664 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3665 {
3666 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3668 }
3669
3670 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3671 if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3673
3674 if (comp_size != MZ_UINT32_MAX)
3675 {
3678 }
3679
3680 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3683
3686
3687 n -= total_header_size;
3688 p += total_header_size;
3689 }
3690 }
3691
3692 if (sort_central_dir)
3694
3695 return MZ_TRUE;
3696}
3697
3699{
3700 if (pZip)
3701 MZ_CLEAR_OBJ(*pZip);
3702}
3703
3705{
3706 mz_bool status = MZ_TRUE;
3707
3708 if (!pZip)
3709 return MZ_FALSE;
3710
3711 if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3712 {
3713 if (set_last_error)
3715
3716 return MZ_FALSE;
3717 }
3718
3719 if (pZip->m_pState)
3720 {
3721 mz_zip_internal_state *pState = pZip->m_pState;
3722 pZip->m_pState = NULL;
3723
3724 mz_zip_array_clear(pZip, &pState->m_central_dir);
3727
3728#ifndef MINIZ_NO_STDIO
3729 if (pState->m_pFile)
3730 {
3731 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3732 {
3733 if (MZ_FCLOSE(pState->m_pFile) == EOF)
3734 {
3735 if (set_last_error)
3737 status = MZ_FALSE;
3738 }
3739 }
3740 pState->m_pFile = NULL;
3741 }
3742#endif /* #ifndef MINIZ_NO_STDIO */
3743
3744 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3745 }
3747
3748 return status;
3749}
3750
3752{
3753 return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3754}
3756{
3757 if ((!pZip) || (!pZip->m_pRead))
3759
3760 if (!mz_zip_reader_init_internal(pZip, flags))
3761 return MZ_FALSE;
3762
3764 pZip->m_archive_size = size;
3765
3766 if (!mz_zip_reader_read_central_dir(pZip, flags))
3767 {
3769 return MZ_FALSE;
3770 }
3771
3772 return MZ_TRUE;
3773}
3774
3775static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3776{
3777 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3778 size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3779 memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3780 return s;
3781}
3782
3783mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
3784{
3785 if (!pMem)
3787
3790
3791 if (!mz_zip_reader_init_internal(pZip, flags))
3792 return MZ_FALSE;
3793
3795 pZip->m_archive_size = size;
3797 pZip->m_pIO_opaque = pZip;
3798 pZip->m_pNeeds_keepalive = NULL;
3799
3800#ifdef __cplusplus
3801 pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3802#else
3803 pZip->m_pState->m_pMem = (void *)pMem;
3804#endif
3805
3806 pZip->m_pState->m_mem_size = size;
3807
3808 if (!mz_zip_reader_read_central_dir(pZip, flags))
3809 {
3811 return MZ_FALSE;
3812 }
3813
3814 return MZ_TRUE;
3815}
3816
3817#ifndef MINIZ_NO_STDIO
3818static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3819{
3820 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3821 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3822
3823 file_ofs += pZip->m_pState->m_file_archive_start_ofs;
3824
3825 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
3826 return 0;
3827
3828 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3829}
3830
3831mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
3832{
3833 return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
3834}
3835
3836mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
3837{
3838 mz_uint64 file_size;
3839 MZ_FILE *pFile;
3840
3841 if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3843
3844 pFile = MZ_FOPEN(pFilename, "rb");
3845 if (!pFile)
3847
3848 file_size = archive_size;
3849 if (!file_size)
3850 {
3851 if (MZ_FSEEK64(pFile, 0, SEEK_END))
3852 {
3853 MZ_FCLOSE(pFile);
3855 }
3856
3857 file_size = MZ_FTELL64(pFile);
3858 }
3859
3860 /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
3861
3864
3865 if (!mz_zip_reader_init_internal(pZip, flags))
3866 {
3867 MZ_FCLOSE(pFile);
3868 return MZ_FALSE;
3869 }
3870
3873 pZip->m_pIO_opaque = pZip;
3874 pZip->m_pState->m_pFile = pFile;
3875 pZip->m_archive_size = file_size;
3876 pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
3877
3878 if (!mz_zip_reader_read_central_dir(pZip, flags))
3879 {
3881 return MZ_FALSE;
3882 }
3883
3884 return MZ_TRUE;
3885}
3886
3888{
3889 mz_uint64 cur_file_ofs;
3890
3891 if ((!pZip) || (!pFile))
3893
3894 cur_file_ofs = MZ_FTELL64(pFile);
3895
3896 if (!archive_size)
3897 {
3898 if (MZ_FSEEK64(pFile, 0, SEEK_END))
3900
3901 archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
3902
3903 if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3905 }
3906
3907 if (!mz_zip_reader_init_internal(pZip, flags))
3908 return MZ_FALSE;
3909
3912
3913 pZip->m_pIO_opaque = pZip;
3914 pZip->m_pState->m_pFile = pFile;
3915 pZip->m_archive_size = archive_size;
3916 pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
3917
3918 if (!mz_zip_reader_read_central_dir(pZip, flags))
3919 {
3921 return MZ_FALSE;
3922 }
3923
3924 return MZ_TRUE;
3925}
3926
3927#endif /* #ifndef MINIZ_NO_STDIO */
3928
3930{
3931 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
3932 return NULL;
3934}
3935
3937{
3938 mz_uint m_bit_flag;
3939 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
3940 if (!p)
3941 {
3943 return MZ_FALSE;
3944 }
3945
3946 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3948}
3949
3951{
3952 mz_uint bit_flag;
3953 mz_uint method;
3954
3955 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
3956 if (!p)
3957 {
3959 return MZ_FALSE;
3960 }
3961
3962 method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
3963 bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3964
3965 if ((method != 0) && (method != MZ_DEFLATED))
3966 {
3968 return MZ_FALSE;
3969 }
3970
3972 {
3974 return MZ_FALSE;
3975 }
3976
3978 {
3980 return MZ_FALSE;
3981 }
3982
3983 return MZ_TRUE;
3984}
3985
3987{
3988 mz_uint filename_len, attribute_mapping_id, external_attr;
3989 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
3990 if (!p)
3991 {
3993 return MZ_FALSE;
3994 }
3995
3996 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3997 if (filename_len)
3998 {
3999 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4000 return MZ_TRUE;
4001 }
4002
4003 /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4004 /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */
4005 /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4006 attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4007 (void)attribute_mapping_id;
4008
4009 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4010 if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4011 {
4012 return MZ_TRUE;
4013 }
4014
4015 return MZ_FALSE;
4016}
4017
4018static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
4019{
4020 mz_uint n;
4021 const mz_uint8 *p = pCentral_dir_header;
4022
4023 if (pFound_zip64_extra_data)
4024 *pFound_zip64_extra_data = MZ_FALSE;
4025
4026 if ((!p) || (!pStat))
4028
4029 /* Extract fields from the central directory record. */
4030 pStat->m_file_index = file_index;
4036#ifndef MINIZ_NO_TIME
4038#endif
4045
4046 /* Copy as much of the filename and comment as possible. */
4049 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4050 pStat->m_filename[n] = '\0';
4051
4054 pStat->m_comment_size = n;
4056 pStat->m_comment[n] = '\0';
4057
4058 /* Set some flags for convienance */
4059 pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4060 pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4061 pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4062
4063 /* See if we need to read any zip64 extended information fields. */
4064 /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */
4066 {
4067 /* Attempt to find zip64 extended information field in the entry's extra data */
4068 mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4069
4070 if (extra_size_remaining)
4071 {
4073
4074 do
4075 {
4076 mz_uint32 field_id;
4077 mz_uint32 field_data_size;
4078
4079 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4081
4082 field_id = MZ_READ_LE16(pExtra_data);
4083 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4084
4085 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4087
4089 {
4090 const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4091 mz_uint32 field_data_remaining = field_data_size;
4092
4093 if (pFound_zip64_extra_data)
4094 *pFound_zip64_extra_data = MZ_TRUE;
4095
4096 if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4097 {
4098 if (field_data_remaining < sizeof(mz_uint64))
4100
4101 pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4102 pField_data += sizeof(mz_uint64);
4103 field_data_remaining -= sizeof(mz_uint64);
4104 }
4105
4106 if (pStat->m_comp_size == MZ_UINT32_MAX)
4107 {
4108 if (field_data_remaining < sizeof(mz_uint64))
4110
4111 pStat->m_comp_size = MZ_READ_LE64(pField_data);
4112 pField_data += sizeof(mz_uint64);
4113 field_data_remaining -= sizeof(mz_uint64);
4114 }
4115
4116 if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4117 {
4118 if (field_data_remaining < sizeof(mz_uint64))
4120
4121 pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4122 pField_data += sizeof(mz_uint64);
4123 field_data_remaining -= sizeof(mz_uint64);
4124 }
4125
4126 break;
4127 }
4128
4129 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4130 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4131 } while (extra_size_remaining);
4132 }
4133 }
4134
4135 return MZ_TRUE;
4136}
4137
4138static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4139{
4140 mz_uint i;
4141 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4142 return 0 == memcmp(pA, pB, len);
4143 for (i = 0; i < len; ++i)
4144 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4145 return MZ_FALSE;
4146 return MZ_TRUE;
4147}
4148
4149static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
4150{
4151 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
4153 mz_uint8 l = 0, r = 0;
4155 pE = pL + MZ_MIN(l_len, r_len);
4156 while (pL < pE)
4157 {
4158 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4159 break;
4160 pL++;
4161 pR++;
4162 }
4163 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4164}
4165
4166static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4167{
4168 mz_zip_internal_state *pState = pZip->m_pState;
4169 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4170 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4172 const uint32_t size = pZip->m_total_files;
4173 const mz_uint filename_len = (mz_uint)strlen(pFilename);
4174
4175 if (pIndex)
4176 *pIndex = 0;
4177
4178 if (size)
4179 {
4180 /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4181 /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4182 mz_int64 l = 0, h = (mz_int64)size - 1;
4183
4184 while (l <= h)
4185 {
4186 mz_int64 m = l + ((h - l) >> 1);
4187 uint32_t file_index = pIndices[(uint32_t)m];
4188
4189 int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4190 if (!comp)
4191 {
4192 if (pIndex)
4193 *pIndex = file_index;
4194 return MZ_TRUE;
4195 }
4196 else if (comp < 0)
4197 l = m + 1;
4198 else
4199 h = m - 1;
4200 }
4201 }
4202
4204}
4205
4206int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4207{
4208 mz_uint32 index;
4209 if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4210 return -1;
4211 else
4212 return (int)index;
4213}
4214
4215mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4216{
4217 mz_uint file_index;
4218 size_t name_len, comment_len;
4219
4220 if (pIndex)
4221 *pIndex = 0;
4222
4223 if ((!pZip) || (!pZip->m_pState) || (!pName))
4225
4226 /* See if we can use a binary search */
4228 (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4230 {
4231 return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4232 }
4233
4234 /* Locate the entry by scanning the entire central directory */
4235 name_len = strlen(pName);
4236 if (name_len > MZ_UINT16_MAX)
4238
4239 comment_len = pComment ? strlen(pComment) : 0;
4240 if (comment_len > MZ_UINT16_MAX)
4242
4243 for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4244 {
4246 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4247 const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4248 if (filename_len < name_len)
4249 continue;
4250 if (comment_len)
4251 {
4252 mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4253 const char *pFile_comment = pFilename + filename_len + file_extra_len;
4254 if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4255 continue;
4256 }
4257 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4258 {
4259 int ofs = filename_len - 1;
4260 do
4261 {
4262 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4263 break;
4264 } while (--ofs >= 0);
4265 ofs++;
4266 pFilename += ofs;
4267 filename_len -= ofs;
4268 }
4269 if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4270 {
4271 if (pIndex)
4272 *pIndex = file_index;
4273 return MZ_TRUE;
4274 }
4275 }
4276
4278}
4279
4280mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4281{
4282 int status = TINFL_STATUS_DONE;
4283 mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4284 mz_zip_archive_file_stat file_stat;
4285 void *pRead_buf;
4286 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4287 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4288 tinfl_decompressor inflator;
4289
4290 if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4292
4293 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4294 return MZ_FALSE;
4295
4296 /* A directory or zero length file */
4297 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4298 return MZ_TRUE;
4299
4300 /* Encryption and patch files are not supported. */
4303
4304 /* This function only supports decompressing stored and deflate. */
4305 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4307
4308 /* Ensure supplied output buffer is large enough. */
4309 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4310 if (buf_size < needed_size)
4312
4313 /* Read and parse the local directory entry. */
4314 cur_file_ofs = file_stat.m_local_header_ofs;
4315 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4317
4318 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4320
4322 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4324
4325 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4326 {
4327 /* The file is stored or the caller has requested the compressed data. */
4328 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4330
4331#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4332 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4333 {
4334 if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4336 }
4337#endif
4338
4339 return MZ_TRUE;
4340 }
4341
4342 /* Decompress the file either directly from memory or from a file input buffer. */
4343 tinfl_init(&inflator);
4344
4345 if (pZip->m_pState->m_pMem)
4346 {
4347 /* Read directly from the archive in memory. */
4348 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4349 read_buf_size = read_buf_avail = file_stat.m_comp_size;
4350 comp_remaining = 0;
4351 }
4352 else if (pUser_read_buf)
4353 {
4354 /* Use a user provided read buffer. */
4355 if (!user_read_buf_size)
4356 return MZ_FALSE;
4357 pRead_buf = (mz_uint8 *)pUser_read_buf;
4358 read_buf_size = user_read_buf_size;
4359 read_buf_avail = 0;
4360 comp_remaining = file_stat.m_comp_size;
4361 }
4362 else
4363 {
4364 /* Temporarily allocate a read buffer. */
4365 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4366 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4368
4369 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4371
4372 read_buf_avail = 0;
4373 comp_remaining = file_stat.m_comp_size;
4374 }
4375
4376 do
4377 {
4378 /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4379 size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4380 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4381 {
4382 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4383 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4384 {
4385 status = TINFL_STATUS_FAILED;
4387 break;
4388 }
4389 cur_file_ofs += read_buf_avail;
4390 comp_remaining -= read_buf_avail;
4391 read_buf_ofs = 0;
4392 }
4393 in_buf_size = (size_t)read_buf_avail;
4394 status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
4395 read_buf_avail -= in_buf_size;
4396 read_buf_ofs += in_buf_size;
4397 out_buf_ofs += out_buf_size;
4398 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4399
4400 if (status == TINFL_STATUS_DONE)
4401 {
4402 /* Make sure the entire file was decompressed, and check its CRC. */
4403 if (out_buf_ofs != file_stat.m_uncomp_size)
4404 {
4406 status = TINFL_STATUS_FAILED;
4407 }
4408#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4409 else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4410 {
4412 status = TINFL_STATUS_FAILED;
4413 }
4414#endif
4415 }
4416
4417 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4418 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4419
4420 return status == TINFL_STATUS_DONE;
4421}
4422
4423mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4424{
4425 mz_uint32 file_index;
4426 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4427 return MZ_FALSE;
4428 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4429}
4430
4431mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
4432{
4433 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4434}
4435
4436mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
4437{
4438 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4439}
4440
4441void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4442{
4443 mz_uint64 comp_size, uncomp_size, alloc_size;
4444 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4445 void *pBuf;
4446
4447 if (pSize)
4448 *pSize = 0;
4449
4450 if (!p)
4451 {
4453 return NULL;
4454 }
4455
4458
4459 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4460 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4461 {
4463 return NULL;
4464 }
4465
4466 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4467 {
4469 return NULL;
4470 }
4471
4472 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
4473 {
4474 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4475 return NULL;
4476 }
4477
4478 if (pSize)
4479 *pSize = (size_t)alloc_size;
4480 return pBuf;
4481}
4482
4483void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4484{
4485 mz_uint32 file_index;
4486 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4487 {
4488 if (pSize)
4489 *pSize = 0;
4490 return MZ_FALSE;
4491 }
4492 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4493}
4494
4496{
4497 int status = TINFL_STATUS_DONE;
4498 mz_uint file_crc32 = MZ_CRC32_INIT;
4499 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4500 mz_zip_archive_file_stat file_stat;
4501 void *pRead_buf = NULL;
4502 void *pWrite_buf = NULL;
4503 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4504 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4505
4506 if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4508
4509 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4510 return MZ_FALSE;
4511
4512 /* A directory or zero length file */
4513 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4514 return MZ_TRUE;
4515
4516 /* Encryption and patch files are not supported. */
4519
4520 /* This function only supports decompressing stored and deflate. */
4521 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4523
4524 /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */
4525 cur_file_ofs = file_stat.m_local_header_ofs;
4526 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4528
4529 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4531
4533 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4535
4536 /* Decompress the file either directly from memory or from a file input buffer. */
4537 if (pZip->m_pState->m_pMem)
4538 {
4539 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4540 read_buf_size = read_buf_avail = file_stat.m_comp_size;
4541 comp_remaining = 0;
4542 }
4543 else
4544 {
4545 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4546 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4548
4549 read_buf_avail = 0;
4550 comp_remaining = file_stat.m_comp_size;
4551 }
4552
4553 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4554 {
4555 /* The file is stored or the caller has requested the compressed data. */
4556 if (pZip->m_pState->m_pMem)
4557 {
4558 if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4560
4561 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4562 {
4564 status = TINFL_STATUS_FAILED;
4565 }
4566 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4567 {
4568#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4569 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4570#endif
4571 }
4572
4573 cur_file_ofs += file_stat.m_comp_size;
4574 out_buf_ofs += file_stat.m_comp_size;
4575 comp_remaining = 0;
4576 }
4577 else
4578 {
4579 while (comp_remaining)
4580 {
4581 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4582 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4583 {
4585 status = TINFL_STATUS_FAILED;
4586 break;
4587 }
4588
4589#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4590 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4591 {
4592 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4593 }
4594#endif
4595
4596 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4597 {
4599 status = TINFL_STATUS_FAILED;
4600 break;
4601 }
4602
4603 cur_file_ofs += read_buf_avail;
4604 out_buf_ofs += read_buf_avail;
4605 comp_remaining -= read_buf_avail;
4606 }
4607 }
4608 }
4609 else
4610 {
4611 tinfl_decompressor inflator;
4612 tinfl_init(&inflator);
4613
4614 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4615 {
4617 status = TINFL_STATUS_FAILED;
4618 }
4619 else
4620 {
4621 do
4622 {
4623 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4624 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4625 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4626 {
4627 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4628 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4629 {
4631 status = TINFL_STATUS_FAILED;
4632 break;
4633 }
4634 cur_file_ofs += read_buf_avail;
4635 comp_remaining -= read_buf_avail;
4636 read_buf_ofs = 0;
4637 }
4638
4639 in_buf_size = (size_t)read_buf_avail;
4640 status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
4641 read_buf_avail -= in_buf_size;
4642 read_buf_ofs += in_buf_size;
4643
4644 if (out_buf_size)
4645 {
4646 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4647 {
4649 status = TINFL_STATUS_FAILED;
4650 break;
4651 }
4652
4653#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4654 file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4655#endif
4656 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4657 {
4659 status = TINFL_STATUS_FAILED;
4660 break;
4661 }
4662 }
4663 } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4664 }
4665 }
4666
4667 if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4668 {
4669 /* Make sure the entire file was decompressed, and check its CRC. */
4670 if (out_buf_ofs != file_stat.m_uncomp_size)
4671 {
4673 status = TINFL_STATUS_FAILED;
4674 }
4675#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4676 else if (file_crc32 != file_stat.m_crc32)
4677 {
4679 status = TINFL_STATUS_FAILED;
4680 }
4681#endif
4682 }
4683
4684 if (!pZip->m_pState->m_pMem)
4685 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4686
4687 if (pWrite_buf)
4688 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4689
4690 return status == TINFL_STATUS_DONE;
4691}
4692
4693mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4694{
4695 mz_uint32 file_index;
4696 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4697 return MZ_FALSE;
4698
4699 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4700}
4701
4702#ifndef MINIZ_NO_STDIO
4703static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
4704{
4705 (void)ofs;
4706
4707 return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
4708}
4709
4710mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
4711{
4712 mz_bool status;
4713 mz_zip_archive_file_stat file_stat;
4714 MZ_FILE *pFile;
4715
4716 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4717 return MZ_FALSE;
4718
4719 if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
4721
4722 pFile = MZ_FOPEN(pDst_filename, "wb");
4723 if (!pFile)
4725
4726 status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
4727
4728 if (MZ_FCLOSE(pFile) == EOF)
4729 {
4730 if (status)
4732
4733 status = MZ_FALSE;
4734 }
4735
4736#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
4737 if (status)
4738 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
4739#endif
4740
4741 return status;
4742}
4743
4744mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
4745{
4746 mz_uint32 file_index;
4747 if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
4748 return MZ_FALSE;
4749
4750 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
4751}
4752
4754{
4755 mz_zip_archive_file_stat file_stat;
4756
4757 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4758 return MZ_FALSE;
4759
4760 if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
4762
4763 return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
4764}
4765
4766mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
4767{
4768 mz_uint32 file_index;
4769 if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
4770 return MZ_FALSE;
4771
4772 return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
4773}
4774#endif /* #ifndef MINIZ_NO_STDIO */
4775
4776static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
4777{
4778 mz_uint32 *p = (mz_uint32 *)pOpaque;
4779 (void)file_ofs;
4780 *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
4781 return n;
4782}
4783
4785{
4786 mz_zip_archive_file_stat file_stat;
4787 mz_zip_internal_state *pState;
4788 const mz_uint8 *pCentral_dir_header;
4789 mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
4790 mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
4791 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4792 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4793 mz_uint64 local_header_ofs = 0;
4794 mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
4795 mz_uint64 local_header_comp_size, local_header_uncomp_size;
4796 mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
4797 mz_bool has_data_descriptor;
4798 mz_uint32 local_header_bit_flags;
4799
4800 mz_zip_array file_data_array;
4801 mz_zip_array_init(&file_data_array, 1);
4802
4803 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
4805
4806 if (file_index > pZip->m_total_files)
4808
4809 pState = pZip->m_pState;
4810
4811 pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
4812
4813 if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
4814 return MZ_FALSE;
4815
4816 /* A directory or zero length file */
4817 if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
4818 return MZ_TRUE;
4819
4820 /* Encryption and patch files are not supported. */
4821 if (file_stat.m_is_encrypted)
4823
4824 /* This function only supports stored and deflate. */
4825 if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4827
4828 if (!file_stat.m_is_supported)
4830
4831 /* Read and parse the local directory entry. */
4832 local_header_ofs = file_stat.m_local_header_ofs;
4833 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4835
4836 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4838
4839 local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
4840 local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4841 local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
4842 local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
4843 local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
4844 local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
4845 has_data_descriptor = (local_header_bit_flags & 8) != 0;
4846
4847 if (local_header_filename_len != strlen(file_stat.m_filename))
4849
4850 if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)
4852
4853 if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
4855
4856 if (local_header_filename_len)
4857 {
4858 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)
4859 {
4861 goto handle_failure;
4862 }
4863
4864 /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */
4865 if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
4866 {
4868 goto handle_failure;
4869 }
4870 }
4871
4872 if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
4873 {
4874 mz_uint32 extra_size_remaining = local_header_extra_len;
4875 const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
4876
4877 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
4878 {
4880 goto handle_failure;
4881 }
4882
4883 do
4884 {
4885 mz_uint32 field_id, field_data_size, field_total_size;
4886
4887 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4889
4890 field_id = MZ_READ_LE16(pExtra_data);
4891 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4892 field_total_size = field_data_size + sizeof(mz_uint16) * 2;
4893
4894 if (field_total_size > extra_size_remaining)
4896
4898 {
4899 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
4900
4901 if (field_data_size < sizeof(mz_uint64) * 2)
4902 {
4904 goto handle_failure;
4905 }
4906
4907 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
4908 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
4909
4910 found_zip64_ext_data_in_ldir = MZ_TRUE;
4911 break;
4912 }
4913
4914 pExtra_data += field_total_size;
4915 extra_size_remaining -= field_total_size;
4916 } while (extra_size_remaining);
4917 }
4918
4919 /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
4920 /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
4921 if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
4922 {
4923 mz_uint8 descriptor_buf[32];
4924 mz_bool has_id;
4925 const mz_uint8 *pSrc;
4926 mz_uint32 file_crc32;
4927 mz_uint64 comp_size = 0, uncomp_size = 0;
4928
4929 mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
4930
4931 if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))
4932 {
4934 goto handle_failure;
4935 }
4936
4937 has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
4938 pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
4939
4940 file_crc32 = MZ_READ_LE32(pSrc);
4941
4942 if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
4943 {
4944 comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
4945 uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
4946 }
4947 else
4948 {
4949 comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
4950 uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
4951 }
4952
4953 if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
4954 {
4956 goto handle_failure;
4957 }
4958 }
4959 else
4960 {
4961 if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))
4962 {
4964 goto handle_failure;
4965 }
4966 }
4967
4968 mz_zip_array_clear(pZip, &file_data_array);
4969
4970 if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
4971 {
4972 if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
4973 return MZ_FALSE;
4974
4975 /* 1 more check to be sure, although the extract checks too. */
4976 if (uncomp_crc32 != file_stat.m_crc32)
4977 {
4979 return MZ_FALSE;
4980 }
4981 }
4982
4983 return MZ_TRUE;
4984
4985handle_failure:
4986 mz_zip_array_clear(pZip, &file_data_array);
4987 return MZ_FALSE;
4988}
4989
4991{
4992 mz_zip_internal_state *pState;
4993 uint32_t i;
4994
4995 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
4997
4998 pState = pZip->m_pState;
4999
5000 /* Basic sanity checks */
5001 if (!pState->m_zip64)
5002 {
5003 if (pZip->m_total_files > MZ_UINT16_MAX)
5005
5006 if (pZip->m_archive_size > MZ_UINT32_MAX)
5008 }
5009 else
5010 {
5011 if (pZip->m_total_files >= MZ_UINT32_MAX)
5013
5014 if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5016 }
5017
5018 for (i = 0; i < pZip->m_total_files; i++)
5019 {
5021 {
5022 mz_uint32 found_index;
5024
5025 if (!mz_zip_reader_file_stat(pZip, i, &stat))
5026 return MZ_FALSE;
5027
5028 if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5029 return MZ_FALSE;
5030
5031 /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
5032 if (found_index != i)
5034 }
5035
5036 if (!mz_zip_validate_file(pZip, i, flags))
5037 return MZ_FALSE;
5038 }
5039
5040 return MZ_TRUE;
5041}
5042
5043mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5044{
5045 mz_bool success = MZ_TRUE;
5046 mz_zip_archive zip;
5047 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5048
5049 if ((!pMem) || (!size))
5050 {
5051 if (pErr)
5053 return MZ_FALSE;
5054 }
5055
5056 mz_zip_zero_struct(&zip);
5057
5058 if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5059 {
5060 if (pErr)
5061 *pErr = zip.m_last_error;
5062 return MZ_FALSE;
5063 }
5064
5065 if (!mz_zip_validate_archive(&zip, flags))
5066 {
5067 actual_err = zip.m_last_error;
5068 success = MZ_FALSE;
5069 }
5070
5071 if (!mz_zip_reader_end_internal(&zip, success))
5072 {
5073 if (!actual_err)
5074 actual_err = zip.m_last_error;
5075 success = MZ_FALSE;
5076 }
5077
5078 if (pErr)
5079 *pErr = actual_err;
5080
5081 return success;
5082}
5083
5084#ifndef MINIZ_NO_STDIO
5085mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5086{
5087 mz_bool success = MZ_TRUE;
5088 mz_zip_archive zip;
5089 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5090
5091 if (!pFilename)
5092 {
5093 if (pErr)
5095 return MZ_FALSE;
5096 }
5097
5098 mz_zip_zero_struct(&zip);
5099
5100 if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5101 {
5102 if (pErr)
5103 *pErr = zip.m_last_error;
5104 return MZ_FALSE;
5105 }
5106
5107 if (!mz_zip_validate_archive(&zip, flags))
5108 {
5109 actual_err = zip.m_last_error;
5110 success = MZ_FALSE;
5111 }
5112
5113 if (!mz_zip_reader_end_internal(&zip, success))
5114 {
5115 if (!actual_err)
5116 actual_err = zip.m_last_error;
5117 success = MZ_FALSE;
5118 }
5119
5120 if (pErr)
5121 *pErr = actual_err;
5122
5123 return success;
5124}
5125#endif /* #ifndef MINIZ_NO_STDIO */
5126
5127/* ------------------- .ZIP archive writing */
5128
5129#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5130
5132{
5133 p[0] = (mz_uint8)v;
5134 p[1] = (mz_uint8)(v >> 8);
5135}
5137{
5138 p[0] = (mz_uint8)v;
5139 p[1] = (mz_uint8)(v >> 8);
5140 p[2] = (mz_uint8)(v >> 16);
5141 p[3] = (mz_uint8)(v >> 24);
5142}
5144{
5145 mz_write_le32(p, (mz_uint32)v);
5146 mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5147}
5148
5149#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5150#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5151#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5152
5153static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5154{
5155 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5156 mz_zip_internal_state *pState = pZip->m_pState;
5157 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5158
5159 if (!n)
5160 return 0;
5161
5162 /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5163 if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5164 {
5166 return 0;
5167 }
5168
5169 if (new_size > pState->m_mem_capacity)
5170 {
5171 void *pNew_block;
5172 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5173
5174 while (new_capacity < new_size)
5175 new_capacity *= 2;
5176
5177 if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5178 {
5180 return 0;
5181 }
5182
5183 pState->m_pMem = pNew_block;
5184 pState->m_mem_capacity = new_capacity;
5185 }
5186 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5187 pState->m_mem_size = (size_t)new_size;
5188 return n;
5189}
5190
5192{
5193 mz_zip_internal_state *pState;
5194 mz_bool status = MZ_TRUE;
5195
5196 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
5197 {
5198 if (set_last_error)
5200 return MZ_FALSE;
5201 }
5202
5203 pState = pZip->m_pState;
5204 pZip->m_pState = NULL;
5205 mz_zip_array_clear(pZip, &pState->m_central_dir);
5208
5209#ifndef MINIZ_NO_STDIO
5210 if (pState->m_pFile)
5211 {
5212 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5213 {
5214 if (MZ_FCLOSE(pState->m_pFile) == EOF)
5215 {
5216 if (set_last_error)
5218 status = MZ_FALSE;
5219 }
5220 }
5221
5222 pState->m_pFile = NULL;
5223 }
5224#endif /* #ifndef MINIZ_NO_STDIO */
5225
5226 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5227 {
5228 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5229 pState->m_pMem = NULL;
5230 }
5231
5232 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5234 return status;
5235}
5236
5238{
5239 mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5240
5241 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5243
5245 {
5246 if (!pZip->m_pRead)
5248 }
5249
5250 if (pZip->m_file_offset_alignment)
5251 {
5252 /* Ensure user specified file offset alignment is a power of 2. */
5253 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5255 }
5256
5257 if (!pZip->m_pAlloc)
5259 if (!pZip->m_pFree)
5261 if (!pZip->m_pRealloc)
5263
5264 pZip->m_archive_size = existing_size;
5266 pZip->m_total_files = 0;
5267
5268 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5270
5271 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5272
5276
5277 pZip->m_pState->m_zip64 = zip64;
5279
5282
5283 return MZ_TRUE;
5284}
5285
5287{
5288 return mz_zip_writer_init_v2(pZip, existing_size, 0);
5289}
5290
5291mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
5292{
5294 pZip->m_pNeeds_keepalive = NULL;
5295
5298
5299 pZip->m_pIO_opaque = pZip;
5300
5301 if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5302 return MZ_FALSE;
5303
5305
5306 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5307 {
5308 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5309 {
5312 }
5313 pZip->m_pState->m_mem_capacity = initial_allocation_size;
5314 }
5315
5316 return MZ_TRUE;
5317}
5318
5319mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5320{
5321 return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5322}
5323
5324#ifndef MINIZ_NO_STDIO
5325static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5326{
5327 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5328 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5329
5330 file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5331
5332 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5333 {
5335 return 0;
5336 }
5337
5338 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5339}
5340
5341mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5342{
5343 return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5344}
5345
5346mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
5347{
5348 MZ_FILE *pFile;
5349
5351 pZip->m_pNeeds_keepalive = NULL;
5352
5355
5356 pZip->m_pIO_opaque = pZip;
5357
5358 if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5359 return MZ_FALSE;
5360
5361 if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5362 {
5363 mz_zip_writer_end(pZip);
5365 }
5366
5367 pZip->m_pState->m_pFile = pFile;
5369
5370 if (size_to_reserve_at_beginning)
5371 {
5372 mz_uint64 cur_ofs = 0;
5373 char buf[4096];
5374
5375 MZ_CLEAR_OBJ(buf);
5376
5377 do
5378 {
5379 size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5380 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5381 {
5382 mz_zip_writer_end(pZip);
5384 }
5385 cur_ofs += n;
5386 size_to_reserve_at_beginning -= n;
5387 } while (size_to_reserve_at_beginning);
5388 }
5389
5390 return MZ_TRUE;
5391}
5392
5394{
5396 pZip->m_pNeeds_keepalive = NULL;
5397
5400
5401 pZip->m_pIO_opaque = pZip;
5402
5403 if (!mz_zip_writer_init_v2(pZip, 0, flags))
5404 return MZ_FALSE;
5405
5406 pZip->m_pState->m_pFile = pFile;
5409
5410 return MZ_TRUE;
5411}
5412#endif /* #ifndef MINIZ_NO_STDIO */
5413
5415{
5416 mz_zip_internal_state *pState;
5417
5418 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5420
5421 if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5422 {
5423 /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */
5424 if (!pZip->m_pState->m_zip64)
5426 }
5427
5428 /* No sense in trying to write to an archive that's already at the support max size */
5429 if (pZip->m_pState->m_zip64)
5430 {
5431 if (pZip->m_total_files == MZ_UINT32_MAX)
5433 }
5434 else
5435 {
5436 if (pZip->m_total_files == MZ_UINT16_MAX)
5438
5441 }
5442
5443 pState = pZip->m_pState;
5444
5445 if (pState->m_pFile)
5446 {
5447#ifdef MINIZ_NO_STDIO
5448 (void)pFilename;
5450#else
5451 if (pZip->m_pIO_opaque != pZip)
5453
5454 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5455 {
5456 if (!pFilename)
5458
5459 /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
5460 if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
5461 {
5462 /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
5465 }
5466 }
5467
5469 pZip->m_pNeeds_keepalive = NULL;
5470#endif /* #ifdef MINIZ_NO_STDIO */
5471 }
5472 else if (pState->m_pMem)
5473 {
5474 /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
5475 if (pZip->m_pIO_opaque != pZip)
5477
5478 pState->m_mem_capacity = pState->m_mem_size;
5480 pZip->m_pNeeds_keepalive = NULL;
5481 }
5482 /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
5483 else if (!pZip->m_pWrite)
5485
5486 /* Start writing new files at the archive's current central directory location. */
5487 /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
5490
5491 /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
5492 /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
5493 /* TODO: We could easily maintain the sorted central directory offsets. */
5495
5497
5498 return MZ_TRUE;
5499}
5500
5502{
5503 return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
5504}
5505
5506/* TODO: pArchive_name is a terrible name here! */
5507mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
5508{
5509 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
5510}
5511
5512typedef struct
5513{
5518
5519static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
5520{
5522 if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
5523 return MZ_FALSE;
5524
5525 pState->m_cur_archive_file_ofs += len;
5526 pState->m_comp_size += len;
5527 return MZ_TRUE;
5528}
5529
5530#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
5531#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
5532static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
5533{
5534 mz_uint8 *pDst = pBuf;
5535 mz_uint32 field_size = 0;
5536
5538 MZ_WRITE_LE16(pDst + 2, 0);
5539 pDst += sizeof(mz_uint16) * 2;
5540
5541 if (pUncomp_size)
5542 {
5543 MZ_WRITE_LE64(pDst, *pUncomp_size);
5544 pDst += sizeof(mz_uint64);
5545 field_size += sizeof(mz_uint64);
5546 }
5547
5548 if (pComp_size)
5549 {
5550 MZ_WRITE_LE64(pDst, *pComp_size);
5551 pDst += sizeof(mz_uint64);
5552 field_size += sizeof(mz_uint64);
5553 }
5554
5555 if (pLocal_header_ofs)
5556 {
5557 MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
5558 pDst += sizeof(mz_uint64);
5559 field_size += sizeof(mz_uint64);
5560 }
5561
5562 MZ_WRITE_LE16(pBuf + 2, field_size);
5563
5564 return (mz_uint32)(pDst - pBuf);
5565}
5566
5567static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
5568{
5569 (void)pZip;
5570 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5572 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5573 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5574 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5575 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5576 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5577 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5580 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
5581 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
5582 return MZ_TRUE;
5583}
5584
5586 mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
5587 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
5588 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
5589 mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
5590{
5591 (void)pZip;
5592 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
5594 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5595 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
5596 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
5597 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
5598 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
5599 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
5602 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
5603 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
5604 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
5605 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
5607 return MZ_TRUE;
5608}
5609
5610static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
5611 const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
5612 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
5613 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
5614 mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
5615 const char *user_extra_data, mz_uint user_extra_data_len)
5616{
5617 mz_zip_internal_state *pState = pZip->m_pState;
5618 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
5619 size_t orig_central_dir_size = pState->m_central_dir.m_size;
5620 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
5621
5622 if (!pZip->m_pState->m_zip64)
5623 {
5624 if (local_header_ofs > 0xFFFFFFFF)
5626 }
5627
5628 /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
5629 if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
5631
5632 if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
5634
5635 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
5636 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
5637 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
5638 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
5639 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
5640 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
5641 {
5642 /* Try to resize the central directory array back into its original state. */
5643 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
5645 }
5646
5647 return MZ_TRUE;
5648}
5649
5650static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
5651{
5652 /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */
5653 if (*pArchive_name == '/')
5654 return MZ_FALSE;
5655
5656 while (*pArchive_name)
5657 {
5658 if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
5659 return MZ_FALSE;
5660
5661 pArchive_name++;
5662 }
5663
5664 return MZ_TRUE;
5665}
5666
5668{
5669 mz_uint32 n;
5670 if (!pZip->m_file_offset_alignment)
5671 return 0;
5672 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
5673 return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
5674}
5675
5677{
5678 char buf[4096];
5679 memset(buf, 0, MZ_MIN(sizeof(buf), n));
5680 while (n)
5681 {
5682 mz_uint32 s = MZ_MIN(sizeof(buf), n);
5683 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
5685
5686 cur_file_ofs += s;
5687 n -= s;
5688 }
5689 return MZ_TRUE;
5690}
5691
5692mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
5693 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
5694{
5695 return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
5696}
5697
5698mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
5699 mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
5700 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
5701{
5702 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
5703 mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
5704 mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
5705 size_t archive_name_size;
5706 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
5707 tdefl_compressor *pComp = NULL;
5708 mz_bool store_data_uncompressed;
5709 mz_zip_internal_state *pState;
5710 mz_uint8 *pExtra_data = NULL;
5711 mz_uint32 extra_size = 0;
5713 mz_uint16 bit_flags = 0;
5714
5715 if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5717
5718 if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
5720
5721 if ((int)level_and_flags < 0)
5722 level_and_flags = MZ_DEFAULT_LEVEL;
5723 level = level_and_flags & 0xF;
5724 store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
5725
5726 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
5728
5729 pState = pZip->m_pState;
5730
5731 if (pState->m_zip64)
5732 {
5733 if (pZip->m_total_files == MZ_UINT32_MAX)
5735 }
5736 else
5737 {
5738 if (pZip->m_total_files == MZ_UINT16_MAX)
5739 {
5740 pState->m_zip64 = MZ_TRUE;
5741 /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
5742 }
5743 if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
5744 {
5745 pState->m_zip64 = MZ_TRUE;
5746 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
5747 }
5748 }
5749
5750 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
5752
5753 if (!mz_zip_writer_validate_archive_name(pArchive_name))
5755
5756#ifndef MINIZ_NO_TIME
5757 if (last_modified != NULL)
5758 {
5759 mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
5760 }
5761 else
5762 {
5763 MZ_TIME_T cur_time;
5764 time(&cur_time);
5765 mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
5766 }
5767#endif /* #ifndef MINIZ_NO_TIME */
5768
5769 archive_name_size = strlen(pArchive_name);
5770 if (archive_name_size > MZ_UINT16_MAX)
5772
5773 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
5774
5775 /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
5778
5779 if (!pState->m_zip64)
5780 {
5781 /* Bail early if the archive would obviously become too large */
5782 if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)
5783 {
5784 pState->m_zip64 = MZ_TRUE;
5785 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
5786 }
5787 }
5788
5789 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
5790 {
5791 /* Set DOS Subdirectory attribute bit. */
5792 ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
5793
5794 /* Subdirectories cannot contain data. */
5795 if ((buf_size) || (uncomp_size))
5797 }
5798
5799 /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */
5800 if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
5802
5803 if ((!store_data_uncompressed) && (buf_size))
5804 {
5805 if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
5807 }
5808
5809 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
5810 {
5811 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
5812 return MZ_FALSE;
5813 }
5814
5815 local_dir_header_ofs += num_alignment_padding_bytes;
5816 if (pZip->m_file_offset_alignment)
5817 {
5818 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
5819 }
5820 cur_archive_file_ofs += num_alignment_padding_bytes;
5821
5822 MZ_CLEAR_OBJ(local_dir_header);
5823
5824 if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5825 {
5826 method = MZ_DEFLATED;
5827 }
5828
5829 if (pState->m_zip64)
5830 {
5831 if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
5832 {
5833 pExtra_data = extra_data;
5834 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
5835 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
5836 }
5837
5838 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
5840
5841 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
5843
5844 cur_archive_file_ofs += sizeof(local_dir_header);
5845
5846 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
5847 {
5848 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
5850 }
5851 cur_archive_file_ofs += archive_name_size;
5852
5853 if (pExtra_data != NULL)
5854 {
5855 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
5857
5858 cur_archive_file_ofs += extra_size;
5859 }
5860 }
5861 else
5862 {
5863 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
5865 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
5867
5868 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
5870
5871 cur_archive_file_ofs += sizeof(local_dir_header);
5872
5873 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
5874 {
5875 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
5877 }
5878 cur_archive_file_ofs += archive_name_size;
5879 }
5880
5881 if (user_extra_data_len > 0)
5882 {
5883 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
5885
5886 cur_archive_file_ofs += user_extra_data_len;
5887 }
5888
5889 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5890 {
5891 uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
5892 uncomp_size = buf_size;
5893 if (uncomp_size <= 3)
5894 {
5895 level = 0;
5896 store_data_uncompressed = MZ_TRUE;
5897 }
5898 }
5899
5900 if (store_data_uncompressed)
5901 {
5902 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
5903 {
5904 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
5906 }
5907
5908 cur_archive_file_ofs += buf_size;
5909 comp_size = buf_size;
5910 }
5911 else if (buf_size)
5912 {
5914
5915 state.m_pZip = pZip;
5916 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
5917 state.m_comp_size = 0;
5918
5920 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
5921 {
5922 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
5924 }
5925
5926 comp_size = state.m_comp_size;
5927 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
5928 }
5929
5930 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
5931 pComp = NULL;
5932
5933 if (uncomp_size)
5934 {
5935 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
5936 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
5937
5939
5940 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
5941 MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
5942 if (pExtra_data == NULL)
5943 {
5944 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
5946
5947 MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
5948 MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
5949 }
5950 else
5951 {
5952 MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
5953 MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
5954 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
5955 }
5956
5957 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
5958 return MZ_FALSE;
5959
5960 cur_archive_file_ofs += local_dir_footer_size;
5961 }
5962
5963 if (pExtra_data != NULL)
5964 {
5965 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
5966 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
5967 }
5968
5969 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment,
5970 comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
5971 user_extra_data_central, user_extra_data_central_len))
5972 return MZ_FALSE;
5973
5974 pZip->m_total_files++;
5975 pZip->m_archive_size = cur_archive_file_ofs;
5976
5977 return MZ_TRUE;
5978}
5979
5980#ifndef MINIZ_NO_STDIO
5981mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
5982 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
5983{
5985 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
5986 mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
5987 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
5988 size_t archive_name_size;
5989 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
5990 mz_uint8 *pExtra_data = NULL;
5991 mz_uint32 extra_size = 0;
5993 mz_zip_internal_state *pState;
5994
5995 if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
5997
5998 if ((int)level_and_flags < 0)
5999 level_and_flags = MZ_DEFAULT_LEVEL;
6000 level = level_and_flags & 0xF;
6001
6002 /* Sanity checks */
6003 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6005
6006 pState = pZip->m_pState;
6007
6008 if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6009 {
6010 /* Source file is too large for non-zip64 */
6011 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6012 pState->m_zip64 = MZ_TRUE;
6013 }
6014
6015 /* We could support this, but why? */
6016 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6018
6019 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6021
6022 if (pState->m_zip64)
6023 {
6024 if (pZip->m_total_files == MZ_UINT32_MAX)
6026 }
6027 else
6028 {
6029 if (pZip->m_total_files == MZ_UINT16_MAX)
6030 {
6031 pState->m_zip64 = MZ_TRUE;
6032 /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6033 }
6034 }
6035
6036 archive_name_size = strlen(pArchive_name);
6037 if (archive_name_size > MZ_UINT16_MAX)
6039
6040 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6041
6042 /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6045
6046 if (!pState->m_zip64)
6047 {
6048 /* Bail early if the archive would obviously become too large */
6049 if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024) > 0xFFFFFFFF)
6050 {
6051 pState->m_zip64 = MZ_TRUE;
6052 /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6053 }
6054 }
6055
6056#ifndef MINIZ_NO_TIME
6057 if (pFile_time)
6058 {
6059 mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6060 }
6061#endif
6062
6063 if (uncomp_size <= 3)
6064 level = 0;
6065
6066 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6067 {
6069 }
6070
6071 cur_archive_file_ofs += num_alignment_padding_bytes;
6072 local_dir_header_ofs = cur_archive_file_ofs;
6073
6074 if (pZip->m_file_offset_alignment)
6075 {
6076 MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6077 }
6078
6079 if (uncomp_size && level)
6080 {
6081 method = MZ_DEFLATED;
6082 }
6083
6084 MZ_CLEAR_OBJ(local_dir_header);
6085 if (pState->m_zip64)
6086 {
6087 if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6088 {
6089 pExtra_data = extra_data;
6090 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6091 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6092 }
6093
6094 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6096
6097 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6099
6100 cur_archive_file_ofs += sizeof(local_dir_header);
6101
6102 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6103 {
6105 }
6106
6107 cur_archive_file_ofs += archive_name_size;
6108
6109 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6111
6112 cur_archive_file_ofs += extra_size;
6113 }
6114 else
6115 {
6116 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6118 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6120
6121 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6123
6124 cur_archive_file_ofs += sizeof(local_dir_header);
6125
6126 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6127 {
6129 }
6130
6131 cur_archive_file_ofs += archive_name_size;
6132 }
6133
6134 if (user_extra_data_len > 0)
6135 {
6136 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6138
6139 cur_archive_file_ofs += user_extra_data_len;
6140 }
6141
6142 if (uncomp_size)
6143 {
6144 mz_uint64 uncomp_remaining = uncomp_size;
6145 void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6146 if (!pRead_buf)
6147 {
6149 }
6150
6151 if (!level)
6152 {
6153 while (uncomp_remaining)
6154 {
6155 mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6156 if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
6157 {
6158 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6160 }
6161 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6162 uncomp_remaining -= n;
6163 cur_archive_file_ofs += n;
6164 }
6165 comp_size = uncomp_size;
6166 }
6167 else
6168 {
6169 mz_bool result = MZ_FALSE;
6171 tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6172 if (!pComp)
6173 {
6174 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6176 }
6177
6178 state.m_pZip = pZip;
6179 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6180 state.m_comp_size = 0;
6181
6183 {
6184 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6185 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6187 }
6188
6189 for (;;)
6190 {
6191 size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6192 tdefl_status status;
6194
6195 if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6196 {
6198 break;
6199 }
6200
6201 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6202 uncomp_remaining -= in_buf_size;
6203
6204 if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6205 flush = TDEFL_FULL_FLUSH;
6206
6207 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6208 if (status == TDEFL_STATUS_DONE)
6209 {
6210 result = MZ_TRUE;
6211 break;
6212 }
6213 else if (status != TDEFL_STATUS_OKAY)
6214 {
6216 break;
6217 }
6218 }
6219
6220 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6221
6222 if (!result)
6223 {
6224 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6225 return MZ_FALSE;
6226 }
6227
6228 comp_size = state.m_comp_size;
6229 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6230 }
6231
6232 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6233 }
6234
6235 {
6236 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6237 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6238
6239 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6240 MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6241 if (pExtra_data == NULL)
6242 {
6243 if (comp_size > MZ_UINT32_MAX)
6245
6246 MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6247 MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6248 }
6249 else
6250 {
6251 MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6252 MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6253 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6254 }
6255
6256 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6257 return MZ_FALSE;
6258
6259 cur_archive_file_ofs += local_dir_footer_size;
6260 }
6261
6262 if (pExtra_data != NULL)
6263 {
6264 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6265 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6266 }
6267
6268 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size,
6269 uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6270 user_extra_data_central, user_extra_data_central_len))
6271 return MZ_FALSE;
6272
6273 pZip->m_total_files++;
6274 pZip->m_archive_size = cur_archive_file_ofs;
6275
6276 return MZ_TRUE;
6277}
6278
6279mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
6280{
6281 MZ_FILE *pSrc_file = NULL;
6282 mz_uint64 uncomp_size = 0;
6283 MZ_TIME_T file_modified_time;
6284 MZ_TIME_T *pFile_time = NULL;
6285 mz_bool status;
6286
6287 memset(&file_modified_time, 0, sizeof(file_modified_time));
6288
6289#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6290 pFile_time = &file_modified_time;
6291 if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6293#endif
6294
6295 pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6296 if (!pSrc_file)
6298
6299 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6300 uncomp_size = MZ_FTELL64(pSrc_file);
6301 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6302
6303 status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);
6304
6305 MZ_FCLOSE(pSrc_file);
6306
6307 return status;
6308}
6309#endif /* #ifndef MINIZ_NO_STDIO */
6310
6311static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
6312{
6313 /* + 64 should be enough for any new zip64 data */
6314 if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6316
6317 mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6318
6319 if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6320 {
6321 mz_uint8 new_ext_block[64];
6322 mz_uint8 *pDst = new_ext_block;
6324 mz_write_le16(pDst + sizeof(mz_uint16), 0);
6325 pDst += sizeof(mz_uint16) * 2;
6326
6327 if (pUncomp_size)
6328 {
6329 mz_write_le64(pDst, *pUncomp_size);
6330 pDst += sizeof(mz_uint64);
6331 }
6332
6333 if (pComp_size)
6334 {
6335 mz_write_le64(pDst, *pComp_size);
6336 pDst += sizeof(mz_uint64);
6337 }
6338
6339 if (pLocal_header_ofs)
6340 {
6341 mz_write_le64(pDst, *pLocal_header_ofs);
6342 pDst += sizeof(mz_uint64);
6343 }
6344
6345 if (pDisk_start)
6346 {
6347 mz_write_le32(pDst, *pDisk_start);
6348 pDst += sizeof(mz_uint32);
6349 }
6350
6351 mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6352
6353 if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6355 }
6356
6357 if ((pExt) && (ext_len))
6358 {
6359 mz_uint32 extra_size_remaining = ext_len;
6360 const mz_uint8 *pExtra_data = pExt;
6361
6362 do
6363 {
6364 mz_uint32 field_id, field_data_size, field_total_size;
6365
6366 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6368
6369 field_id = MZ_READ_LE16(pExtra_data);
6370 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6371 field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6372
6373 if (field_total_size > extra_size_remaining)
6375
6377 {
6378 if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6380 }
6381
6382 pExtra_data += field_total_size;
6383 extra_size_remaining -= field_total_size;
6384 } while (extra_size_remaining);
6385 }
6386
6387 return MZ_TRUE;
6388}
6389
6390/* TODO: This func is now pretty freakin complex due to zip64, split it up? */
6392{
6393 mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6394 mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6395 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6396 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
6397 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6398 mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6399 size_t orig_central_dir_size;
6400 mz_zip_internal_state *pState;
6401 void *pBuf;
6402 const mz_uint8 *pSrc_central_header;
6403 mz_zip_archive_file_stat src_file_stat;
6404 mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6405 mz_uint32 local_header_filename_size, local_header_extra_len;
6406 mz_uint64 local_header_comp_size, local_header_uncomp_size;
6407 mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6408
6409 /* Sanity checks */
6410 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6412
6413 pState = pZip->m_pState;
6414
6415 /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
6416 if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6418
6419 /* Get pointer to the source central dir header and crack it */
6420 if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
6422
6425
6426 src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6427 src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6428 src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
6429 src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
6430
6431 /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */
6432 if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
6434
6435 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6436
6437 if (!pState->m_zip64)
6438 {
6439 if (pZip->m_total_files == MZ_UINT16_MAX)
6441 }
6442 else
6443 {
6444 /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
6445 if (pZip->m_total_files == MZ_UINT32_MAX)
6447 }
6448
6449 if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
6450 return MZ_FALSE;
6451
6452 cur_src_file_ofs = src_file_stat.m_local_header_ofs;
6453 cur_dst_file_ofs = pZip->m_archive_size;
6454
6455 /* Read the source archive's local dir header */
6456 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6458
6459 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6461
6462 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6463
6464 /* Compute the total size we need to copy (filename+extra data+compressed data) */
6465 local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
6466 local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6467 local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
6468 local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
6469 src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
6470
6471 /* Try to find a zip64 extended information field */
6472 if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
6473 {
6474 mz_zip_array file_data_array;
6475 const mz_uint8 *pExtra_data;
6476 mz_uint32 extra_size_remaining = local_header_extra_len;
6477
6478 mz_zip_array_init(&file_data_array, 1);
6479 if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
6480 {
6482 }
6483
6484 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
6485 {
6486 mz_zip_array_clear(pZip, &file_data_array);
6488 }
6489
6490 pExtra_data = (const mz_uint8 *)file_data_array.m_p;
6491
6492 do
6493 {
6494 mz_uint32 field_id, field_data_size, field_total_size;
6495
6496 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6497 {
6498 mz_zip_array_clear(pZip, &file_data_array);
6500 }
6501
6502 field_id = MZ_READ_LE16(pExtra_data);
6503 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6504 field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6505
6506 if (field_total_size > extra_size_remaining)
6507 {
6508 mz_zip_array_clear(pZip, &file_data_array);
6510 }
6511
6513 {
6514 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
6515
6516 if (field_data_size < sizeof(mz_uint64) * 2)
6517 {
6518 mz_zip_array_clear(pZip, &file_data_array);
6520 }
6521
6522 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
6523 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
6524
6525 found_zip64_ext_data_in_ldir = MZ_TRUE;
6526 break;
6527 }
6528
6529 pExtra_data += field_total_size;
6530 extra_size_remaining -= field_total_size;
6531 } while (extra_size_remaining);
6532
6533 mz_zip_array_clear(pZip, &file_data_array);
6534 }
6535
6536 if (!pState->m_zip64)
6537 {
6538 /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */
6539 /* We also check when the archive is finalized so this doesn't need to be perfect. */
6540 mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +
6541 pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
6542
6543 if (approx_new_archive_size >= MZ_UINT32_MAX)
6545 }
6546
6547 /* Write dest archive padding */
6548 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
6549 return MZ_FALSE;
6550
6551 cur_dst_file_ofs += num_alignment_padding_bytes;
6552
6553 local_dir_header_ofs = cur_dst_file_ofs;
6554 if (pZip->m_file_offset_alignment)
6555 {
6556 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6557 }
6558
6559 /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */
6560 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6562
6563 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6564
6565 /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
6566 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
6568
6569 while (src_archive_bytes_remaining)
6570 {
6571 n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
6572 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
6573 {
6574 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6576 }
6577 cur_src_file_ofs += n;
6578
6579 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
6580 {
6581 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6583 }
6584 cur_dst_file_ofs += n;
6585
6586 src_archive_bytes_remaining -= n;
6587 }
6588
6589 /* Now deal with the optional data descriptor */
6590 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6591 if (bit_flags & 8)
6592 {
6593 /* Copy data descriptor */
6594 if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
6595 {
6596 /* src is zip64, dest must be zip64 */
6597
6598 /* name uint32_t's */
6599 /* id 1 (optional in zip64?) */
6600 /* crc 1 */
6601 /* comp_size 2 */
6602 /* uncomp_size 2 */
6603 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
6604 {
6605 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6607 }
6608
6609 n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
6610 }
6611 else
6612 {
6613 /* src is NOT zip64 */
6614 mz_bool has_id;
6615
6616 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
6617 {
6618 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6620 }
6621
6622 has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
6623
6624 if (pZip->m_pState->m_zip64)
6625 {
6626 /* dest is zip64, so upgrade the data descriptor */
6627 const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
6628 const mz_uint32 src_crc32 = pSrc_descriptor[0];
6629 const mz_uint64 src_comp_size = pSrc_descriptor[1];
6630 const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
6631
6633 mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
6634 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
6635 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
6636
6637 n = sizeof(mz_uint32) * 6;
6638 }
6639 else
6640 {
6641 /* dest is NOT zip64, just copy it as-is */
6642 n = sizeof(mz_uint32) * (has_id ? 4 : 3);
6643 }
6644 }
6645
6646 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
6647 {
6648 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6650 }
6651
6652 cur_src_file_ofs += n;
6653 cur_dst_file_ofs += n;
6654 }
6655 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6656
6657 /* Finally, add the new central dir header */
6658 orig_central_dir_size = pState->m_central_dir.m_size;
6659
6660 memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6661
6662 if (pState->m_zip64)
6663 {
6664 /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */
6665 const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
6666 mz_zip_array new_ext_block;
6667
6668 mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
6669
6673
6674 if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))
6675 {
6676 mz_zip_array_clear(pZip, &new_ext_block);
6677 return MZ_FALSE;
6678 }
6679
6680 MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
6681
6682 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6683 {
6684 mz_zip_array_clear(pZip, &new_ext_block);
6686 }
6687
6688 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
6689 {
6690 mz_zip_array_clear(pZip, &new_ext_block);
6691 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6693 }
6694
6695 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
6696 {
6697 mz_zip_array_clear(pZip, &new_ext_block);
6698 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6700 }
6701
6702 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))
6703 {
6704 mz_zip_array_clear(pZip, &new_ext_block);
6705 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6707 }
6708
6709 mz_zip_array_clear(pZip, &new_ext_block);
6710 }
6711 else
6712 {
6713 /* sanity checks */
6714 if (cur_dst_file_ofs > MZ_UINT32_MAX)
6716
6717 if (local_dir_header_ofs >= MZ_UINT32_MAX)
6719
6720 MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
6721
6722 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6724
6725 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))
6726 {
6727 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6729 }
6730 }
6731
6732 /* This shouldn't trigger unless we screwed up during the initial sanity checks */
6733 if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
6734 {
6735 /* TODO: Support central dirs >= 32-bits in size */
6736 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6738 }
6739
6740 n = (mz_uint32)orig_central_dir_size;
6741 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
6742 {
6743 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6745 }
6746
6747 pZip->m_total_files++;
6748 pZip->m_archive_size = cur_dst_file_ofs;
6749
6750 return MZ_TRUE;
6751}
6752
6754{
6755 mz_zip_internal_state *pState;
6756 mz_uint64 central_dir_ofs, central_dir_size;
6757 mz_uint8 hdr[256];
6758
6759 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6761
6762 pState = pZip->m_pState;
6763
6764 if (pState->m_zip64)
6765 {
6766 if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
6768 }
6769 else
6770 {
6773 }
6774
6775 central_dir_ofs = 0;
6776 central_dir_size = 0;
6777 if (pZip->m_total_files)
6778 {
6779 /* Write central directory */
6780 central_dir_ofs = pZip->m_archive_size;
6781 central_dir_size = pState->m_central_dir.m_size;
6782 pZip->m_central_directory_file_ofs = central_dir_ofs;
6783 if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
6785
6786 pZip->m_archive_size += central_dir_size;
6787 }
6788
6789 if (pState->m_zip64)
6790 {
6791 /* Write zip64 end of central directory header */
6792 mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
6793
6794 MZ_CLEAR_OBJ(hdr);
6797 MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
6801 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
6802 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6805
6807
6808 /* Write zip64 end of central directory locator */
6809 MZ_CLEAR_OBJ(hdr);
6811 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
6815
6817 }
6818
6819 /* Write end of central directory record */
6820 MZ_CLEAR_OBJ(hdr);
6826
6829
6830#ifndef MINIZ_NO_STDIO
6831 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
6833#endif /* #ifndef MINIZ_NO_STDIO */
6834
6836
6838 return MZ_TRUE;
6839}
6840
6842{
6843 if ((!ppBuf) || (!pSize))
6845
6846 *ppBuf = NULL;
6847 *pSize = 0;
6848
6849 if ((!pZip) || (!pZip->m_pState))
6851
6852 if (pZip->m_pWrite != mz_zip_heap_write_func)
6854
6856 return MZ_FALSE;
6857
6858 *ppBuf = pZip->m_pState->m_pMem;
6859 *pSize = pZip->m_pState->m_mem_size;
6860 pZip->m_pState->m_pMem = NULL;
6861 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6862
6863 return MZ_TRUE;
6864}
6865
6867{
6868 return mz_zip_writer_end_internal(pZip, MZ_TRUE);
6869}
6870
6871#ifndef MINIZ_NO_STDIO
6872mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
6873{
6874 return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);
6875}
6876
6877mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
6878{
6879 mz_bool status, created_new_archive = MZ_FALSE;
6880 mz_zip_archive zip_archive;
6881 struct MZ_FILE_STAT_STRUCT file_stat;
6882 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
6883
6884 mz_zip_zero_struct(&zip_archive);
6885 if ((int)level_and_flags < 0)
6886 level_and_flags = MZ_DEFAULT_LEVEL;
6887
6888 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6889 {
6890 if (pErr)
6892 return MZ_FALSE;
6893 }
6894
6895 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6896 {
6897 if (pErr)
6899 return MZ_FALSE;
6900 }
6901
6902 /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */
6903 /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
6904 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
6905 {
6906 /* Create a new archive. */
6907 if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
6908 {
6909 if (pErr)
6910 *pErr = zip_archive.m_last_error;
6911 return MZ_FALSE;
6912 }
6913
6914 created_new_archive = MZ_TRUE;
6915 }
6916 else
6917 {
6918 /* Append to an existing archive. */
6919 if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
6920 {
6921 if (pErr)
6922 *pErr = zip_archive.m_last_error;
6923 return MZ_FALSE;
6924 }
6925
6926 if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
6927 {
6928 if (pErr)
6929 *pErr = zip_archive.m_last_error;
6930
6931 mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
6932
6933 return MZ_FALSE;
6934 }
6935 }
6936
6937 status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
6938 actual_err = zip_archive.m_last_error;
6939
6940 /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */
6941 if (!mz_zip_writer_finalize_archive(&zip_archive))
6942 {
6943 if (!actual_err)
6944 actual_err = zip_archive.m_last_error;
6945
6946 status = MZ_FALSE;
6947 }
6948
6949 if (!mz_zip_writer_end_internal(&zip_archive, status))
6950 {
6951 if (!actual_err)
6952 actual_err = zip_archive.m_last_error;
6953
6954 status = MZ_FALSE;
6955 }
6956
6957 if ((!status) && (created_new_archive))
6958 {
6959 /* It's a new archive and something went wrong, so just delete it. */
6960 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6961 (void)ignoredStatus;
6962 }
6963
6964 if (pErr)
6965 *pErr = actual_err;
6966
6967 return status;
6968}
6969
6970void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
6971{
6972 mz_uint32 file_index;
6973 mz_zip_archive zip_archive;
6974 void *p = NULL;
6975
6976 if (pSize)
6977 *pSize = 0;
6978
6979 if ((!pZip_filename) || (!pArchive_name))
6980 {
6981 if (pErr)
6983
6984 return NULL;
6985 }
6986
6987 mz_zip_zero_struct(&zip_archive);
6988 if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
6989 {
6990 if (pErr)
6991 *pErr = zip_archive.m_last_error;
6992
6993 return NULL;
6994 }
6995
6996 if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
6997 {
6998 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6999 }
7000
7001 mz_zip_reader_end_internal(&zip_archive, p != NULL);
7002
7003 if (pErr)
7004 *pErr = zip_archive.m_last_error;
7005
7006 return p;
7007}
7008
7009void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
7010{
7011 return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7012}
7013
7014#endif /* #ifndef MINIZ_NO_STDIO */
7015
7016#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
7017
7018/* ------------------- Misc utils */
7019
7021{
7022 return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7023}
7024
7026{
7027 return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7028}
7029
7031{
7032 mz_zip_error prev_err;
7033
7034 if (!pZip)
7036
7037 prev_err = pZip->m_last_error;
7038
7039 pZip->m_last_error = err_num;
7040 return prev_err;
7041}
7042
7044{
7045 if (!pZip)
7047
7048 return pZip->m_last_error;
7049}
7050
7052{
7054}
7055
7057{
7058 mz_zip_error prev_err;
7059
7060 if (!pZip)
7062
7063 prev_err = pZip->m_last_error;
7064
7066 return prev_err;
7067}
7068
7070{
7071 switch (mz_err)
7072 {
7073 case MZ_ZIP_NO_ERROR:
7074 return "no error";
7076 return "undefined error";
7078 return "too many files";
7080 return "file too large";
7082 return "unsupported method";
7084 return "unsupported encryption";
7086 return "unsupported feature";
7088 return "failed finding central directory";
7090 return "not a ZIP archive";
7092 return "invalid header or archive is corrupted";
7094 return "unsupported multidisk archive";
7096 return "decompression failed or archive is corrupted";
7098 return "compression failed";
7100 return "unexpected decompressed size";
7102 return "CRC-32 check failed";
7104 return "unsupported central directory size";
7106 return "allocation failed";
7108 return "file open failed";
7110 return "file create failed";
7112 return "file write failed";
7114 return "file read failed";
7116 return "file close failed";
7118 return "file seek failed";
7120 return "file stat failed";
7122 return "invalid parameter";
7124 return "invalid filename";
7126 return "buffer too small";
7128 return "internal error";
7130 return "file not found";
7132 return "archive is too large";
7134 return "validation failed";
7136 return "write calledback failed";
7137 default:
7138 break;
7139 }
7140
7141 return "unknown error";
7142}
7143
7144/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
7146{
7147 if ((!pZip) || (!pZip->m_pState))
7148 return MZ_FALSE;
7149
7150 return pZip->m_pState->m_zip64;
7151}
7152
7154{
7155 if ((!pZip) || (!pZip->m_pState))
7156 return 0;
7157
7158 return pZip->m_pState->m_central_dir.m_size;
7159}
7160
7162{
7163 return pZip ? pZip->m_total_files : 0;
7164}
7165
7167{
7168 if (!pZip)
7169 return 0;
7170 return pZip->m_archive_size;
7171}
7172
7174{
7175 if ((!pZip) || (!pZip->m_pState))
7176 return 0;
7177 return pZip->m_pState->m_file_archive_start_ofs;
7178}
7179
7181{
7182 if ((!pZip) || (!pZip->m_pState))
7183 return 0;
7184 return pZip->m_pState->m_pFile;
7185}
7186
7187size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7188{
7189 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7191
7192 return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7193}
7194
7195mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
7196{
7197 mz_uint n;
7198 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7199 if (!p)
7200 {
7201 if (filename_buf_size)
7202 pFilename[0] = '\0';
7204 return 0;
7205 }
7207 if (filename_buf_size)
7208 {
7209 n = MZ_MIN(n, filename_buf_size - 1);
7210 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7211 pFilename[n] = '\0';
7212 }
7213 return n + 1;
7214}
7215
7217{
7218 return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7219}
7220
7222{
7223 if (!pZip)
7224 return MZ_FALSE;
7225
7226 if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7227 return mz_zip_reader_end(pZip);
7228#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7230 return mz_zip_writer_end(pZip);
7231#endif
7232
7233 return MZ_FALSE;
7234}
7235
7236#ifdef __cplusplus
7237}
7238#endif
7239
7240#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
7241
QWindow * w
Definition: QtImGui.cpp:152
for(uint32_t i=0;i< queueCount;i++)
if(err !=VK_SUCCESS)
Creates the platform specific surface abstraction of the native platform window used for presentation...
#define MZ_WRITE_LE32(p, v)
Definition: miniz.c:5150
#define MZ_FILE_STAT
Definition: miniz.c:3030
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
Definition: miniz.c:39
static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes, const char *user_extra_data, mz_uint user_extra_data_len)
Definition: miniz.c:5610
mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
Definition: miniz.c:7145
static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
Definition: miniz.c:3226
static const mz_uint8 s_tdefl_len_extra[256]
Definition: miniz.c:652
mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
Definition: miniz.c:3751
mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
Definition: miniz.c:4990
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
Definition: miniz.c:6753
mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
Definition: miniz.c:7025
static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition: miniz.c:3818
mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
Definition: miniz.c:1939
void * miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
Definition: miniz.c:170
static const mz_uint16 s_tdefl_len_sym[256]
Definition: miniz.c:640
mz_bool mz_zip_end(mz_zip_archive *pZip)
Definition: miniz.c:7221
static int tdefl_flush_block(tdefl_compressor *d, int flush)
Definition: miniz.c:1207
static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
Definition: miniz.c:5136
#define TINFL_CR_BEGIN
Definition: miniz.c:2186
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
Definition: miniz.c:7161
void * tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
Definition: miniz.c:2045
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
Definition: miniz.c:5341
#define MZ_WRITE_LE16(p, v)
Definition: miniz.c:5149
void * tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
Definition: miniz.c:1986
static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
Definition: miniz.c:3376
static void tdefl_start_dynamic_block(tdefl_compressor *d)
Definition: miniz.c:944
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
Definition: miniz.c:3831
int mz_deflateReset(mz_streamp pStream)
Definition: miniz.c:224
#define TINFL_GET_BYTE(state_index, c)
Definition: miniz.c:2211
#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size)
Definition: miniz.c:3160
static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
Definition: miniz.c:5191
size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
Definition: miniz.c:7153
static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
Definition: miniz.c:4018
#define MZ_FFLUSH
Definition: miniz.c:3031
int mz_inflateInit(mz_streamp pStream)
Definition: miniz.c:395
int mz_inflate(mz_streamp pStream, int flush)
Definition: miniz.c:400
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
Definition: miniz.c:340
mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
Definition: miniz.c:1934
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
Definition: miniz.c:4693
#define TDEFL_RLE_ZERO_CODE_SIZE()
Definition: miniz.c:916
mz_ulong mz_compressBound(mz_ulong source_len)
Definition: miniz.c:345
static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
Definition: miniz.c:3293
static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
Definition: miniz.c:5131
static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
Definition: miniz.c:3428
mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
Definition: miniz.c:6872
int mz_deflateEnd(mz_streamp pStream)
Definition: miniz.c:291
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
Definition: miniz.c:2001
mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
Definition: miniz.c:7020
#define MZ_FREOPEN(f, m, s)
Definition: miniz.c:3032
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
Definition: miniz.c:741
static const mz_uint8 s_tdefl_small_dist_sym[512]
Definition: miniz.c:660
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
Definition: miniz.c:1896
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
Definition: miniz.c:1150
size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition: miniz.c:7187
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
Definition: miniz.c:2838
mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
Definition: miniz.c:5346
static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition: miniz.c:5325
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
Definition: miniz.c:3986
void * tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
Definition: miniz.c:2791
static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
Definition: miniz.c:1961
static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
Definition: miniz.c:3279
mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
Definition: miniz.c:6877
mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
Definition: miniz.c:4280
unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 :-1]
Definition: miniz.c:30
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
Definition: miniz.c:5692
void * miniz_def_alloc_func(void *opaque, size_t items, size_t size)
Definition: miniz.c:160
#define TINFL_MEMCPY(d, s, l)
Definition: miniz.c:2183
#define TINFL_GET_BITS(state_index, b, n)
Definition: miniz.c:2241
mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
Definition: miniz.c:4215
static const mz_uint8 s_tdefl_small_dist_extra[512]
Definition: miniz.c:676
tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
Definition: miniz.c:1929
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
Definition: miniz.c:5319
#define MZ_FREAD
Definition: miniz.c:3020
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
Definition: miniz.c:3313
static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
Definition: miniz.c:3704
mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
Definition: miniz.c:7043
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
Definition: miniz.c:3755
#define TINFL_HUFF_DECODE(state_index, sym, pHuff)
Definition: miniz.c:2289
mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
Definition: miniz.c:7056
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
Definition: miniz.c:4744
#define MZ_FWRITE
Definition: miniz.c:3021
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
Definition: miniz.c:1890
mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
Definition: miniz.c:4495
mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
Definition: miniz.c:5085
#define MZ_TOLOWER(c)
Definition: miniz.c:3037
static const mz_uint8 s_tdefl_large_dist_extra[128]
Definition: miniz.c:695
static const mz_uint s_tdefl_num_probes[11]
Definition: miniz.c:2014
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
Definition: miniz.c:188
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
Definition: miniz.c:3783
const char * mz_version(void)
Definition: miniz.c:176
static mz_bool tdefl_compress_normal(tdefl_compressor *d)
Definition: miniz.c:1656
int mz_deflateInit(mz_streamp pStream, int level)
Definition: miniz.c:183
static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
Definition: miniz.c:4703
void * mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
Definition: miniz.c:6970
#define MZ_FSEEK64
Definition: miniz.c:3027
static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
Definition: miniz.c:3173
const char * mz_zip_get_error_string(mz_zip_error mz_err)
Definition: miniz.c:7069
static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
Definition: miniz.c:1397
void * mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
Definition: miniz.c:4441
static MZ_FORCEINLINE const mz_uint8 * mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
Definition: miniz.c:3929
void miniz_def_free_func(void *opaque, void *address)
Definition: miniz.c:165
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
Definition: miniz.c:801
static void tdefl_start_static_block(tdefl_compressor *d)
Definition: miniz.c:1031
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
Definition: miniz.c:310
#define MZ_FOPEN(f, m)
Definition: miniz.c:3018
static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
Definition: miniz.c:3474
mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
Definition: miniz.c:6866
static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
Definition: miniz.c:5585
void mz_free(void *p)
Definition: miniz.c:155
mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
Definition: miniz.c:5393
#define TINFL_MEMSET(p, c, l)
Definition: miniz.c:2184
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
Definition: miniz.c:6279
static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition: miniz.c:5153
static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
Definition: miniz.c:3256
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
Definition: miniz.c:4206
static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
Definition: miniz.c:3231
static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
Definition: miniz.c:3241
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
Definition: miniz.c:3936
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
Definition: miniz.c:5286
const char * mz_error(int err)
Definition: miniz.c:554
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
Definition: miniz.c:88
void mz_zip_zero_struct(mz_zip_archive *pZip)
Definition: miniz.c:3698
static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
Definition: miniz.c:3179
static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
Definition: miniz.c:4149
static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
Definition: miniz.c:5532
mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
Definition: miniz.c:7166
tdefl_compressor * tdefl_compressor_alloc()
Definition: miniz.c:2132
MZ_FILE * mz_zip_get_cfile(mz_zip_archive *pZip)
Definition: miniz.c:7180
static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
Definition: miniz.c:5667
int mz_inflateInit2(mz_streamp pStream, int window_bits)
Definition: miniz.c:359
static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
Definition: miniz.c:5519
static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
Definition: miniz.c:5650
static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
Definition: miniz.c:3775
static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
Definition: miniz.c:3347
static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
Definition: miniz.c:3306
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
Definition: miniz.c:6391
mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
Definition: miniz.c:3950
#define TINFL_CR_FINISH
Definition: miniz.c:2209
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
Definition: miniz.c:4431
#define TINFL_CR_RETURN(state_index, result)
Definition: miniz.c:2190
#define TINFL_CR_RETURN_FOREVER(state_index, result)
Definition: miniz.c:2200
mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
Definition: miniz.c:7030
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
Definition: miniz.c:524
#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE
Definition: miniz.c:5531
static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
Definition: miniz.c:1613
void * mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
Definition: miniz.c:7009
static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
Definition: miniz.c:3205
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
Definition: miniz.c:7216
mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
Definition: miniz.c:5414
static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
Definition: miniz.c:4166
mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
Definition: miniz.c:3836
mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
Definition: miniz.c:5981
void tdefl_compressor_free(tdefl_compressor *pComp)
Definition: miniz.c:2137
@ MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS
Definition: miniz.c:3112
@ MZ_ZIP_CDH_FILENAME_LEN_OFS
Definition: miniz.c:3071
@ MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR
Definition: miniz.c:3091
@ MZ_ZIP_LOCAL_DIR_HEADER_SIG
Definition: miniz.c:3045
@ MZ_ZIP_CDH_FILE_DATE_OFS
Definition: miniz.c:3067
@ MZ_ZIP_LDH_CRC32_OFS
Definition: miniz.c:3086
@ MZ_ZIP64_ECDH_SIG_OFS
Definition: miniz.c:3110
@ MZ_ZIP_LDH_BIT_FLAG_OFS
Definition: miniz.c:3082
@ MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS
Definition: miniz.c:3096
@ MZ_ZIP_CDH_VERSION_NEEDED_OFS
Definition: miniz.c:3063
@ MZ_ZIP_DATA_DESCRIPTER_SIZE64
Definition: miniz.c:3057
@ MZ_ZIP_CDH_LOCAL_HEADER_OFS
Definition: miniz.c:3077
@ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG
Definition: miniz.c:3051
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8
Definition: miniz.c:3126
@ MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS
Definition: miniz.c:3115
@ MZ_ZIP_CDH_COMPRESSED_SIZE_OFS
Definition: miniz.c:3069
@ MZ_ZIP_DATA_DESCRIPTER_SIZE32
Definition: miniz.c:3058
@ MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS
Definition: miniz.c:3097
@ MZ_ZIP_CDH_SIG_OFS
Definition: miniz.c:3061
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG
Definition: miniz.c:3123
@ MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS
Definition: miniz.c:3105
@ MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS
Definition: miniz.c:3070
@ MZ_ZIP_ECDH_CDIR_SIZE_OFS
Definition: miniz.c:3099
@ MZ_ZIP64_ECDL_SIG_OFS
Definition: miniz.c:3104
@ MZ_ZIP_CDH_METHOD_OFS
Definition: miniz.c:3065
@ MZ_ZIP_LDH_FILENAME_LEN_OFS
Definition: miniz.c:3089
@ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE
Definition: miniz.c:3054
@ MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG
Definition: miniz.c:3121
@ MZ_ZIP_LDH_FILE_TIME_OFS
Definition: miniz.c:3084
@ MZ_ZIP64_ECDH_VERSION_NEEDED_OFS
Definition: miniz.c:3113
@ MZ_ZIP_CDH_EXTRA_LEN_OFS
Definition: miniz.c:3072
@ MZ_ZIP_LDH_FILE_DATE_OFS
Definition: miniz.c:3085
@ MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS
Definition: miniz.c:3106
@ MZ_ZIP_LDH_METHOD_OFS
Definition: miniz.c:3083
@ MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS
Definition: miniz.c:3116
@ MZ_ZIP_LDH_COMPRESSED_SIZE_OFS
Definition: miniz.c:3087
@ MZ_ZIP_CDH_FILE_TIME_OFS
Definition: miniz.c:3066
@ MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID
Definition: miniz.c:3120
@ MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS
Definition: miniz.c:3098
@ MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID
Definition: miniz.c:3055
@ MZ_ZIP_CENTRAL_DIR_HEADER_SIG
Definition: miniz.c:3044
@ MZ_ZIP_ECDH_SIG_OFS
Definition: miniz.c:3094
@ MZ_ZIP_ECDH_COMMENT_SIZE_OFS
Definition: miniz.c:3101
@ MZ_ZIP64_ECDH_CDIR_SIZE_OFS
Definition: miniz.c:3118
@ MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS
Definition: miniz.c:3107
@ MZ_ZIP_LDH_SIG_OFS
Definition: miniz.c:3080
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION
Definition: miniz.c:3124
@ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG
Definition: miniz.c:3043
@ MZ_ZIP_CDH_CRC32_OFS
Definition: miniz.c:3068
@ MZ_ZIP_CDH_DISK_START_OFS
Definition: miniz.c:3074
@ MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS
Definition: miniz.c:3117
@ MZ_ZIP_CDH_INTERNAL_ATTR_OFS
Definition: miniz.c:3075
@ MZ_ZIP_LDH_VERSION_NEEDED_OFS
Definition: miniz.c:3081
@ MZ_ZIP_ECDH_CDIR_OFS_OFS
Definition: miniz.c:3100
@ MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG
Definition: miniz.c:3052
@ MZ_ZIP_LDH_EXTRA_LEN_OFS
Definition: miniz.c:3090
@ MZ_ZIP_CDH_EXTERNAL_ATTR_OFS
Definition: miniz.c:3076
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED
Definition: miniz.c:3125
@ MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS
Definition: miniz.c:3114
@ MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE
Definition: miniz.c:3048
@ MZ_ZIP_LOCAL_DIR_HEADER_SIZE
Definition: miniz.c:3046
@ MZ_ZIP64_ECDH_CDIR_OFS_OFS
Definition: miniz.c:3119
@ MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS
Definition: miniz.c:3088
@ MZ_ZIP_CDH_BIT_FLAG_OFS
Definition: miniz.c:3064
@ MZ_ZIP_CDH_COMMENT_LEN_OFS
Definition: miniz.c:3073
@ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
Definition: miniz.c:3047
@ MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE
Definition: miniz.c:3053
@ MZ_ZIP_DATA_DESCRIPTOR_ID
Definition: miniz.c:3056
@ MZ_ZIP_CDH_VERSION_MADE_BY_OFS
Definition: miniz.c:3062
@ MZ_ZIP_ECDH_NUM_THIS_DISK_OFS
Definition: miniz.c:3095
@ MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED
Definition: miniz.c:3122
@ MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS
Definition: miniz.c:3111
mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
Definition: miniz.c:7173
unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 :-1]
Definition: miniz.c:31
int mz_inflateEnd(mz_streamp pStream)
Definition: miniz.c:512
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
Definition: miniz.c:5507
static const mz_uint mz_bitmasks[17]
Definition: miniz.c:1053
void * mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
Definition: miniz.c:4483
int mz_deflate(mz_streamp pStream, int flush)
Definition: miniz.c:233
@ TDEFL_MAX_SUPPORTED_HUFF_CODESIZE
Definition: miniz.c:799
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
Definition: miniz.c:4436
#define MZ_FILE_STAT_STRUCT
Definition: miniz.c:3029
static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[]
Definition: miniz.c:942
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
Definition: miniz.c:4423
static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
Definition: miniz.c:5676
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
Definition: miniz.c:2829
static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
Definition: miniz.c:4138
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
Definition: miniz.c:2323
#define MZ_SWAP_UINT32(a, b)
Definition: miniz.c:3366
static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
Definition: miniz.c:825
static const mz_uint8 s_tdefl_large_dist_sym[128]
Definition: miniz.c:688
#define TDEFL_PROBE
#define MZ_FCLOSE
Definition: miniz.c:3019
mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
Definition: miniz.c:5043
mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
Definition: miniz.c:4784
void * tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
Definition: miniz.c:2123
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
Definition: miniz.c:303
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
Definition: miniz.c:2017
static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
Definition: miniz.c:1198
static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition: miniz.c:4776
static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
Definition: miniz.c:1626
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index)
Definition: miniz.c:3170
static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
Definition: miniz.c:6311
mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
Definition: miniz.c:4753
mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
Definition: miniz.c:3887
tinfl_decompressor * tinfl_decompressor_alloc()
Definition: miniz.c:2867
static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
Definition: miniz.c:5567
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
Definition: miniz.c:6841
unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 :-1]
Definition: miniz.c:29
static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
Definition: miniz.c:5143
mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
Definition: miniz.c:4766
#define MZ_WRITE_LE64(p, v)
Definition: miniz.c:5151
mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
Definition: miniz.c:5237
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
Definition: miniz.c:1822
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
Definition: miniz.c:5501
static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
Definition: miniz.c:3185
mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
Definition: miniz.c:7051
#define TINFL_SKIP_BITS(state_index, n)
Definition: miniz.c:2230
mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
Definition: miniz.c:5698
static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
Definition: miniz.c:3215
#define TDEFL_RLE_PREV_CODE_SIZE()
Definition: miniz.c:896
mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
Definition: miniz.c:5291
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
Definition: miniz.c:4710
#define MZ_FTELL64
Definition: miniz.c:3026
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
Definition: miniz.c:7195
static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
Definition: miniz.c:1801
void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
Definition: miniz.c:2875
#define TDEFL_PUT_BITS(b, l)
Definition: miniz.c:878
#define MZ_DELETE_FILE
Definition: miniz.c:3033
static tdefl_sym_freq * tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
Definition: miniz.c:707
unsigned long mz_ulong
Definition: miniz.h:186
#define MZ_MALLOC(x)
Definition: miniz.h:512
@ MZ_ZIP_FLAG_ASCII_FILENAME
Definition: miniz.h:986
@ MZ_ZIP_FLAG_WRITE_ZIP64
Definition: miniz.h:984
@ MZ_ZIP_FLAG_WRITE_ALLOW_READING
Definition: miniz.h:985
@ MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY
Definition: miniz.h:983
@ MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG
Definition: miniz.h:982
@ MZ_ZIP_FLAG_COMPRESSED_DATA
Definition: miniz.h:980
@ MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY
Definition: miniz.h:981
@ MZ_ZIP_FLAG_CASE_SENSITIVE
Definition: miniz.h:978
@ MZ_ZIP_FLAG_IGNORE_PATH
Definition: miniz.h:979
#define MZ_READ_LE16(p)
Definition: miniz.h:525
#define MZ_REALLOC(p, x)
Definition: miniz.h:514
size_t(* mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
Definition: miniz.h:962
#define MZ_FALSE
Definition: miniz.h:478
#define MZ_FORCEINLINE
Definition: miniz.h:536
#define MZ_ASSERT(x)
Definition: miniz.h:505
#define tinfl_init(r)
Definition: miniz.h:832
tinfl_status
Definition: miniz.h:798
@ TINFL_STATUS_ADLER32_MISMATCH
Definition: miniz.h:808
@ TINFL_STATUS_FAILED
Definition: miniz.h:811
@ TINFL_STATUS_NEEDS_MORE_INPUT
Definition: miniz.h:822
@ TINFL_STATUS_HAS_MORE_OUTPUT
Definition: miniz.h:828
@ TINFL_STATUS_BAD_PARAM
Definition: miniz.h:805
@ TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS
Definition: miniz.h:802
@ TINFL_STATUS_DONE
Definition: miniz.h:817
#define TINFL_LZ_DICT_SIZE
Definition: miniz.h:794
@ TDEFL_FORCE_ALL_RAW_BLOCKS
Definition: miniz.h:591
@ TDEFL_GREEDY_PARSING_FLAG
Definition: miniz.h:586
@ TDEFL_FORCE_ALL_STATIC_BLOCKS
Definition: miniz.h:590
@ TDEFL_COMPUTE_ADLER32
Definition: miniz.h:585
@ TDEFL_FILTER_MATCHES
Definition: miniz.h:589
@ TDEFL_WRITE_ZLIB_HEADER
Definition: miniz.h:584
@ TDEFL_NONDETERMINISTIC_PARSING_FLAG
Definition: miniz.h:587
@ TDEFL_RLE_MATCHES
Definition: miniz.h:588
#define MZ_CLEAR_OBJ(obj)
Definition: miniz.h:519
#define MZ_DEFLATED
Definition: miniz.h:210
unsigned int mz_uint
Definition: miniz.h:473
int64_t mz_int64
Definition: miniz.h:474
#define MZ_ADLER32_INIT
Definition: miniz.h:191
#define MZ_CRC32_INIT
Definition: miniz.h:195
int(* tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser)
Definition: miniz.h:780
#define MZ_UINT16_MAX
Definition: miniz.h:547
#define tinfl_get_adler32(r)
Definition: miniz.h:838
signed short mz_int16
Definition: miniz.h:470
#define MZ_DEFAULT_WINDOW_BITS
Definition: miniz.h:265
#define MZ_VERSION
Definition: miniz.h:229
@ MZ_UBER_COMPRESSION
Definition: miniz.h:224
@ MZ_DEFAULT_LEVEL
Definition: miniz.h:225
@ MZ_DEFAULT_COMPRESSION
Definition: miniz.h:226
#define MZ_FILE
Definition: miniz.h:492
@ TINFL_FAST_LOOKUP_SIZE
Definition: miniz.h:852
@ TINFL_FAST_LOOKUP_BITS
Definition: miniz.h:851
@ MZ_FILTERED
Definition: miniz.h:203
@ MZ_FIXED
Definition: miniz.h:206
@ MZ_DEFAULT_STRATEGY
Definition: miniz.h:202
@ MZ_RLE
Definition: miniz.h:205
@ MZ_HUFFMAN_ONLY
Definition: miniz.h:204
#define MZ_TIME_T
Definition: miniz.h:502
int mz_bool
Definition: miniz.h:476
unsigned char mz_uint8
Definition: miniz.h:469
@ TDEFL_MAX_HUFF_SYMBOLS
Definition: miniz.h:657
@ TDEFL_LEVEL1_HASH_SIZE_MASK
Definition: miniz.h:659
@ TDEFL_LZ_HASH_BITS
Definition: miniz.h:658
@ TDEFL_LZ_HASH_SIZE
Definition: miniz.h:661
@ TDEFL_LZ_CODE_BUF_SIZE
Definition: miniz.h:655
@ TDEFL_LZ_HASH_SHIFT
Definition: miniz.h:660
@ TDEFL_OUT_BUF_SIZE
Definition: miniz.h:656
tdefl_flush
Definition: miniz.h:676
@ TDEFL_NO_FLUSH
Definition: miniz.h:677
@ TDEFL_FULL_FLUSH
Definition: miniz.h:679
@ TDEFL_FINISH
Definition: miniz.h:680
mz_zip_type
Definition: miniz.h:990
@ MZ_ZIP_TYPE_USER
Definition: miniz.h:992
@ MZ_ZIP_TYPE_FILE
Definition: miniz.h:995
@ MZ_ZIP_TYPE_HEAP
Definition: miniz.h:994
@ MZ_ZIP_TYPE_MEMORY
Definition: miniz.h:993
@ MZ_ZIP_TYPE_CFILE
Definition: miniz.h:996
@ MZ_ZIP_TYPE_INVALID
Definition: miniz.h:991
#define crc32
Definition: miniz.h:442
@ MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE
Definition: miniz.h:902
@ MZ_ZIP_MAX_IO_BUF_SIZE
Definition: miniz.h:900
@ MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE
Definition: miniz.h:901
@ TDEFL_MAX_PROBES_MASK
Definition: miniz.h:570
@ TDEFL_MAX_MATCH_LEN
Definition: miniz.h:637
@ TDEFL_MAX_HUFF_SYMBOLS_0
Definition: miniz.h:631
@ TDEFL_LZ_DICT_SIZE_MASK
Definition: miniz.h:635
@ TDEFL_LZ_DICT_SIZE
Definition: miniz.h:634
@ TDEFL_MIN_MATCH_LEN
Definition: miniz.h:636
@ TDEFL_MAX_HUFF_SYMBOLS_1
Definition: miniz.h:632
@ TDEFL_MAX_HUFF_SYMBOLS_2
Definition: miniz.h:633
unsigned int mz_uint32
Definition: miniz.h:472
unsigned short mz_uint16
Definition: miniz.h:471
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
Definition: miniz.h:775
#define MZ_MIN(a, b)
Definition: miniz.h:518
tdefl_status
Definition: miniz.h:667
@ TDEFL_STATUS_OKAY
Definition: miniz.h:670
@ TDEFL_STATUS_DONE
Definition: miniz.h:671
@ TDEFL_STATUS_BAD_PARAM
Definition: miniz.h:668
@ TDEFL_STATUS_PUT_BUF_FAILED
Definition: miniz.h:669
#define MZ_FREE(x)
Definition: miniz.h:513
uint64_t mz_uint64
Definition: miniz.h:475
#define MZ_READ_LE32(p)
Definition: miniz.h:526
mz_zip_mode
Definition: miniz.h:969
@ MZ_ZIP_MODE_WRITING
Definition: miniz.h:972
@ MZ_ZIP_MODE_READING
Definition: miniz.h:971
@ MZ_ZIP_MODE_INVALID
Definition: miniz.h:970
@ MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED
Definition: miniz.h:973
mz_bool(* tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser)
Definition: miniz.h:623
@ MZ_MEM_ERROR
Definition: miniz.h:258
@ MZ_PARAM_ERROR
Definition: miniz.h:261
@ MZ_NEED_DICT
Definition: miniz.h:254
@ MZ_VERSION_ERROR
Definition: miniz.h:260
@ MZ_STREAM_END
Definition: miniz.h:253
@ MZ_ERRNO
Definition: miniz.h:255
@ MZ_OK
Definition: miniz.h:252
@ MZ_BUF_ERROR
Definition: miniz.h:259
@ MZ_STREAM_ERROR
Definition: miniz.h:256
@ MZ_DATA_ERROR
Definition: miniz.h:257
mz_zip_error
Definition: miniz.h:1002
@ MZ_ZIP_UNSUPPORTED_METHOD
Definition: miniz.h:1007
@ MZ_ZIP_UNSUPPORTED_FEATURE
Definition: miniz.h:1009
@ MZ_ZIP_FILE_OPEN_FAILED
Definition: miniz.h:1020
@ MZ_ZIP_FILE_TOO_LARGE
Definition: miniz.h:1006
@ MZ_ZIP_WRITE_CALLBACK_FAILED
Definition: miniz.h:1034
@ MZ_ZIP_CRC_CHECK_FAILED
Definition: miniz.h:1017
@ MZ_ZIP_INTERNAL_ERROR
Definition: miniz.h:1030
@ MZ_ZIP_FILE_CLOSE_FAILED
Definition: miniz.h:1024
@ MZ_ZIP_FILE_CREATE_FAILED
Definition: miniz.h:1021
@ MZ_ZIP_BUF_TOO_SMALL
Definition: miniz.h:1029
@ MZ_ZIP_VALIDATION_FAILED
Definition: miniz.h:1033
@ MZ_ZIP_FILE_STAT_FAILED
Definition: miniz.h:1026
@ MZ_ZIP_INVALID_FILENAME
Definition: miniz.h:1028
@ MZ_ZIP_COMPRESSION_FAILED
Definition: miniz.h:1015
@ MZ_ZIP_NO_ERROR
Definition: miniz.h:1003
@ MZ_ZIP_UNSUPPORTED_ENCRYPTION
Definition: miniz.h:1008
@ MZ_ZIP_TOO_MANY_FILES
Definition: miniz.h:1005
@ MZ_ZIP_UNDEFINED_ERROR
Definition: miniz.h:1004
@ MZ_ZIP_UNSUPPORTED_MULTIDISK
Definition: miniz.h:1013
@ MZ_ZIP_ALLOC_FAILED
Definition: miniz.h:1019
@ MZ_ZIP_ARCHIVE_TOO_LARGE
Definition: miniz.h:1032
@ MZ_ZIP_DECOMPRESSION_FAILED
Definition: miniz.h:1014
@ MZ_ZIP_FILE_WRITE_FAILED
Definition: miniz.h:1022
@ MZ_ZIP_INVALID_PARAMETER
Definition: miniz.h:1027
@ MZ_ZIP_INVALID_HEADER_OR_CORRUPTED
Definition: miniz.h:1012
@ MZ_ZIP_UNSUPPORTED_CDIR_SIZE
Definition: miniz.h:1018
@ MZ_ZIP_FILE_READ_FAILED
Definition: miniz.h:1023
@ MZ_ZIP_FILE_NOT_FOUND
Definition: miniz.h:1031
@ MZ_ZIP_FAILED_FINDING_CENTRAL_DIR
Definition: miniz.h:1010
@ MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE
Definition: miniz.h:1016
@ MZ_ZIP_NOT_AN_ARCHIVE
Definition: miniz.h:1011
@ MZ_ZIP_FILE_SEEK_FAILED
Definition: miniz.h:1025
#define MZ_READ_LE64(p)
Definition: miniz.h:529
@ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
Definition: miniz.h:759
@ TINFL_FLAG_HAS_MORE_INPUT
Definition: miniz.h:758
@ TINFL_FLAG_COMPUTE_ADLER32
Definition: miniz.h:760
@ TINFL_FLAG_PARSE_ZLIB_HEADER
Definition: miniz.h:757
#define MZ_MAX(a, b)
Definition: miniz.h:517
#define MZ_TRUE
Definition: miniz.h:479
mz_uint32 tinfl_bit_buf_t
Definition: miniz.h:869
@ MZ_SYNC_FLUSH
Definition: miniz.h:243
@ MZ_FINISH
Definition: miniz.h:245
@ MZ_PARTIAL_FLUSH
Definition: miniz.h:242
#define MZ_UINT32_MAX
Definition: miniz.h:548
int m_window_bits
Definition: miniz.c:354
mz_uint m_dict_ofs
Definition: miniz.c:353
mz_uint m_has_flushed
Definition: miniz.c:353
mz_uint m_dict_avail
Definition: miniz.c:353
mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]
Definition: miniz.c:355
mz_uint m_first_call
Definition: miniz.c:353
tinfl_status m_last_status
Definition: miniz.c:356
tinfl_decompressor m_decomp
Definition: miniz.c:352
mz_ulong adler
Definition: miniz.h:288
unsigned char * next_out
Definition: miniz.h:276
void * opaque
Definition: miniz.h:285
int data_type
Definition: miniz.h:287
mz_free_func zfree
Definition: miniz.h:284
mz_ulong total_out
Definition: miniz.h:278
unsigned int avail_out
Definition: miniz.h:277
struct mz_internal_state * state
Definition: miniz.h:281
const unsigned char * next_in
Definition: miniz.h:272
unsigned int avail_in
Definition: miniz.h:273
mz_alloc_func zalloc
Definition: miniz.h:283
mz_ulong total_in
Definition: miniz.h:274
char * msg
Definition: miniz.h:280
mz_ulong reserved
Definition: miniz.h:289
mz_bool m_is_directory
Definition: miniz.h:943
mz_uint32 m_external_attr
Definition: miniz.h:934
mz_uint16 m_version_needed
Definition: miniz.h:915
mz_uint16 m_version_made_by
Definition: miniz.h:914
mz_bool m_is_supported
Definition: miniz.h:949
mz_uint64 m_central_dir_ofs
Definition: miniz.h:911
mz_bool m_is_encrypted
Definition: miniz.h:946
mz_uint32 m_file_index
Definition: miniz.h:908
mz_uint64 m_uncomp_size
Definition: miniz.h:930
mz_uint32 m_comment_size
Definition: miniz.h:940
mz_uint16 m_bit_flag
Definition: miniz.h:916
mz_uint64 m_local_header_ofs
Definition: miniz.h:937
mz_uint16 m_internal_attr
Definition: miniz.h:933
mz_uint16 m_method
Definition: miniz.h:917
mz_uint64 m_comp_size
Definition: miniz.h:927
char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]
Definition: miniz.h:953
char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]
Definition: miniz.h:957
mz_uint64 m_central_directory_file_ofs
Definition: miniz.h:1041
mz_zip_error m_last_error
Definition: miniz.h:1047
mz_alloc_func m_pAlloc
Definition: miniz.h:1051
mz_zip_mode m_zip_mode
Definition: miniz.h:1045
mz_uint64 m_archive_size
Definition: miniz.h:1040
void * m_pIO_opaque
Definition: miniz.h:1059
void * m_pAlloc_opaque
Definition: miniz.h:1054
mz_file_needs_keepalive m_pNeeds_keepalive
Definition: miniz.h:1058
mz_file_write_func m_pWrite
Definition: miniz.h:1057
mz_zip_internal_state * m_pState
Definition: miniz.h:1061
mz_free_func m_pFree
Definition: miniz.h:1052
mz_realloc_func m_pRealloc
Definition: miniz.h:1053
mz_file_read_func m_pRead
Definition: miniz.h:1056
mz_uint64 m_file_offset_alignment
Definition: miniz.h:1049
mz_zip_type m_zip_type
Definition: miniz.h:1046
mz_uint32 m_total_files
Definition: miniz.h:1044
size_t m_size
Definition: miniz.c:3132
void * m_p
Definition: miniz.c:3131
size_t m_capacity
Definition: miniz.c:3132
mz_uint m_element_size
Definition: miniz.c:3133
mz_bool m_zip64_has_extended_info_fields
Definition: miniz.c:3149
mz_zip_array m_sorted_central_dir_offsets
Definition: miniz.c:3140
mz_uint64 m_file_archive_start_ofs
Definition: miniz.c:3153
mz_zip_array m_central_dir_offsets
Definition: miniz.c:3139
mz_zip_array m_central_dir
Definition: miniz.c:3138
mz_uint64 m_cur_archive_file_ofs
Definition: miniz.c:5515
mz_uint64 m_comp_size
Definition: miniz.c:5516
mz_zip_archive * m_pZip
Definition: miniz.c:5514
mz_uint m_max_probes[2]
Definition: miniz.h:688
mz_uint m_block_index
Definition: miniz.h:693
mz_uint m_saved_lit
Definition: miniz.h:693
mz_uint m_saved_match_dist
Definition: miniz.h:693
size_t * m_pOut_buf_size
Definition: miniz.h:697
mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]
Definition: miniz.h:707
const mz_uint8 * m_pSrc
Definition: miniz.h:699
mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]
Definition: miniz.h:703
mz_uint m_output_flush_remaining
Definition: miniz.h:693
mz_uint m_num_flags_left
Definition: miniz.h:692
mz_uint m_lookahead_pos
Definition: miniz.h:690
mz_uint m_wants_to_finish
Definition: miniz.h:693
mz_uint m_finished
Definition: miniz.h:693
mz_uint m_total_lz_bytes
Definition: miniz.h:692
size_t m_src_buf_left
Definition: miniz.h:700
tdefl_status m_prev_return_status
Definition: miniz.h:694
mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE+TDEFL_MAX_MATCH_LEN - 1]
Definition: miniz.h:701
tdefl_put_buf_func_ptr m_pPut_buf_func
Definition: miniz.h:686
tdefl_flush m_flush
Definition: miniz.h:698
mz_uint m_output_flush_ofs
Definition: miniz.h:693
size_t m_out_buf_ofs
Definition: miniz.h:700
mz_uint m_bit_buffer
Definition: miniz.h:692
mz_uint m_bits_in
Definition: miniz.h:692
mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]
Definition: miniz.h:706
mz_uint8 * m_pOutput_buf_end
Definition: miniz.h:691
mz_uint m_lookahead_size
Definition: miniz.h:690
mz_uint8 * m_pLZ_flags
Definition: miniz.h:691
mz_uint m_saved_match_len
Definition: miniz.h:693
mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]
Definition: miniz.h:702
void * m_pOut_buf
Definition: miniz.h:696
mz_uint m_lz_code_buf_dict_pos
Definition: miniz.h:692
const void * m_pIn_buf
Definition: miniz.h:695
mz_uint m_flags
Definition: miniz.h:688
mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]
Definition: miniz.h:705
int m_greedy_parsing
Definition: miniz.h:689
void * m_pPut_buf_user
Definition: miniz.h:687
mz_uint8 * m_pLZ_code_buf
Definition: miniz.h:691
mz_uint m_dict_size
Definition: miniz.h:690
mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]
Definition: miniz.h:704
size_t * m_pIn_buf_size
Definition: miniz.h:697
mz_uint m_adler32
Definition: miniz.h:690
mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]
Definition: miniz.h:708
mz_uint8 * m_pOutput_buf
Definition: miniz.h:691
mz_bool m_expandable
Definition: miniz.c:1958
mz_uint8 * m_pBuf
Definition: miniz.c:1957
size_t m_capacity
Definition: miniz.c:1956
mz_uint16 m_sym_index
Definition: miniz.c:705
mz_uint16 m_key
Definition: miniz.c:705
mz_uint32 m_type
Definition: miniz.h:875
mz_uint32 m_final
Definition: miniz.h:875
mz_uint32 m_zhdr0
Definition: miniz.h:875
tinfl_bit_buf_t m_bit_buf
Definition: miniz.h:876
mz_uint32 m_counter
Definition: miniz.h:875
size_t m_dist_from_out_buf_start
Definition: miniz.h:877
mz_uint32 m_check_adler32
Definition: miniz.h:875
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]
Definition: miniz.h:878
mz_uint8 m_raw_header[4]
Definition: miniz.h:879
mz_uint32 m_zhdr1
Definition: miniz.h:875
mz_uint32 m_num_bits
Definition: miniz.h:875
mz_uint32 m_z_adler32
Definition: miniz.h:875
mz_uint32 m_table_sizes[TINFL_MAX_HUFF_TABLES]
Definition: miniz.h:875
mz_uint32 m_dist
Definition: miniz.h:875
mz_uint8 m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0+TINFL_MAX_HUFF_SYMBOLS_1+137]
Definition: miniz.h:879
mz_uint32 m_num_extra
Definition: miniz.h:875
mz_int16 m_tree[TINFL_MAX_HUFF_SYMBOLS_0 *2]
Definition: miniz.h:858
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]
Definition: miniz.h:857
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE]
Definition: miniz.h:858