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