29 typedef unsigned char mz_validate_uint16[
sizeof(mz_uint16) == 2 ? 1 : -1];
30 typedef unsigned char mz_validate_uint32[
sizeof(mz_uint32) == 4 ? 1 : -1];
31 typedef unsigned char mz_validate_uint64[
sizeof(mz_uint64) == 8 ? 1 : -1];
39 mz_ulong mz_adler32(mz_ulong adler,
const unsigned char *ptr,
size_t buf_len)
41 mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
42 size_t block_len = buf_len % 5552;
44 return MZ_ADLER32_INIT;
47 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
49 s1 += ptr[0], s2 += s1;
50 s1 += ptr[1], s2 += s1;
51 s1 += ptr[2], s2 += s1;
52 s1 += ptr[3], s2 += s1;
53 s1 += ptr[4], s2 += s1;
54 s1 += ptr[5], s2 += s1;
55 s1 += ptr[6], s2 += s1;
56 s1 += ptr[7], s2 += s1;
58 for (; i < block_len; ++i)
59 s1 += *ptr++, s2 += s1;
60 s1 %= 65521U, s2 %= 65521U;
64 return (s2 << 16) + s1;
69 mz_ulong mz_crc32(mz_ulong crc,
const mz_uint8 *ptr,
size_t buf_len)
71 static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
72 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
73 mz_uint32 crcu32 = (mz_uint32)crc;
80 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
81 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
88 mz_ulong mz_crc32(mz_ulong crc,
const mz_uint8 *ptr,
size_t buf_len)
90 static const mz_uint32 s_crc_table[256] =
92 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
93 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
94 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
95 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
96 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
97 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
98 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
99 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
100 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
101 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
102 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
103 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
104 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
105 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
106 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
107 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
108 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
109 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
110 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
111 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
112 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
113 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
114 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
115 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
116 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
117 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
118 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
119 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
120 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
121 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
122 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
123 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
124 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
125 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
126 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
127 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
128 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
131 mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
132 const mz_uint8 *pByte_buf = (
const mz_uint8 *)ptr;
136 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
137 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
138 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
139 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
146 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
155 void mz_free(
void *p)
160 void *miniz_def_alloc_func(
void *opaque,
size_t items,
size_t size)
162 (void)opaque, (
void)items, (void)size;
163 return MZ_MALLOC(items * size);
165 void miniz_def_free_func(
void *opaque,
void *address)
167 (void)opaque, (
void)address;
170 void *miniz_def_realloc_func(
void *opaque,
void *address,
size_t items,
size_t size)
172 (void)opaque, (
void)address, (void)items, (
void)size;
173 return MZ_REALLOC(address, items * size);
176 const
char *mz_version(
void)
181 #ifndef MINIZ_NO_ZLIB_APIS
183 int mz_deflateInit(
mz_streamp pStream,
int level)
185 return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
188 int mz_deflateInit2(
mz_streamp pStream,
int level,
int method,
int window_bits,
int mem_level,
int strategy)
191 mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
194 return MZ_STREAM_ERROR;
195 if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
196 return MZ_PARAM_ERROR;
198 pStream->data_type = 0;
199 pStream->adler = MZ_ADLER32_INIT;
201 pStream->reserved = 0;
202 pStream->total_in = 0;
203 pStream->total_out = 0;
204 if (!pStream->zalloc)
205 pStream->zalloc = miniz_def_alloc_func;
207 pStream->zfree = miniz_def_free_func;
213 pStream->state = (
struct mz_internal_state *)pComp;
215 if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
217 mz_deflateEnd(pStream);
218 return MZ_PARAM_ERROR;
226 if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
227 return MZ_STREAM_ERROR;
228 pStream->total_in = pStream->total_out = 0;
235 size_t in_bytes, out_bytes;
236 mz_ulong orig_total_in, orig_total_out;
237 int mz_status = MZ_OK;
239 if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
240 return MZ_STREAM_ERROR;
241 if (!pStream->avail_out)
244 if (flush == MZ_PARTIAL_FLUSH)
245 flush = MZ_SYNC_FLUSH;
247 if (((
tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
248 return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
250 orig_total_in = pStream->total_in;
251 orig_total_out = pStream->total_out;
254 tdefl_status defl_status;
255 in_bytes = pStream->avail_in;
256 out_bytes = pStream->avail_out;
258 defl_status = tdefl_compress((
tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
259 pStream->next_in += (mz_uint)in_bytes;
260 pStream->avail_in -= (mz_uint)in_bytes;
261 pStream->total_in += (mz_uint)in_bytes;
264 pStream->next_out += (mz_uint)out_bytes;
265 pStream->avail_out -= (mz_uint)out_bytes;
266 pStream->total_out += (mz_uint)out_bytes;
270 mz_status = MZ_STREAM_ERROR;
273 else if (defl_status == TDEFL_STATUS_DONE)
275 mz_status = MZ_STREAM_END;
278 else if (!pStream->avail_out)
280 else if ((!pStream->avail_in) && (flush != MZ_FINISH))
282 if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
294 return MZ_STREAM_ERROR;
297 pStream->zfree(pStream->opaque, pStream->state);
298 pStream->state = NULL;
303 mz_ulong mz_deflateBound(
mz_streamp pStream, mz_ulong source_len)
307 return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
310 int mz_compress2(
unsigned char *pDest, mz_ulong *pDest_len,
const unsigned char *pSource, mz_ulong source_len,
int level)
314 memset(&stream, 0,
sizeof(stream));
317 if ((source_len | *pDest_len) > 0xFFFFFFFFU)
318 return MZ_PARAM_ERROR;
320 stream.next_in = pSource;
321 stream.avail_in = (mz_uint32)source_len;
322 stream.next_out = pDest;
323 stream.avail_out = (mz_uint32)*pDest_len;
325 status = mz_deflateInit(&stream, level);
329 status = mz_deflate(&stream, MZ_FINISH);
330 if (status != MZ_STREAM_END)
332 mz_deflateEnd(&stream);
333 return (status == MZ_OK) ? MZ_BUF_ERROR : status;
336 *pDest_len = stream.total_out;
337 return mz_deflateEnd(&stream);
340 int mz_compress(
unsigned char *pDest, mz_ulong *pDest_len,
const unsigned char *pSource, mz_ulong source_len)
342 return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
345 mz_ulong mz_compressBound(mz_ulong source_len)
347 return mz_deflateBound(NULL, source_len);
353 mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
355 mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
356 tinfl_status m_last_status;
359 int mz_inflateInit2(
mz_streamp pStream,
int window_bits)
363 return MZ_STREAM_ERROR;
364 if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
365 return MZ_PARAM_ERROR;
367 pStream->data_type = 0;
370 pStream->total_in = 0;
371 pStream->total_out = 0;
372 pStream->reserved = 0;
373 if (!pStream->zalloc)
374 pStream->zalloc = miniz_def_alloc_func;
376 pStream->zfree = miniz_def_free_func;
382 pStream->state = (
struct mz_internal_state *)pDecomp;
384 tinfl_init(&pDecomp->m_decomp);
385 pDecomp->m_dict_ofs = 0;
386 pDecomp->m_dict_avail = 0;
387 pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
388 pDecomp->m_first_call = 1;
389 pDecomp->m_has_flushed = 0;
390 pDecomp->m_window_bits = window_bits;
397 return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
404 return MZ_STREAM_ERROR;
406 pStream->data_type = 0;
409 pStream->total_in = 0;
410 pStream->total_out = 0;
411 pStream->reserved = 0;
415 tinfl_init(&pDecomp->m_decomp);
416 pDecomp->m_dict_ofs = 0;
417 pDecomp->m_dict_avail = 0;
418 pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
419 pDecomp->m_first_call = 1;
420 pDecomp->m_has_flushed = 0;
429 mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
430 size_t in_bytes, out_bytes, orig_avail_in;
433 if ((!pStream) || (!pStream->state))
434 return MZ_STREAM_ERROR;
435 if (flush == MZ_PARTIAL_FLUSH)
436 flush = MZ_SYNC_FLUSH;
437 if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
438 return MZ_STREAM_ERROR;
441 if (pState->m_window_bits > 0)
442 decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
443 orig_avail_in = pStream->avail_in;
445 first_call = pState->m_first_call;
446 pState->m_first_call = 0;
447 if (pState->m_last_status < 0)
448 return MZ_DATA_ERROR;
450 if (pState->m_has_flushed && (flush != MZ_FINISH))
451 return MZ_STREAM_ERROR;
452 pState->m_has_flushed |= (flush == MZ_FINISH);
454 if ((flush == MZ_FINISH) && (first_call))
457 decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
458 in_bytes = pStream->avail_in;
459 out_bytes = pStream->avail_out;
460 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
461 pState->m_last_status = status;
462 pStream->next_in += (mz_uint)in_bytes;
463 pStream->avail_in -= (mz_uint)in_bytes;
464 pStream->total_in += (mz_uint)in_bytes;
465 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
466 pStream->next_out += (mz_uint)out_bytes;
467 pStream->avail_out -= (mz_uint)out_bytes;
468 pStream->total_out += (mz_uint)out_bytes;
471 return MZ_DATA_ERROR;
472 else if (status != TINFL_STATUS_DONE)
474 pState->m_last_status = TINFL_STATUS_FAILED;
477 return MZ_STREAM_END;
480 if (flush != MZ_FINISH)
481 decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
483 if (pState->m_dict_avail)
485 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
486 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
487 pStream->next_out += n;
488 pStream->avail_out -= n;
489 pStream->total_out += n;
490 pState->m_dict_avail -= n;
491 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
492 return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
497 in_bytes = pStream->avail_in;
498 out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
500 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);
501 pState->m_last_status = status;
503 pStream->next_in += (mz_uint)in_bytes;
504 pStream->avail_in -= (mz_uint)in_bytes;
505 pStream->total_in += (mz_uint)in_bytes;
506 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
508 pState->m_dict_avail = (mz_uint)out_bytes;
510 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
511 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
512 pStream->next_out += n;
513 pStream->avail_out -= n;
514 pStream->total_out += n;
515 pState->m_dict_avail -= n;
516 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
519 return MZ_DATA_ERROR;
520 else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
522 else if (flush == MZ_FINISH)
525 if (status == TINFL_STATUS_DONE)
526 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
528 else if (!pStream->avail_out)
531 else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
535 return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
541 return MZ_STREAM_ERROR;
544 pStream->zfree(pStream->opaque, pStream->state);
545 pStream->state = NULL;
550 int mz_uncompress(
unsigned char *pDest, mz_ulong *pDest_len,
const unsigned char *pSource, mz_ulong source_len)
554 memset(&stream, 0,
sizeof(stream));
557 if ((source_len | *pDest_len) > 0xFFFFFFFFU)
558 return MZ_PARAM_ERROR;
560 stream.next_in = pSource;
561 stream.avail_in = (mz_uint32)source_len;
562 stream.next_out = pDest;
563 stream.avail_out = (mz_uint32)*pDest_len;
565 status = mz_inflateInit(&stream);
569 status = mz_inflate(&stream, MZ_FINISH);
570 if (status != MZ_STREAM_END)
572 mz_inflateEnd(&stream);
573 return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
575 *pDest_len = stream.total_out;
577 return mz_inflateEnd(&stream);
580 const char *mz_error(
int err)
588 { MZ_OK,
"" }, { MZ_STREAM_END,
"stream end" }, { MZ_NEED_DICT,
"need dictionary" }, { MZ_ERRNO,
"file error" }, { MZ_STREAM_ERROR,
"stream error" }, { 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" }
591 for (i = 0; i <
sizeof(s_error_descs) /
sizeof(s_error_descs[0]); ++i)
592 if (s_error_descs[i].m_err == err)
593 return s_error_descs[i].m_pDesc;
665 static const mz_uint16 s_tdefl_len_sym[256] =
667 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,
668 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,
669 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,
670 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,
671 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,
672 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,
673 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,
674 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
677 static const mz_uint8 s_tdefl_len_extra[256] =
679 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,
680 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,
681 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,
682 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
685 static const mz_uint8 s_tdefl_small_dist_sym[512] =
687 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,
688 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,
689 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,
690 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,
691 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,
692 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,
693 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,
694 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,
695 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,
696 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,
697 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,
698 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
701 static const mz_uint8 s_tdefl_small_dist_extra[512] =
703 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,
704 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,
705 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,
706 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,
707 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
708 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
709 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
710 7, 7, 7, 7, 7, 7, 7, 7
713 static const mz_uint8 s_tdefl_large_dist_sym[128] =
715 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,
716 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,
717 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
720 static const mz_uint8 s_tdefl_large_dist_extra[128] =
722 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,
723 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,
724 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
730 mz_uint16 m_key, m_sym_index;
734 mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
737 for (i = 0; i < num_syms; i++)
739 mz_uint freq = pSyms0[i].m_key;
741 hist[256 + ((freq >> 8) & 0xFF)]++;
743 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
745 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
747 const mz_uint32 *pHist = &hist[pass << 8];
748 mz_uint offsets[256], cur_ofs = 0;
749 for (i = 0; i < 256; i++)
751 offsets[i] = cur_ofs;
754 for (i = 0; i < num_syms; i++)
755 pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
758 pCur_syms = pNew_syms;
766 static void tdefl_calculate_minimum_redundancy(
tdefl_sym_freq *A,
int n)
768 int root, leaf, next, avbl, used, dpth;
776 A[0].m_key += A[1].m_key;
779 for (next = 1; next < n - 1; next++)
781 if (leaf >= n || A[root].m_key < A[leaf].m_key)
783 A[next].m_key = A[root].m_key;
784 A[root++].m_key = (mz_uint16)next;
787 A[next].m_key = A[leaf++].m_key;
788 if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
790 A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
791 A[root++].m_key = (mz_uint16)next;
794 A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
797 for (next = n - 3; next >= 0; next--)
798 A[next].m_key = A[A[next].m_key].m_key + 1;
805 while (root >= 0 && (
int)A[root].m_key == dpth)
812 A[next--].m_key = (mz_uint16)(dpth);
824 TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32
826 static void tdefl_huffman_enforce_max_code_size(
int *pNum_codes,
int code_list_len,
int max_code_size)
830 if (code_list_len <= 1)
832 for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
833 pNum_codes[max_code_size] += pNum_codes[i];
834 for (i = max_code_size; i > 0; i--)
835 total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
836 while (total != (1UL << max_code_size))
838 pNum_codes[max_code_size]--;
839 for (i = max_code_size - 1; i > 0; i--)
843 pNum_codes[i + 1] += 2;
850 static void tdefl_optimize_huffman_table(
tdefl_compressor *d,
int table_num,
int table_len,
int code_size_limit,
int static_table)
852 int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
853 mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
854 MZ_CLEAR_OBJ(num_codes);
857 for (i = 0; i < table_len; i++)
858 num_codes[d->m_huff_code_sizes[table_num][i]]++;
862 tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
863 int num_used_syms = 0;
864 const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
865 for (i = 0; i < table_len; i++)
868 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
869 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
872 pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
873 tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
875 for (i = 0; i < num_used_syms; i++)
876 num_codes[pSyms[i].m_key]++;
878 tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
880 MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
881 MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
882 for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
883 for (l = num_codes[i]; l > 0; l--)
884 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
888 for (j = 0, i = 2; i <= code_size_limit; i++)
889 next_code[i] = j = ((j + num_codes[i - 1]) << 1);
891 for (i = 0; i < table_len; i++)
893 mz_uint rev_code = 0, code, code_size;
894 if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
896 code = next_code[code_size]++;
897 for (l = code_size; l > 0; l--, code >>= 1)
898 rev_code = (rev_code << 1) | (code & 1);
899 d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
903 #define TDEFL_PUT_BITS(b, l) \
908 MZ_ASSERT(bits <= ((1U << len) - 1U)); \
909 d->m_bit_buffer |= (bits << d->m_bits_in); \
910 d->m_bits_in += len; \
911 while (d->m_bits_in >= 8) \
913 if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
914 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
915 d->m_bit_buffer >>= 8; \
921 #define TDEFL_RLE_PREV_CODE_SIZE() \
923 if (rle_repeat_count) \
925 if (rle_repeat_count < 3) \
927 d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
928 while (rle_repeat_count--) \
929 packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
933 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
934 packed_code_sizes[num_packed_code_sizes++] = 16; \
935 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
937 rle_repeat_count = 0; \
941 #define TDEFL_RLE_ZERO_CODE_SIZE() \
945 if (rle_z_count < 3) \
947 d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \
948 while (rle_z_count--) \
949 packed_code_sizes[num_packed_code_sizes++] = 0; \
951 else if (rle_z_count <= 10) \
953 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \
954 packed_code_sizes[num_packed_code_sizes++] = 17; \
955 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
959 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \
960 packed_code_sizes[num_packed_code_sizes++] = 18; \
961 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
967 static 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 };
971 int num_lit_codes, num_dist_codes, num_bit_lengths;
972 mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
973 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;
975 d->m_huff_count[0][256] = 1;
977 tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
978 tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
980 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
981 if (d->m_huff_code_sizes[0][num_lit_codes - 1])
983 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
984 if (d->m_huff_code_sizes[1][num_dist_codes - 1])
987 memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
988 memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
989 total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
990 num_packed_code_sizes = 0;
992 rle_repeat_count = 0;
994 memset(&d->m_huff_count[2][0], 0,
sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
995 for (i = 0; i < total_code_sizes_to_pack; i++)
997 mz_uint8 code_size = code_sizes_to_pack[i];
1000 TDEFL_RLE_PREV_CODE_SIZE();
1001 if (++rle_z_count == 138)
1003 TDEFL_RLE_ZERO_CODE_SIZE();
1008 TDEFL_RLE_ZERO_CODE_SIZE();
1009 if (code_size != prev_code_size)
1011 TDEFL_RLE_PREV_CODE_SIZE();
1012 d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
1013 packed_code_sizes[num_packed_code_sizes++] = code_size;
1015 else if (++rle_repeat_count == 6)
1017 TDEFL_RLE_PREV_CODE_SIZE();
1020 prev_code_size = code_size;
1022 if (rle_repeat_count)
1024 TDEFL_RLE_PREV_CODE_SIZE();
1028 TDEFL_RLE_ZERO_CODE_SIZE();
1031 tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1033 TDEFL_PUT_BITS(2, 2);
1035 TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1036 TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1038 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1039 if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1041 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1042 TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1043 for (i = 0; (int)i < num_bit_lengths; i++)
1044 TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1046 for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1048 mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1049 MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1050 TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1052 TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
"\02\03\07"[code - 16]);
1059 mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1061 for (i = 0; i <= 143; ++i)
1063 for (; i <= 255; ++i)
1065 for (; i <= 279; ++i)
1067 for (; i <= 287; ++i)
1070 memset(d->m_huff_code_sizes[1], 5, 32);
1072 tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1073 tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1075 TDEFL_PUT_BITS(1, 2);
1078 static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1080 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
1084 mz_uint8 *pLZ_codes;
1085 mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1086 mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1087 mz_uint64 bit_buffer = d->m_bit_buffer;
1088 mz_uint bits_in = d->m_bits_in;
1090 #define TDEFL_PUT_BITS_FAST(b, l) \
1092 bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1097 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1100 flags = *pLZ_codes++ | 0x100;
1104 mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1105 mz_uint match_len = pLZ_codes[0], match_dist = *(
const mz_uint16 *)(pLZ_codes + 1);
1108 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1109 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]]);
1110 TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1113 s0 = s_tdefl_small_dist_sym[match_dist & 511];
1114 n0 = s_tdefl_small_dist_extra[match_dist & 511];
1115 s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1116 n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1117 sym = (match_dist < 512) ? s0 : s1;
1118 num_extra_bits = (match_dist < 512) ? n0 : n1;
1120 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1121 TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1122 TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1126 mz_uint 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]);
1130 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
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]);
1137 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1141 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1142 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1147 if (pOutput_buf >= d->m_pOutput_buf_end)
1150 *(mz_uint64 *)pOutput_buf = bit_buffer;
1151 pOutput_buf += (bits_in >> 3);
1152 bit_buffer >>= (bits_in & ~7);
1156 #undef TDEFL_PUT_BITS_FAST
1158 d->m_pOutput_buf = pOutput_buf;
1160 d->m_bit_buffer = 0;
1164 mz_uint32 n = MZ_MIN(bits_in, 16);
1165 TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1170 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1172 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1178 mz_uint8 *pLZ_codes;
1181 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1184 flags = *pLZ_codes++ | 0x100;
1187 mz_uint sym, num_extra_bits;
1188 mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1191 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1192 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]]);
1193 TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1195 if (match_dist < 512)
1197 sym = s_tdefl_small_dist_sym[match_dist];
1198 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1202 sym = s_tdefl_large_dist_sym[match_dist >> 8];
1203 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1205 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1206 TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1207 TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1211 mz_uint lit = *pLZ_codes++;
1212 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1213 TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1217 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1219 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1223 static mz_bool tdefl_compress_block(
tdefl_compressor *d, mz_bool static_block)
1226 tdefl_start_static_block(d);
1228 tdefl_start_dynamic_block(d);
1229 return tdefl_compress_lz_codes(d);
1234 mz_uint saved_bit_buf, saved_bits_in;
1235 mz_uint8 *pSaved_output_buf;
1236 mz_bool comp_block_succeeded = MZ_FALSE;
1237 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;
1238 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;
1240 d->m_pOutput_buf = pOutput_buf_start;
1241 d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1243 MZ_ASSERT(!d->m_output_flush_remaining);
1244 d->m_output_flush_ofs = 0;
1245 d->m_output_flush_remaining = 0;
1247 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1248 d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1250 if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1252 TDEFL_PUT_BITS(0x78, 8);
1253 TDEFL_PUT_BITS(0x01, 8);
1256 TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1258 pSaved_output_buf = d->m_pOutput_buf;
1259 saved_bit_buf = d->m_bit_buffer;
1260 saved_bits_in = d->m_bits_in;
1263 comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1266 if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1267 ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
1270 d->m_pOutput_buf = pSaved_output_buf;
1271 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1272 TDEFL_PUT_BITS(0, 2);
1275 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1277 for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1279 TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1281 for (i = 0; i < d->m_total_lz_bytes; ++i)
1283 TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1287 else if (!comp_block_succeeded)
1289 d->m_pOutput_buf = pSaved_output_buf;
1290 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1291 tdefl_compress_block(d, MZ_TRUE);
1296 if (flush == TDEFL_FINISH)
1300 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1302 if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
1304 mz_uint i, a = d->m_adler32;
1305 for (i = 0; i < 4; i++)
1307 TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1315 TDEFL_PUT_BITS(0, 3);
1318 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1320 for (i = 2; i; --i, z ^= 0xFFFF)
1322 TDEFL_PUT_BITS(z & 0xFFFF, 16);
1327 MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1329 memset(&d->m_huff_count[0][0], 0,
sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1330 memset(&d->m_huff_count[1][0], 0,
sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1332 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1333 d->m_pLZ_flags = d->m_lz_code_buf;
1334 d->m_num_flags_left = 8;
1335 d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
1336 d->m_total_lz_bytes = 0;
1339 if ((n = (
int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1341 if (d->m_pPut_buf_func)
1343 *d->m_pIn_buf_size = d->m_pSrc - (
const mz_uint8 *)d->m_pIn_buf;
1344 if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1345 return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1347 else if (pOutput_buf_start == d->m_output_buf)
1349 int bytes_to_copy = (int)MZ_MIN((
size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1350 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1351 d->m_out_buf_ofs += bytes_to_copy;
1352 if ((n -= bytes_to_copy) != 0)
1354 d->m_output_flush_ofs = bytes_to_copy;
1355 d->m_output_flush_remaining = n;
1360 d->m_out_buf_ofs += n;
1364 return d->m_output_flush_remaining;
1367 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1368 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1369 static mz_uint16 TDEFL_READ_UNALIGNED_WORD(
const mz_uint8* p)
1372 memcpy(&ret, p,
sizeof(mz_uint16));
1375 static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(
const mz_uint16* p)
1378 memcpy(&ret, p,
sizeof(mz_uint16));
1382 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1383 #define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
1385 static MZ_FORCEINLINE
void tdefl_find_match(
tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1387 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1388 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1389 const mz_uint16 *s = (
const mz_uint16 *)(d->m_dict + pos), *p, *q;
1390 mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
1391 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1392 if (max_match_len <= match_len)
1398 if (--num_probes_left == 0)
1400 #define TDEFL_PROBE \
1401 next_probe_pos = d->m_next[probe_pos]; \
1402 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1404 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1405 if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
1413 q = (
const mz_uint16 *)(d->m_dict + probe_pos);
1414 if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
1420 }
while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1421 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1424 *pMatch_dist = dist;
1425 *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1428 else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(
const mz_uint8 *)p == *(
const mz_uint8 *)q)) > match_len)
1430 *pMatch_dist = dist;
1431 if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1433 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1438 static MZ_FORCEINLINE
void tdefl_find_match(
tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1440 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1441 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1442 const mz_uint8 *s = d->m_dict + pos, *p, *q;
1443 mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1444 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1445 if (max_match_len <= match_len)
1451 if (--num_probes_left == 0)
1453 #define TDEFL_PROBE \
1454 next_probe_pos = d->m_next[probe_pos]; \
1455 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1457 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1458 if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1467 q = d->m_dict + probe_pos;
1468 for (probe_len = 0; probe_len < max_match_len; probe_len++)
1471 if (probe_len > match_len)
1473 *pMatch_dist = dist;
1474 if ((*pMatch_len = match_len = probe_len) == max_match_len)
1476 c0 = d->m_dict[pos + match_len];
1477 c1 = d->m_dict[pos + match_len - 1];
1483 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1484 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1485 static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(
const mz_uint8* p)
1488 memcpy(&ret, p,
sizeof(mz_uint32));
1492 #define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
1497 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;
1498 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1499 mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1501 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1503 const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1504 mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1505 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1506 d->m_src_buf_left -= num_bytes_to_process;
1507 lookahead_size += num_bytes_to_process;
1509 while (num_bytes_to_process)
1511 mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1512 memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1513 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1514 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1516 dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1517 num_bytes_to_process -= n;
1520 dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1521 if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1524 while (lookahead_size >= 4)
1526 mz_uint cur_match_dist, cur_match_len = 1;
1527 mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1528 mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
1529 mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1530 mz_uint probe_pos = d->m_hash[hash];
1531 d->m_hash[hash] = (mz_uint16)lookahead_pos;
1533 if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1535 const mz_uint16 *p = (
const mz_uint16 *)pCur_dict;
1536 const mz_uint16 *q = (
const mz_uint16 *)(d->m_dict + probe_pos);
1537 mz_uint32 probe_len = 32;
1540 }
while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1541 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1542 cur_match_len = ((mz_uint)(p - (
const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(
const mz_uint8 *)p == *(
const mz_uint8 *)q);
1544 cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1546 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1549 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1550 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1551 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1556 cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1558 MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1562 pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1563 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1564 memcpy(&pLZ_code_buf[1], &cur_match_dist,
sizeof(cur_match_dist));
1566 *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1569 *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1571 s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1572 s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1573 d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1575 d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1580 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1581 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1582 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1585 if (--num_flags_left == 0)
1588 pLZ_flags = pLZ_code_buf++;
1591 total_lz_bytes += cur_match_len;
1592 lookahead_pos += cur_match_len;
1593 dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1594 cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1595 MZ_ASSERT(lookahead_size >= cur_match_len);
1596 lookahead_size -= cur_match_len;
1598 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1601 d->m_lookahead_pos = lookahead_pos;
1602 d->m_lookahead_size = lookahead_size;
1603 d->m_dict_size = dict_size;
1604 d->m_total_lz_bytes = total_lz_bytes;
1605 d->m_pLZ_code_buf = pLZ_code_buf;
1606 d->m_pLZ_flags = pLZ_flags;
1607 d->m_num_flags_left = num_flags_left;
1608 if ((n = tdefl_flush_block(d, 0)) != 0)
1609 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1610 total_lz_bytes = d->m_total_lz_bytes;
1611 pLZ_code_buf = d->m_pLZ_code_buf;
1612 pLZ_flags = d->m_pLZ_flags;
1613 num_flags_left = d->m_num_flags_left;
1617 while (lookahead_size)
1619 mz_uint8 lit = d->m_dict[cur_pos];
1622 *pLZ_code_buf++ = lit;
1623 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1624 if (--num_flags_left == 0)
1627 pLZ_flags = pLZ_code_buf++;
1630 d->m_huff_count[0][lit]++;
1633 dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1634 cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1637 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1640 d->m_lookahead_pos = lookahead_pos;
1641 d->m_lookahead_size = lookahead_size;
1642 d->m_dict_size = dict_size;
1643 d->m_total_lz_bytes = total_lz_bytes;
1644 d->m_pLZ_code_buf = pLZ_code_buf;
1645 d->m_pLZ_flags = pLZ_flags;
1646 d->m_num_flags_left = num_flags_left;
1647 if ((n = tdefl_flush_block(d, 0)) != 0)
1648 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1649 total_lz_bytes = d->m_total_lz_bytes;
1650 pLZ_code_buf = d->m_pLZ_code_buf;
1651 pLZ_flags = d->m_pLZ_flags;
1652 num_flags_left = d->m_num_flags_left;
1657 d->m_lookahead_pos = lookahead_pos;
1658 d->m_lookahead_size = lookahead_size;
1659 d->m_dict_size = dict_size;
1660 d->m_total_lz_bytes = total_lz_bytes;
1661 d->m_pLZ_code_buf = pLZ_code_buf;
1662 d->m_pLZ_flags = pLZ_flags;
1663 d->m_num_flags_left = num_flags_left;
1668 static MZ_FORCEINLINE
void tdefl_record_literal(
tdefl_compressor *d, mz_uint8 lit)
1670 d->m_total_lz_bytes++;
1671 *d->m_pLZ_code_buf++ = lit;
1672 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1673 if (--d->m_num_flags_left == 0)
1675 d->m_num_flags_left = 8;
1676 d->m_pLZ_flags = d->m_pLZ_code_buf++;
1678 d->m_huff_count[0][lit]++;
1681 static MZ_FORCEINLINE
void tdefl_record_match(
tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1685 MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1687 d->m_total_lz_bytes += match_len;
1689 d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1692 d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1693 d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1694 d->m_pLZ_code_buf += 3;
1696 *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1697 if (--d->m_num_flags_left == 0)
1699 d->m_num_flags_left = 8;
1700 d->m_pLZ_flags = d->m_pLZ_code_buf++;
1703 s0 = s_tdefl_small_dist_sym[match_dist & 511];
1704 s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1705 d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1707 if (match_len >= TDEFL_MIN_MATCH_LEN)
1708 d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1713 const mz_uint8 *pSrc = d->m_pSrc;
1714 size_t src_buf_left = d->m_src_buf_left;
1715 tdefl_flush flush = d->m_flush;
1717 while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1719 mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1721 if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1723 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
1724 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];
1725 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1726 const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1727 src_buf_left -= num_bytes_to_process;
1728 d->m_lookahead_size += num_bytes_to_process;
1729 while (pSrc != pSrc_end)
1731 mz_uint8 c = *pSrc++;
1732 d->m_dict[dst_pos] = c;
1733 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1734 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1735 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1736 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1737 d->m_hash[hash] = (mz_uint16)(ins_pos);
1738 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1744 while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1746 mz_uint8 c = *pSrc++;
1747 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1749 d->m_dict[dst_pos] = c;
1750 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1751 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1752 if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1754 mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1755 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);
1756 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1757 d->m_hash[hash] = (mz_uint16)(ins_pos);
1761 d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1762 if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1768 cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1769 cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1770 if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1772 if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1774 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1776 while (cur_match_len < d->m_lookahead_size)
1778 if (d->m_dict[cur_pos + cur_match_len] != c)
1782 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1790 tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1792 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)))
1794 cur_match_dist = cur_match_len = 0;
1796 if (d->m_saved_match_len)
1798 if (cur_match_len > d->m_saved_match_len)
1800 tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1801 if (cur_match_len >= 128)
1803 tdefl_record_match(d, cur_match_len, cur_match_dist);
1804 d->m_saved_match_len = 0;
1805 len_to_move = cur_match_len;
1809 d->m_saved_lit = d->m_dict[cur_pos];
1810 d->m_saved_match_dist = cur_match_dist;
1811 d->m_saved_match_len = cur_match_len;
1816 tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1817 len_to_move = d->m_saved_match_len - 1;
1818 d->m_saved_match_len = 0;
1821 else if (!cur_match_dist)
1822 tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos,
sizeof(d->m_dict) - 1)]);
1823 else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1825 tdefl_record_match(d, cur_match_len, cur_match_dist);
1826 len_to_move = cur_match_len;
1830 d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos,
sizeof(d->m_dict) - 1)];
1831 d->m_saved_match_dist = cur_match_dist;
1832 d->m_saved_match_len = cur_match_len;
1835 d->m_lookahead_pos += len_to_move;
1836 MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1837 d->m_lookahead_size -= len_to_move;
1838 d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1840 if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1841 ((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))))
1845 d->m_src_buf_left = src_buf_left;
1846 if ((n = tdefl_flush_block(d, 0)) != 0)
1847 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1852 d->m_src_buf_left = src_buf_left;
1858 if (d->m_pIn_buf_size)
1860 *d->m_pIn_buf_size = d->m_pSrc - (
const mz_uint8 *)d->m_pIn_buf;
1863 if (d->m_pOut_buf_size)
1865 size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1866 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1867 d->m_output_flush_ofs += (mz_uint)n;
1868 d->m_output_flush_remaining -= (mz_uint)n;
1869 d->m_out_buf_ofs += n;
1871 *d->m_pOut_buf_size = d->m_out_buf_ofs;
1874 return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1877 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)
1885 return TDEFL_STATUS_BAD_PARAM;
1888 d->m_pIn_buf = pIn_buf;
1889 d->m_pIn_buf_size = pIn_buf_size;
1890 d->m_pOut_buf = pOut_buf;
1891 d->m_pOut_buf_size = pOut_buf_size;
1892 d->m_pSrc = (
const mz_uint8 *)(pIn_buf);
1893 d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1894 d->m_out_buf_ofs = 0;
1897 if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1898 (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1904 return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1906 d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1908 if ((d->m_output_flush_remaining) || (d->m_finished))
1909 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1911 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1912 if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1913 ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1914 ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
1916 if (!tdefl_compress_fast(d))
1917 return d->m_prev_return_status;
1922 if (!tdefl_compress_normal(d))
1923 return d->m_prev_return_status;
1926 if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1927 d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (
const mz_uint8 *)pIn_buf, d->m_pSrc - (
const mz_uint8 *)pIn_buf);
1929 if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1931 if (tdefl_flush_block(d, flush) < 0)
1932 return d->m_prev_return_status;
1933 d->m_finished = (flush == TDEFL_FINISH);
1934 if (flush == TDEFL_FULL_FLUSH)
1936 MZ_CLEAR_OBJ(d->m_hash);
1937 MZ_CLEAR_OBJ(d->m_next);
1942 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1945 tdefl_status tdefl_compress_buffer(
tdefl_compressor *d,
const void *pIn_buf,
size_t in_buf_size, tdefl_flush flush)
1947 MZ_ASSERT(d->m_pPut_buf_func);
1948 return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1951 tdefl_status tdefl_init(
tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func,
void *pPut_buf_user,
int flags)
1953 d->m_pPut_buf_func = pPut_buf_func;
1954 d->m_pPut_buf_user = pPut_buf_user;
1955 d->m_flags = (mz_uint)(flags);
1956 d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
1957 d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
1958 d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
1959 if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1960 MZ_CLEAR_OBJ(d->m_hash);
1961 d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
1962 d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
1963 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1964 d->m_pLZ_flags = d->m_lz_code_buf;
1965 d->m_num_flags_left = 8;
1966 d->m_pOutput_buf = d->m_output_buf;
1967 d->m_pOutput_buf_end = d->m_output_buf;
1968 d->m_prev_return_status = TDEFL_STATUS_OKAY;
1969 d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
1971 d->m_pIn_buf = NULL;
1972 d->m_pOut_buf = NULL;
1973 d->m_pIn_buf_size = NULL;
1974 d->m_pOut_buf_size = NULL;
1975 d->m_flush = TDEFL_NO_FLUSH;
1977 d->m_src_buf_left = 0;
1978 d->m_out_buf_ofs = 0;
1979 if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1980 MZ_CLEAR_OBJ(d->m_dict);
1981 memset(&d->m_huff_count[0][0], 0,
sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1982 memset(&d->m_huff_count[1][0], 0,
sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1983 return TDEFL_STATUS_OKAY;
1988 return d->m_prev_return_status;
1993 return d->m_adler32;
1996 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)
2000 if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
2005 succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2006 succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2013 size_t m_size, m_capacity;
2015 mz_bool m_expandable;
2018 static mz_bool tdefl_output_buffer_putter(
const void *pBuf,
int len,
void *pUser)
2021 size_t new_size = p->m_size + len;
2022 if (new_size > p->m_capacity)
2024 size_t new_capacity = p->m_capacity;
2026 if (!p->m_expandable)
2030 new_capacity = MZ_MAX(128U, new_capacity << 1U);
2031 }
while (new_size > new_capacity);
2032 pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
2035 p->m_pBuf = pNew_buf;
2036 p->m_capacity = new_capacity;
2038 memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
2039 p->m_size = new_size;
2043 void *tdefl_compress_mem_to_heap(
const void *pSrc_buf,
size_t src_buf_len,
size_t *pOut_len,
int flags)
2046 MZ_CLEAR_OBJ(out_buf);
2051 out_buf.m_expandable = MZ_TRUE;
2052 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2054 *pOut_len = out_buf.m_size;
2055 return out_buf.m_pBuf;
2058 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)
2061 MZ_CLEAR_OBJ(out_buf);
2064 out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2065 out_buf.m_capacity = out_buf_len;
2066 if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2068 return out_buf.m_size;
2071 static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2074 mz_uint tdefl_create_comp_flags_from_zip_params(
int level,
int window_bits,
int strategy)
2076 mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2077 if (window_bits > 0)
2078 comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2081 comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2082 else if (strategy == MZ_FILTERED)
2083 comp_flags |= TDEFL_FILTER_MATCHES;
2084 else if (strategy == MZ_HUFFMAN_ONLY)
2085 comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2086 else if (strategy == MZ_FIXED)
2087 comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2088 else if (strategy == MZ_RLE)
2089 comp_flags |= TDEFL_RLE_MATCHES;
2095 #pragma warning(push)
2096 #pragma warning(disable : 4204)
2102 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)
2105 static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2108 int i, bpl = w * num_chans, y, z;
2113 MZ_CLEAR_OBJ(out_buf);
2114 out_buf.m_expandable = MZ_TRUE;
2115 out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2116 if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2122 for (z = 41; z; --z)
2123 tdefl_output_buffer_putter(&z, 1, &out_buf);
2125 tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2126 for (y = 0; y < h; ++y)
2128 tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
2129 tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2131 if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
2134 MZ_FREE(out_buf.m_pBuf);
2138 *pLen_out = out_buf.m_size - 41;
2140 static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2141 mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2142 0x0a, 0x1a, 0x0a, 0x00, 0x00,
2143 0x00, 0x0d, 0x49, 0x48, 0x44,
2144 0x52, 0x00, 0x00, 0x00, 0x00,
2145 0x00, 0x00, 0x00, 0x00, 0x08,
2146 0x00, 0x00, 0x00, 0x00, 0x00,
2147 0x00, 0x00, 0x00, 0x00, 0x00,
2148 0x00, 0x00, 0x49, 0x44, 0x41,
2150 pnghdr[18] = (mz_uint8)(w >> 8);
2151 pnghdr[19] = (mz_uint8)w;
2152 pnghdr[22] = (mz_uint8)(h >> 8);
2153 pnghdr[23] = (mz_uint8)h;
2154 pnghdr[25] = chans[num_chans];
2155 pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2156 pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2157 pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2158 pnghdr[36] = (mz_uint8)*pLen_out;
2159 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2160 for (i = 0; i < 4; ++i, c <<= 8)
2161 ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2162 memcpy(out_buf.m_pBuf, pnghdr, 41);
2165 if (!tdefl_output_buffer_putter(
"\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2169 MZ_FREE(out_buf.m_pBuf);
2172 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2173 for (i = 0; i < 4; ++i, c <<= 8)
2174 (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2178 return out_buf.m_pBuf;
2180 void *tdefl_write_image_to_png_file_in_memory(
const void *pImage,
int w,
int h,
int num_chans,
size_t *pLen_out)
2183 return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2186 #ifndef MINIZ_NO_MALLOC
2202 #pragma warning(pop)
2242 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2243 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
2245 #define TINFL_CR_BEGIN \
2246 switch (r->m_state) \
2249 #define TINFL_CR_RETURN(state_index, result) \
2253 r->m_state = state_index; \
2255 case state_index:; \
2258 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
2263 TINFL_CR_RETURN(state_index, result); \
2267 #define TINFL_CR_FINISH }
2269 #define TINFL_GET_BYTE(state_index, c) \
2272 while (pIn_buf_cur >= pIn_buf_end) \
2274 TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2276 c = *pIn_buf_cur++; \
2280 #define TINFL_NEED_BITS(state_index, n) \
2284 TINFL_GET_BYTE(state_index, c); \
2285 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2287 } while (num_bits < (mz_uint)(n))
2288 #define TINFL_SKIP_BITS(state_index, n) \
2291 if (num_bits < (mz_uint)(n)) \
2293 TINFL_NEED_BITS(state_index, n); \
2299 #define TINFL_GET_BITS(state_index, b, n) \
2302 if (num_bits < (mz_uint)(n)) \
2304 TINFL_NEED_BITS(state_index, n); \
2306 b = bit_buf & ((1 << (n)) - 1); \
2316 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
2319 temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
2322 code_len = temp >> 9; \
2323 if ((code_len) && (num_bits >= code_len)) \
2326 else if (num_bits > TINFL_FAST_LOOKUP_BITS) \
2328 code_len = TINFL_FAST_LOOKUP_BITS; \
2331 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2332 } while ((temp < 0) && (num_bits >= (code_len + 1))); \
2336 TINFL_GET_BYTE(state_index, c); \
2337 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2339 } while (num_bits < 15);
2347 #define TINFL_HUFF_DECODE(state_index, sym, pHuff) \
2351 mz_uint code_len, c; \
2352 if (num_bits < 15) \
2354 if ((pIn_buf_end - pIn_buf_cur) < 2) \
2356 TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
2360 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2365 if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
2366 code_len = temp >> 9, temp &= 511; \
2369 code_len = TINFL_FAST_LOOKUP_BITS; \
2372 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2373 } while (temp < 0); \
2376 bit_buf >>= code_len; \
2377 num_bits -= code_len; \
2381 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)
2383 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 };
2384 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 };
2385 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 };
2386 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 };
2387 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 };
2388 static const int s_min_table_sizes[3] = { 257, 1, 4 };
2390 tinfl_status status = TINFL_STATUS_FAILED;
2391 mz_uint32 num_bits, dist, counter, num_extra;
2392 tinfl_bit_buf_t bit_buf;
2393 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *
const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2394 mz_uint8 *pOut_buf_cur = pOut_buf_next, *
const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
2395 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;
2398 if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2400 *pIn_buf_size = *pOut_buf_size = 0;
2401 return TINFL_STATUS_BAD_PARAM;
2404 num_bits = r->m_num_bits;
2405 bit_buf = r->m_bit_buf;
2407 counter = r->m_counter;
2408 num_extra = r->m_num_extra;
2409 dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2412 bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2413 r->m_z_adler32 = r->m_check_adler32 = 1;
2414 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2416 TINFL_GET_BYTE(1, r->m_zhdr0);
2417 TINFL_GET_BYTE(2, r->m_zhdr1);
2418 counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2419 if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2420 counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2423 TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2429 TINFL_GET_BITS(3, r->m_final, 3);
2430 r->m_type = r->m_final >> 1;
2433 TINFL_SKIP_BITS(5, num_bits & 7);
2434 for (counter = 0; counter < 4; ++counter)
2437 TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2439 TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2441 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))))
2443 TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2445 while ((counter) && (num_bits))
2447 TINFL_GET_BITS(51, dist, 8);
2448 while (pOut_buf_cur >= pOut_buf_end)
2450 TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2452 *pOut_buf_cur++ = (mz_uint8)dist;
2458 while (pOut_buf_cur >= pOut_buf_end)
2460 TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2462 while (pIn_buf_cur >= pIn_buf_end)
2464 TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
2466 n = MZ_MIN(MZ_MIN((
size_t)(pOut_buf_end - pOut_buf_cur), (
size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2467 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2470 counter -= (mz_uint)n;
2473 else if (r->m_type == 3)
2475 TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2481 mz_uint8 *p = r->m_tables[0].m_code_size;
2483 r->m_table_sizes[0] = 288;
2484 r->m_table_sizes[1] = 32;
2485 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2486 for (i = 0; i <= 143; ++i)
2488 for (; i <= 255; ++i)
2490 for (; i <= 279; ++i)
2492 for (; i <= 287; ++i)
2497 for (counter = 0; counter < 3; counter++)
2499 TINFL_GET_BITS(11, r->m_table_sizes[counter],
"\05\05\04"[counter]);
2500 r->m_table_sizes[counter] += s_min_table_sizes[counter];
2502 MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2503 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2506 TINFL_GET_BITS(14, s, 3);
2507 r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2509 r->m_table_sizes[2] = 19;
2511 for (; (int)r->m_type >= 0; r->m_type--)
2513 int tree_next, tree_cur;
2515 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2516 pTable = &r->m_tables[r->m_type];
2517 MZ_CLEAR_OBJ(total_syms);
2518 MZ_CLEAR_OBJ(pTable->m_look_up);
2519 MZ_CLEAR_OBJ(pTable->m_tree);
2520 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2521 total_syms[pTable->m_code_size[i]]++;
2522 used_syms = 0, total = 0;
2523 next_code[0] = next_code[1] = 0;
2524 for (i = 1; i <= 15; ++i)
2526 used_syms += total_syms[i];
2527 next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2529 if ((65536 != total) && (used_syms > 1))
2531 TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2533 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2535 mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
2538 cur_code = next_code[code_size]++;
2539 for (l = code_size; l > 0; l--, cur_code >>= 1)
2540 rev_code = (rev_code << 1) | (cur_code & 1);
2541 if (code_size <= TINFL_FAST_LOOKUP_BITS)
2543 mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2544 while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2546 pTable->m_look_up[rev_code] = k;
2547 rev_code += (1 << code_size);
2551 if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2553 pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2554 tree_cur = tree_next;
2557 rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2558 for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2560 tree_cur -= ((rev_code >>= 1) & 1);
2561 if (!pTable->m_tree[-tree_cur - 1])
2563 pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2564 tree_cur = tree_next;
2568 tree_cur = pTable->m_tree[-tree_cur - 1];
2570 tree_cur -= ((rev_code >>= 1) & 1);
2571 pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2575 for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2578 TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2581 r->m_len_codes[counter++] = (mz_uint8)dist;
2584 if ((dist == 16) && (!counter))
2586 TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2588 num_extra =
"\02\03\07"[dist - 16];
2589 TINFL_GET_BITS(18, s, num_extra);
2590 s +=
"\03\03\013"[dist - 16];
2591 TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2594 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2596 TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2598 TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
2599 TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
2607 if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2609 TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2612 while (pOut_buf_cur >= pOut_buf_end)
2614 TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2616 *pOut_buf_cur++ = (mz_uint8)counter;
2622 #if TINFL_USE_64BIT_BITBUF
2625 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2632 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2637 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2638 code_len = sym2 >> 9;
2641 code_len = TINFL_FAST_LOOKUP_BITS;
2644 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2648 bit_buf >>= code_len;
2649 num_bits -= code_len;
2653 #if !TINFL_USE_64BIT_BITBUF
2656 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2661 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2662 code_len = sym2 >> 9;
2665 code_len = TINFL_FAST_LOOKUP_BITS;
2668 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2671 bit_buf >>= code_len;
2672 num_bits -= code_len;
2674 pOut_buf_cur[0] = (mz_uint8)counter;
2681 pOut_buf_cur[1] = (mz_uint8)sym2;
2685 if ((counter &= 511) == 256)
2688 num_extra = s_length_extra[counter - 257];
2689 counter = s_length_base[counter - 257];
2693 TINFL_GET_BITS(25, extra_bits, num_extra);
2694 counter += extra_bits;
2697 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2698 num_extra = s_dist_extra[dist];
2699 dist = s_dist_base[dist];
2703 TINFL_GET_BITS(27, extra_bits, num_extra);
2707 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2708 if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2710 TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2713 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2715 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2719 while (pOut_buf_cur >= pOut_buf_end)
2721 TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2723 *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2727 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2728 else if ((counter >= 9) && (counter <= dist))
2730 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2733 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
2734 memcpy(pOut_buf_cur, pSrc,
sizeof(mz_uint32)*2);
2736 ((mz_uint32 *)pOut_buf_cur)[0] = ((
const mz_uint32 *)pSrc)[0];
2737 ((mz_uint32 *)pOut_buf_cur)[1] = ((
const mz_uint32 *)pSrc)[1];
2740 }
while ((pSrc += 8) < pSrc_end);
2741 if ((counter &= 7) < 3)
2745 pOut_buf_cur[0] = pSrc[0];
2747 pOut_buf_cur[1] = pSrc[1];
2748 pOut_buf_cur += counter;
2756 pOut_buf_cur[0] = pSrc[0];
2757 pOut_buf_cur[1] = pSrc[1];
2758 pOut_buf_cur[2] = pSrc[2];
2765 pOut_buf_cur[0] = pSrc[0];
2767 pOut_buf_cur[1] = pSrc[1];
2768 pOut_buf_cur += counter;
2772 }
while (!(r->m_final & 1));
2776 TINFL_SKIP_BITS(32, num_bits & 7);
2777 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2782 bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2783 MZ_ASSERT(!num_bits);
2785 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2787 for (counter = 0; counter < 4; ++counter)
2791 TINFL_GET_BITS(41, s, 8);
2793 TINFL_GET_BYTE(42, s);
2794 r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2797 TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2805 if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
2807 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2813 r->m_num_bits = num_bits;
2814 r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2816 r->m_counter = counter;
2817 r->m_num_extra = num_extra;
2818 r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2819 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2820 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2821 if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2823 const mz_uint8 *ptr = pOut_buf_next;
2824 size_t buf_len = *pOut_buf_size;
2825 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2826 size_t block_len = buf_len % 5552;
2829 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2831 s1 += ptr[0], s2 += s1;
2832 s1 += ptr[1], s2 += s1;
2833 s1 += ptr[2], s2 += s1;
2834 s1 += ptr[3], s2 += s1;
2835 s1 += ptr[4], s2 += s1;
2836 s1 += ptr[5], s2 += s1;
2837 s1 += ptr[6], s2 += s1;
2838 s1 += ptr[7], s2 += s1;
2840 for (; i < block_len; ++i)
2841 s1 += *ptr++, s2 += s1;
2842 s1 %= 65521U, s2 %= 65521U;
2843 buf_len -= block_len;
2846 r->m_check_adler32 = (s2 << 16) + s1;
2847 if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2848 status = TINFL_STATUS_ADLER32_MISMATCH;
2854 void *tinfl_decompress_mem_to_heap(
const void *pSrc_buf,
size_t src_buf_len,
size_t *pOut_len,
int flags)
2857 void *pBuf = NULL, *pNew_buf;
2858 size_t src_buf_ofs = 0, out_buf_capacity = 0;
2860 tinfl_init(&decomp);
2863 size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2864 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,
2865 (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2866 if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2872 src_buf_ofs += src_buf_size;
2873 *pOut_len += dst_buf_size;
2874 if (status == TINFL_STATUS_DONE)
2876 new_out_buf_capacity = out_buf_capacity * 2;
2877 if (new_out_buf_capacity < 128)
2878 new_out_buf_capacity = 128;
2879 pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2887 out_buf_capacity = new_out_buf_capacity;
2892 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)
2895 tinfl_status status;
2896 tinfl_init(&decomp);
2897 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);
2898 return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2901 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)
2905 mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2906 size_t in_buf_ofs = 0, dict_ofs = 0;
2908 return TINFL_STATUS_FAILED;
2909 tinfl_init(&decomp);
2912 size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2913 tinfl_status status = tinfl_decompress(&decomp, (
const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2914 (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2915 in_buf_ofs += in_buf_size;
2916 if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (
int)dst_buf_size, pPut_buf_user)))
2918 if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2920 result = (status == TINFL_STATUS_DONE);
2923 dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2926 *pIn_buf_size = in_buf_ofs;
2930 #ifndef MINIZ_NO_MALLOC
2935 tinfl_init(pDecomp);
2976 #ifndef MINIZ_NO_ARCHIVE_APIS
2984 #ifdef MINIZ_NO_STDIO
2985 #define MZ_FILE void *
2987 #include <sys/stat.h>
2989 #if defined(_MSC_VER) || defined(__MINGW64__)
2994 static FILE *mz_fopen(
const char *pFilename,
const char *pMode)
2996 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
2997 std::wstring wideFilename = converter.from_bytes(pFilename);
2998 std::wstring wideMode = converter.from_bytes(pMode);
3001 _wfopen_s(&pFile, wideFilename.c_str(), wideMode.c_str());
3004 static FILE *mz_freopen(
const char *pPath,
const char *pMode, FILE *pStream)
3006 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
3007 std::wstring widePath = converter.from_bytes(pPath);
3008 std::wstring wideMode = converter.from_bytes(pMode);
3011 if (_wfreopen_s(&pFile, widePath.c_str(), wideMode.c_str(), pStream))
3015 #ifndef MINIZ_NO_TIME
3016 #include <sys/utime.h>
3018 #define MZ_FOPEN mz_fopen
3019 #define MZ_FCLOSE fclose
3020 #define MZ_FREAD fread
3021 #define MZ_FWRITE fwrite
3022 #define MZ_FTELL64 _ftelli64
3023 #define MZ_FSEEK64 _fseeki64
3024 #define MZ_FILE_STAT_STRUCT _stat64
3025 #define MZ_FILE_STAT _stat64
3026 #define MZ_FFLUSH fflush
3027 #define MZ_FREOPEN mz_freopen
3028 #define MZ_DELETE_FILE remove
3029 #elif defined(__MINGW32__)
3030 #ifndef MINIZ_NO_TIME
3031 #include <sys/utime.h>
3033 #define MZ_FOPEN(f, m) fopen(f, m)
3034 #define MZ_FCLOSE fclose
3035 #define MZ_FREAD fread
3036 #define MZ_FWRITE fwrite
3037 #define MZ_FTELL64 ftello64
3038 #define MZ_FSEEK64 fseeko64
3039 #define MZ_FILE_STAT_STRUCT _stat
3040 #define MZ_FILE_STAT _stat
3041 #define MZ_FFLUSH fflush
3042 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3043 #define MZ_DELETE_FILE remove
3044 #elif defined(__TINYC__)
3045 #ifndef MINIZ_NO_TIME
3046 #include <sys/utime.h>
3048 #define MZ_FOPEN(f, m) fopen(f, m)
3049 #define MZ_FCLOSE fclose
3050 #define MZ_FREAD fread
3051 #define MZ_FWRITE fwrite
3052 #define MZ_FTELL64 ftell
3053 #define MZ_FSEEK64 fseek
3054 #define MZ_FILE_STAT_STRUCT stat
3055 #define MZ_FILE_STAT stat
3056 #define MZ_FFLUSH fflush
3057 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3058 #define MZ_DELETE_FILE remove
3059 #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
3060 #ifndef MINIZ_NO_TIME
3063 #define MZ_FOPEN(f, m) fopen64(f, m)
3064 #define MZ_FCLOSE fclose
3065 #define MZ_FREAD fread
3066 #define MZ_FWRITE fwrite
3067 #define MZ_FTELL64 ftello64
3068 #define MZ_FSEEK64 fseeko64
3069 #define MZ_FILE_STAT_STRUCT stat64
3070 #define MZ_FILE_STAT stat64
3071 #define MZ_FFLUSH fflush
3072 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3073 #define MZ_DELETE_FILE remove
3074 #elif defined(__APPLE__)
3075 #ifndef MINIZ_NO_TIME
3078 #define MZ_FOPEN(f, m) fopen(f, m)
3079 #define MZ_FCLOSE fclose
3080 #define MZ_FREAD fread
3081 #define MZ_FWRITE fwrite
3082 #define MZ_FTELL64 ftello
3083 #define MZ_FSEEK64 fseeko
3084 #define MZ_FILE_STAT_STRUCT stat
3085 #define MZ_FILE_STAT stat
3086 #define MZ_FFLUSH fflush
3087 #define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3088 #define MZ_DELETE_FILE remove
3091 #pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3092 #ifndef MINIZ_NO_TIME
3095 #define MZ_FOPEN(f, m) fopen(f, m)
3096 #define MZ_FCLOSE fclose
3097 #define MZ_FREAD fread
3098 #define MZ_FWRITE fwrite
3099 #ifdef __STRICT_ANSI__
3100 #define MZ_FTELL64 ftell
3101 #define MZ_FSEEK64 fseek
3103 #define MZ_FTELL64 ftello
3104 #define MZ_FSEEK64 fseeko
3106 #define MZ_FILE_STAT_STRUCT stat
3107 #define MZ_FILE_STAT stat
3108 #define MZ_FFLUSH fflush
3109 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3110 #define MZ_DELETE_FILE remove
3114 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3120 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
3121 MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
3122 MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
3123 MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
3124 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
3125 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
3128 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
3129 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
3130 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
3131 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
3132 MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
3133 MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
3134 MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
3135 MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
3138 MZ_ZIP_CDH_SIG_OFS = 0,
3139 MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
3140 MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
3141 MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
3142 MZ_ZIP_CDH_METHOD_OFS = 10,
3143 MZ_ZIP_CDH_FILE_TIME_OFS = 12,
3144 MZ_ZIP_CDH_FILE_DATE_OFS = 14,
3145 MZ_ZIP_CDH_CRC32_OFS = 16,
3146 MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
3147 MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
3148 MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
3149 MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
3150 MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
3151 MZ_ZIP_CDH_DISK_START_OFS = 34,
3152 MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
3153 MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
3154 MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
3157 MZ_ZIP_LDH_SIG_OFS = 0,
3158 MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
3159 MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
3160 MZ_ZIP_LDH_METHOD_OFS = 8,
3161 MZ_ZIP_LDH_FILE_TIME_OFS = 10,
3162 MZ_ZIP_LDH_FILE_DATE_OFS = 12,
3163 MZ_ZIP_LDH_CRC32_OFS = 14,
3164 MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
3165 MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
3166 MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
3167 MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
3168 MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
3171 MZ_ZIP_ECDH_SIG_OFS = 0,
3172 MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
3173 MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
3174 MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
3175 MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
3176 MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
3177 MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
3178 MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
3181 MZ_ZIP64_ECDL_SIG_OFS = 0,
3182 MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,
3183 MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,
3184 MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16,
3187 MZ_ZIP64_ECDH_SIG_OFS = 0,
3188 MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,
3189 MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,
3190 MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,
3191 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,
3192 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,
3193 MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24,
3194 MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,
3195 MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,
3196 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,
3197 MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
3198 MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
3199 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
3200 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
3201 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
3202 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
3203 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
3209 size_t m_size, m_capacity;
3210 mz_uint m_element_size;
3220 uint32_t m_init_flags;
3226 mz_bool m_zip64_has_extended_info_fields;
3230 mz_uint64 m_file_archive_start_ofs;
3234 size_t m_mem_capacity;
3237 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3239 #if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
3240 static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(
const mz_zip_array *pArray, mz_uint index)
3242 MZ_ASSERT(index < pArray->m_size);
3245 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3247 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3250 static MZ_FORCEINLINE
void mz_zip_array_init(
mz_zip_array *pArray, mz_uint32 element_size)
3253 pArray->m_element_size = element_size;
3258 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3262 static mz_bool mz_zip_array_ensure_capacity(
mz_zip_archive *pZip,
mz_zip_array *pArray,
size_t min_new_capacity, mz_uint growing)
3265 size_t new_capacity = min_new_capacity;
3266 MZ_ASSERT(pArray->m_element_size);
3267 if (pArray->m_capacity >= min_new_capacity)
3271 new_capacity = MZ_MAX(1, pArray->m_capacity);
3272 while (new_capacity < min_new_capacity)
3275 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3277 pArray->m_p = pNew_p;
3278 pArray->m_capacity = new_capacity;
3282 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(
mz_zip_archive *pZip,
mz_zip_array *pArray,
size_t new_capacity, mz_uint growing)
3284 if (new_capacity > pArray->m_capacity)
3286 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3292 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(
mz_zip_archive *pZip,
mz_zip_array *pArray,
size_t new_size, mz_uint growing)
3294 if (new_size > pArray->m_capacity)
3296 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3299 pArray->m_size = new_size;
3305 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3308 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(
mz_zip_archive *pZip,
mz_zip_array *pArray,
const void *pElements,
size_t n)
3310 size_t orig_size = pArray->m_size;
3311 if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3314 memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3318 #ifndef MINIZ_NO_TIME
3319 static MZ_TIME_T mz_zip_dos_to_time_t(
int dos_time,
int dos_date)
3322 memset(&tm, 0,
sizeof(tm));
3324 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3325 tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3326 tm.tm_mday = dos_date & 31;
3327 tm.tm_hour = (dos_time >> 11) & 31;
3328 tm.tm_min = (dos_time >> 5) & 63;
3329 tm.tm_sec = (dos_time << 1) & 62;
3333 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3334 static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3337 struct tm tm_struct;
3338 struct tm *tm = &tm_struct;
3339 errno_t err = localtime_s(tm, &time);
3347 struct tm *tm = localtime(&time);
3350 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3351 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3355 #ifndef MINIZ_NO_STDIO
3356 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3357 static mz_bool mz_zip_get_file_modified_time(
const char *pFilename, MZ_TIME_T *pTime)
3359 struct MZ_FILE_STAT_STRUCT file_stat;
3362 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3365 *pTime = file_stat.st_mtime;
3371 static mz_bool mz_zip_set_file_times(
const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3375 memset(&t, 0,
sizeof(t));
3376 t.actime = access_time;
3377 t.modtime = modified_time;
3379 return !utime(pFilename, &t);
3384 static MZ_FORCEINLINE mz_bool mz_zip_set_error(
mz_zip_archive *pZip, mz_zip_error err_num)
3387 pZip->m_last_error = err_num;
3391 static mz_bool mz_zip_reader_init_internal(
mz_zip_archive *pZip, mz_uint flags)
3394 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3395 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3397 if (!pZip->m_pAlloc)
3398 pZip->m_pAlloc = miniz_def_alloc_func;
3400 pZip->m_pFree = miniz_def_free_func;
3401 if (!pZip->m_pRealloc)
3402 pZip->m_pRealloc = miniz_def_realloc_func;
3404 pZip->m_archive_size = 0;
3405 pZip->m_central_directory_file_ofs = 0;
3406 pZip->m_total_files = 0;
3407 pZip->m_last_error = MZ_ZIP_NO_ERROR;
3410 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3413 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
sizeof(mz_uint8));
3414 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
sizeof(mz_uint32));
3415 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
sizeof(mz_uint32));
3416 pZip->m_pState->m_init_flags = flags;
3417 pZip->m_pState->m_zip64 = MZ_FALSE;
3418 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3420 pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3425 static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(
const mz_zip_array *pCentral_dir_array,
const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3427 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;
3428 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3429 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3430 mz_uint8 l = 0, r = 0;
3431 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3432 pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3433 pE = pL + MZ_MIN(l_len, r_len);
3436 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3441 return (pL == pE) ? (l_len < r_len) : (l < r);
3444 #define MZ_SWAP_UINT32(a, b) \
3454 static void mz_zip_reader_sort_central_dir_offsets_by_filename(
mz_zip_archive *pZip)
3457 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3458 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3459 mz_uint32 *pIndices;
3460 mz_uint32 start, end;
3461 const mz_uint32 size = pZip->m_total_files;
3466 pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3468 start = (size - 2U) >> 1U;
3471 mz_uint64 child, root = start;
3474 if ((child = (root << 1U) + 1U) >= size)
3476 child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3477 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3479 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3490 mz_uint64 child, root = 0;
3491 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3494 if ((child = (root << 1U) + 1U) >= end)
3496 child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3497 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3499 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3506 static mz_bool mz_zip_reader_locate_header_sig(
mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
3508 mz_int64 cur_file_ofs;
3509 mz_uint32 buf_u32[4096 /
sizeof(mz_uint32)];
3510 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3513 if (pZip->m_archive_size < record_size)
3517 cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)
sizeof(buf_u32), 0);
3520 int i, n = (int)MZ_MIN(
sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3522 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3525 for (i = n - 4; i >= 0; --i)
3527 mz_uint s = MZ_READ_LE32(pBuf + i);
3528 if (s == record_sig)
3530 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3542 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3545 cur_file_ofs = MZ_MAX(cur_file_ofs - (
sizeof(buf_u32) - 3), 0);
3548 *pOfs = cur_file_ofs;
3552 static mz_bool mz_zip_reader_read_central_dir(
mz_zip_archive *pZip, mz_uint flags)
3554 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3555 mz_uint64 cdir_ofs = 0;
3556 mz_int64 cur_file_ofs = 0;
3559 mz_uint32 buf_u32[4096 /
sizeof(mz_uint32)];
3560 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3561 mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3562 mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
3563 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3565 mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
3566 mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3568 mz_uint64 zip64_end_of_central_dir_ofs = 0;
3571 if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3572 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3574 if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
3575 return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3578 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3579 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3581 if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3582 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3584 if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3586 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
3588 if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3590 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3591 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3592 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3594 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)
3596 if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3598 pZip->m_pState->m_zip64 = MZ_TRUE;
3605 pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3606 cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3607 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3608 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3609 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3610 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3612 if (pZip->m_pState->m_zip64)
3614 mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3615 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3616 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);
3617 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);
3618 mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3620 if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3621 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3623 if (zip64_total_num_of_disks != 1U)
3624 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3627 if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3628 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3630 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3632 if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3633 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3635 cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3638 if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3639 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3641 cdir_size = (mz_uint32)zip64_size_of_central_directory;
3643 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3645 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3647 cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3650 if (pZip->m_total_files != cdir_entries_on_this_disk)
3651 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3653 if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3654 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3656 if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3657 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3659 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3660 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3662 pZip->m_central_directory_file_ofs = cdir_ofs;
3664 if (pZip->m_total_files)
3668 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3669 (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3670 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3672 if (sort_central_dir)
3674 if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3675 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3678 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3679 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3682 p = (
const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3683 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3685 mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3686 mz_uint64 comp_size, decomp_size, local_header_ofs;
3688 if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3689 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3691 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (
const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
3693 if (sort_central_dir)
3694 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3696 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3697 decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3698 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3699 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3700 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3702 if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3704 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3707 mz_uint32 extra_size_remaining = ext_data_size;
3709 if (extra_size_remaining)
3711 const mz_uint8 *pExtra_data;
3714 if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3716 buf = MZ_MALLOC(ext_data_size);
3718 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3720 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size)
3723 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3726 pExtra_data = (mz_uint8*)buf;
3730 pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3736 mz_uint32 field_data_size;
3738 if (extra_size_remaining < (
sizeof(mz_uint16) * 2))
3741 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3744 field_id = MZ_READ_LE16(pExtra_data);
3745 field_data_size = MZ_READ_LE16(pExtra_data +
sizeof(mz_uint16));
3747 if ((field_data_size +
sizeof(mz_uint16) * 2) > extra_size_remaining)
3750 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3753 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3756 pZip->m_pState->m_zip64 = MZ_TRUE;
3757 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3761 pExtra_data +=
sizeof(mz_uint16) * 2 + field_data_size;
3762 extra_size_remaining = extra_size_remaining -
sizeof(mz_uint16) * 2 - field_data_size;
3763 }
while (extra_size_remaining);
3770 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3772 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3773 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3776 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3777 if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3778 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3780 if (comp_size != MZ_UINT32_MAX)
3782 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
3783 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3786 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3787 if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3788 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3790 if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
3791 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3793 n -= total_header_size;
3794 p += total_header_size;
3798 if (sort_central_dir)
3799 mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3807 MZ_CLEAR_OBJ(*pZip);
3810 static mz_bool mz_zip_reader_end_internal(
mz_zip_archive *pZip, mz_bool set_last_error)
3812 mz_bool status = MZ_TRUE;
3817 if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3820 pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3828 pZip->m_pState = NULL;
3830 mz_zip_array_clear(pZip, &pState->m_central_dir);
3831 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3832 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3834 #ifndef MINIZ_NO_STDIO
3835 if (pState->m_pFile)
3837 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3839 if (MZ_FCLOSE(pState->m_pFile) == EOF)
3842 pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
3846 pState->m_pFile = NULL;
3850 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3852 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3859 return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3861 mz_bool mz_zip_reader_init(
mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
3863 if ((!pZip) || (!pZip->m_pRead))
3864 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3866 if (!mz_zip_reader_init_internal(pZip, flags))
3869 pZip->m_zip_type = MZ_ZIP_TYPE_USER;
3870 pZip->m_archive_size = size;
3872 if (!mz_zip_reader_read_central_dir(pZip, flags))
3874 mz_zip_reader_end_internal(pZip, MZ_FALSE);
3881 static size_t mz_zip_mem_read_func(
void *pOpaque, mz_uint64 file_ofs,
void *pBuf,
size_t n)
3884 size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (
size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3885 memcpy(pBuf, (
const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3889 mz_bool mz_zip_reader_init_mem(
mz_zip_archive *pZip,
const void *pMem,
size_t size, mz_uint flags)
3892 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3894 if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3895 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3897 if (!mz_zip_reader_init_internal(pZip, flags))
3900 pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
3901 pZip->m_archive_size = size;
3902 pZip->m_pRead = mz_zip_mem_read_func;
3903 pZip->m_pIO_opaque = pZip;
3904 pZip->m_pNeeds_keepalive = NULL;
3907 pZip->m_pState->m_pMem =
const_cast<void *
>(pMem);
3909 pZip->m_pState->m_pMem = (
void *)pMem;
3912 pZip->m_pState->m_mem_size = size;
3914 if (!mz_zip_reader_read_central_dir(pZip, flags))
3916 mz_zip_reader_end_internal(pZip, MZ_FALSE);
3923 #ifndef MINIZ_NO_STDIO
3924 static size_t mz_zip_file_read_func(
void *pOpaque, mz_uint64 file_ofs,
void *pBuf,
size_t n)
3927 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3929 file_ofs += pZip->m_pState->m_file_archive_start_ofs;
3931 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))))
3934 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3937 mz_bool mz_zip_reader_init_file(
mz_zip_archive *pZip,
const char *pFilename, mz_uint32 flags)
3939 return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
3942 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)
3944 mz_uint64 file_size;
3947 if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3948 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3950 pFile = MZ_FOPEN(pFilename,
"rb");
3952 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
3954 file_size = archive_size;
3957 if (MZ_FSEEK64(pFile, 0, SEEK_END))
3960 return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
3963 file_size = MZ_FTELL64(pFile);
3968 if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3971 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3974 if (!mz_zip_reader_init_internal(pZip, flags))
3980 pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
3981 pZip->m_pRead = mz_zip_file_read_func;
3982 pZip->m_pIO_opaque = pZip;
3983 pZip->m_pState->m_pFile = pFile;
3984 pZip->m_archive_size = file_size;
3985 pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
3987 if (!mz_zip_reader_read_central_dir(pZip, flags))
3989 mz_zip_reader_end_internal(pZip, MZ_FALSE);
3996 mz_bool mz_zip_reader_init_cfile(
mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
3998 mz_uint64 cur_file_ofs;
4000 if ((!pZip) || (!pFile))
4001 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4003 cur_file_ofs = MZ_FTELL64(pFile);
4007 if (MZ_FSEEK64(pFile, 0, SEEK_END))
4008 return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4010 archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4012 if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4013 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4016 if (!mz_zip_reader_init_internal(pZip, flags))
4019 pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
4020 pZip->m_pRead = mz_zip_file_read_func;
4022 pZip->m_pIO_opaque = pZip;
4023 pZip->m_pState->m_pFile = pFile;
4024 pZip->m_archive_size = archive_size;
4025 pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4027 if (!mz_zip_reader_read_central_dir(pZip, flags))
4029 mz_zip_reader_end_internal(pZip, MZ_FALSE);
4038 static MZ_FORCEINLINE
const mz_uint8 *mz_zip_get_cdh(
mz_zip_archive *pZip, mz_uint file_index)
4040 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4042 return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
4045 mz_bool mz_zip_reader_is_file_encrypted(
mz_zip_archive *pZip, mz_uint file_index)
4048 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4051 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4055 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4056 return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
4059 mz_bool mz_zip_reader_is_file_supported(
mz_zip_archive *pZip, mz_uint file_index)
4064 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4067 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4071 method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4072 bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4074 if ((method != 0) && (method != MZ_DEFLATED))
4076 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4080 if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
4082 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4086 if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
4088 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
4095 mz_bool mz_zip_reader_is_file_a_directory(
mz_zip_archive *pZip, mz_uint file_index)
4097 mz_uint filename_len, attribute_mapping_id, external_attr;
4098 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4101 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4105 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4108 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) ==
'/')
4115 attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4116 (void)attribute_mapping_id;
4118 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4119 if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4127 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)
4130 const mz_uint8 *p = pCentral_dir_header;
4132 if (pFound_zip64_extra_data)
4133 *pFound_zip64_extra_data = MZ_FALSE;
4135 if ((!p) || (!pStat))
4136 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4139 pStat->m_file_index = file_index;
4140 pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4141 pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4142 pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4143 pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4144 pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4145 #ifndef MINIZ_NO_TIME
4146 pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
4148 pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4149 pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4150 pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4151 pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4152 pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4153 pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4156 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4157 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4158 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4159 pStat->m_filename[n] =
'\0';
4161 n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4162 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4163 pStat->m_comment_size = n;
4164 memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n);
4165 pStat->m_comment[n] =
'\0';
4168 pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4169 pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4170 pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4174 if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4177 mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4179 if (extra_size_remaining)
4181 const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4186 mz_uint32 field_data_size;
4188 if (extra_size_remaining < (
sizeof(mz_uint16) * 2))
4189 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4191 field_id = MZ_READ_LE16(pExtra_data);
4192 field_data_size = MZ_READ_LE16(pExtra_data +
sizeof(mz_uint16));
4194 if ((field_data_size +
sizeof(mz_uint16) * 2) > extra_size_remaining)
4195 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4197 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4199 const mz_uint8 *pField_data = pExtra_data +
sizeof(mz_uint16) * 2;
4200 mz_uint32 field_data_remaining = field_data_size;
4202 if (pFound_zip64_extra_data)
4203 *pFound_zip64_extra_data = MZ_TRUE;
4205 if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4207 if (field_data_remaining <
sizeof(mz_uint64))
4208 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4210 pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4211 pField_data +=
sizeof(mz_uint64);
4212 field_data_remaining -=
sizeof(mz_uint64);
4215 if (pStat->m_comp_size == MZ_UINT32_MAX)
4217 if (field_data_remaining <
sizeof(mz_uint64))
4218 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4220 pStat->m_comp_size = MZ_READ_LE64(pField_data);
4221 pField_data +=
sizeof(mz_uint64);
4222 field_data_remaining -=
sizeof(mz_uint64);
4225 if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4227 if (field_data_remaining <
sizeof(mz_uint64))
4228 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4230 pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4231 pField_data +=
sizeof(mz_uint64);
4232 field_data_remaining -=
sizeof(mz_uint64);
4238 pExtra_data +=
sizeof(mz_uint16) * 2 + field_data_size;
4239 extra_size_remaining = extra_size_remaining -
sizeof(mz_uint16) * 2 - field_data_size;
4240 }
while (extra_size_remaining);
4247 static MZ_FORCEINLINE mz_bool mz_zip_string_equal(
const char *pA,
const char *pB, mz_uint len, mz_uint flags)
4250 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4251 return 0 == memcmp(pA, pB, len);
4252 for (i = 0; i < len; ++i)
4253 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4258 static MZ_FORCEINLINE
int mz_zip_filename_compare(
const mz_zip_array *pCentral_dir_array,
const mz_zip_array *pCentral_dir_offsets, mz_uint l_index,
const char *pR, mz_uint r_len)
4260 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;
4261 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4262 mz_uint8 l = 0, r = 0;
4263 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4264 pE = pL + MZ_MIN(l_len, r_len);
4267 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4272 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4275 static mz_bool mz_zip_locate_file_binary_search(
mz_zip_archive *pZip,
const char *pFilename, mz_uint32 *pIndex)
4278 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4279 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4280 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4281 const uint32_t size = pZip->m_total_files;
4282 const mz_uint filename_len = (mz_uint)strlen(pFilename);
4291 mz_int64 l = 0, h = (mz_int64)size - 1;
4295 mz_int64 m = l + ((h - l) >> 1);
4296 uint32_t file_index = pIndices[(uint32_t)m];
4298 int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4302 *pIndex = file_index;
4312 return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4315 int mz_zip_reader_locate_file(
mz_zip_archive *pZip,
const char *pName,
const char *pComment, mz_uint flags)
4318 if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4324 mz_bool mz_zip_reader_locate_file_v2(
mz_zip_archive *pZip,
const char *pName,
const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4327 size_t name_len, comment_len;
4332 if ((!pZip) || (!pZip->m_pState) || (!pName))
4333 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4336 if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4337 (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4338 ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4340 return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4344 name_len = strlen(pName);
4345 if (name_len > MZ_UINT16_MAX)
4346 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4348 comment_len = pComment ? strlen(pComment) : 0;
4349 if (comment_len > MZ_UINT16_MAX)
4350 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4352 for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4354 const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
4355 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4356 const char *pFilename = (
const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4357 if (filename_len < name_len)
4361 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);
4362 const char *pFile_comment = pFilename + filename_len + file_extra_len;
4363 if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4366 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4368 int ofs = filename_len - 1;
4371 if ((pFilename[ofs] ==
'/') || (pFilename[ofs] ==
'\\') || (pFilename[ofs] ==
':'))
4373 }
while (--ofs >= 0);
4376 filename_len -= ofs;
4378 if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4381 *pIndex = file_index;
4386 return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4389 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)
4391 int status = TINFL_STATUS_DONE;
4392 mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4395 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
4396 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4399 if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4400 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4402 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4406 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4410 if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4411 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4414 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4415 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4418 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4419 if (buf_size < needed_size)
4420 return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4423 cur_file_ofs = file_stat.m_local_header_ofs;
4424 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)
4425 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4427 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4428 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4430 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4431 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4432 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4434 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4437 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (
size_t)needed_size) != needed_size)
4438 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4440 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4441 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4443 if (mz_crc32(MZ_CRC32_INIT, (
const mz_uint8 *)pBuf, (
size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4444 return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4452 tinfl_init(&inflator);
4454 if (pZip->m_pState->m_pMem)
4457 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4458 read_buf_size = read_buf_avail = file_stat.m_comp_size;
4461 else if (pUser_read_buf)
4464 if (!user_read_buf_size)
4466 pRead_buf = (mz_uint8 *)pUser_read_buf;
4467 read_buf_size = user_read_buf_size;
4469 comp_remaining = file_stat.m_comp_size;
4474 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4475 if (((
sizeof(
size_t) ==
sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4476 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4478 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (
size_t)read_buf_size)))
4479 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4482 comp_remaining = file_stat.m_comp_size;
4488 size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4489 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4491 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4492 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (
size_t)read_buf_avail) != read_buf_avail)
4494 status = TINFL_STATUS_FAILED;
4495 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4498 cur_file_ofs += read_buf_avail;
4499 comp_remaining -= read_buf_avail;
4502 in_buf_size = (size_t)read_buf_avail;
4503 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));
4504 read_buf_avail -= in_buf_size;
4505 read_buf_ofs += in_buf_size;
4506 out_buf_ofs += out_buf_size;
4507 }
while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4509 if (status == TINFL_STATUS_DONE)
4512 if (out_buf_ofs != file_stat.m_uncomp_size)
4514 mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4515 status = TINFL_STATUS_FAILED;
4517 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4518 else if (mz_crc32(MZ_CRC32_INIT, (
const mz_uint8 *)pBuf, (
size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4520 mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4521 status = TINFL_STATUS_FAILED;
4526 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4527 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4529 return status == TINFL_STATUS_DONE;
4532 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)
4534 mz_uint32 file_index;
4535 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4537 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4540 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)
4542 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4545 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)
4547 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4550 void *mz_zip_reader_extract_to_heap(
mz_zip_archive *pZip, mz_uint file_index,
size_t *pSize, mz_uint flags)
4552 mz_uint64 comp_size, uncomp_size, alloc_size;
4553 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4561 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4565 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4566 uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4568 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4569 if (((
sizeof(
size_t) ==
sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4571 mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4575 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (
size_t)alloc_size)))
4577 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4581 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (
size_t)alloc_size, flags))
4583 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4588 *pSize = (size_t)alloc_size;
4592 void *mz_zip_reader_extract_file_to_heap(
mz_zip_archive *pZip,
const char *pFilename,
size_t *pSize, mz_uint flags)
4594 mz_uint32 file_index;
4595 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4601 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4604 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)
4606 int status = TINFL_STATUS_DONE;
4607 mz_uint file_crc32 = MZ_CRC32_INIT;
4608 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4610 void *pRead_buf = NULL;
4611 void *pWrite_buf = NULL;
4612 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
4613 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4615 if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4616 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4618 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4622 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4626 if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4627 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4630 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4631 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4634 cur_file_ofs = file_stat.m_local_header_ofs;
4635 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)
4636 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4638 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4639 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4641 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4642 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4643 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4646 if (pZip->m_pState->m_pMem)
4648 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4649 read_buf_size = read_buf_avail = file_stat.m_comp_size;
4654 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4655 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (
size_t)read_buf_size)))
4656 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4659 comp_remaining = file_stat.m_comp_size;
4662 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4665 if (pZip->m_pState->m_pMem)
4667 if (((
sizeof(
size_t) ==
sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4668 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4670 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (
size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4672 mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4673 status = TINFL_STATUS_FAILED;
4675 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4677 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4678 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (
const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4682 cur_file_ofs += file_stat.m_comp_size;
4683 out_buf_ofs += file_stat.m_comp_size;
4688 while (comp_remaining)
4690 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4691 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (
size_t)read_buf_avail) != read_buf_avail)
4693 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4694 status = TINFL_STATUS_FAILED;
4698 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4699 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4701 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (
const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4705 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (
size_t)read_buf_avail) != read_buf_avail)
4707 mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4708 status = TINFL_STATUS_FAILED;
4712 cur_file_ofs += read_buf_avail;
4713 out_buf_ofs += read_buf_avail;
4714 comp_remaining -= read_buf_avail;
4721 tinfl_init(&inflator);
4723 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4725 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4726 status = TINFL_STATUS_FAILED;
4732 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4733 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4734 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4736 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4737 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (
size_t)read_buf_avail) != read_buf_avail)
4739 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4740 status = TINFL_STATUS_FAILED;
4743 cur_file_ofs += read_buf_avail;
4744 comp_remaining -= read_buf_avail;
4748 in_buf_size = (size_t)read_buf_avail;
4749 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);
4750 read_buf_avail -= in_buf_size;
4751 read_buf_ofs += in_buf_size;
4755 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4757 mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4758 status = TINFL_STATUS_FAILED;
4762 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4763 file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4765 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4767 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4768 status = TINFL_STATUS_FAILED;
4772 }
while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4776 if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4779 if (out_buf_ofs != file_stat.m_uncomp_size)
4781 mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4782 status = TINFL_STATUS_FAILED;
4784 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4785 else if (file_crc32 != file_stat.m_crc32)
4787 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4788 status = TINFL_STATUS_FAILED;
4793 if (!pZip->m_pState->m_pMem)
4794 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4797 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4799 return status == TINFL_STATUS_DONE;
4802 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)
4804 mz_uint32 file_index;
4805 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4808 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4814 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
4815 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4818 if ((!pZip) || (!pZip->m_pState))
4825 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4830 if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4832 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4837 if (pState->file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4839 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4840 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4845 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4847 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4848 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4853 pState->pZip = pZip;
4854 pState->flags = flags;
4857 pState->status = TINFL_STATUS_DONE;
4858 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4859 pState->file_crc32 = MZ_CRC32_INIT;
4861 pState->read_buf_ofs = 0;
4862 pState->out_buf_ofs = 0;
4863 pState->pRead_buf = NULL;
4864 pState->pWrite_buf = NULL;
4865 pState->out_blk_remain = 0;
4868 pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4869 if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4871 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4872 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4876 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4878 mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4879 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4883 pState->cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4884 if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
4886 mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4887 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4892 if (pZip->m_pState->m_pMem)
4894 pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
4895 pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
4896 pState->comp_remaining = pState->file_stat.m_comp_size;
4900 if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4903 pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
4904 if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (
size_t)pState->read_buf_size)))
4906 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4907 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4914 pState->read_buf_size = 0;
4916 pState->read_buf_avail = 0;
4917 pState->comp_remaining = pState->file_stat.m_comp_size;
4920 if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4923 tinfl_init( &pState->inflator );
4926 if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4928 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4929 if (pState->pRead_buf)
4930 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
4931 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4941 mz_uint32 file_index;
4944 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4948 return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
4953 size_t copied_to_caller = 0;
4956 if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
4959 if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
4962 copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
4965 if (pState->pZip->m_pState->m_pMem)
4968 memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
4969 pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
4974 if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
4977 mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
4978 pState->status = TINFL_STATUS_FAILED;
4979 copied_to_caller = 0;
4983 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4985 if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4986 pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (
const mz_uint8 *)pvBuf, copied_to_caller);
4990 pState->cur_file_ofs += copied_to_caller;
4991 pState->out_buf_ofs += copied_to_caller;
4992 pState->comp_remaining -= copied_to_caller;
4999 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5002 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5004 if (!pState->out_blk_remain)
5007 if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5010 pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5011 if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (
size_t)pState->read_buf_avail) != pState->read_buf_avail)
5013 mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5014 pState->status = TINFL_STATUS_FAILED;
5019 pState->cur_file_ofs += pState->read_buf_avail;
5020 pState->comp_remaining -= pState->read_buf_avail;
5021 pState->read_buf_ofs = 0;
5025 in_buf_size = (size_t)pState->read_buf_avail;
5026 pState->status = tinfl_decompress(&pState->inflator, (
const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5027 pState->read_buf_avail -= in_buf_size;
5028 pState->read_buf_ofs += in_buf_size;
5031 pState->out_blk_remain = out_buf_size;
5034 if (pState->out_blk_remain)
5037 size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
5040 memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
5042 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5044 pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5048 pState->out_blk_remain -= to_copy;
5051 if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5053 mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5054 pState->status = TINFL_STATUS_FAILED;
5059 copied_to_caller += to_copy;
5061 }
while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
5065 return copied_to_caller;
5073 if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5077 if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5080 if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5082 mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
5083 pState->status = TINFL_STATUS_FAILED;
5085 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5086 else if (pState->file_crc32 != pState->file_stat.m_crc32)
5088 mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5089 pState->status = TINFL_STATUS_FAILED;
5095 if (!pState->pZip->m_pState->m_pMem)
5096 pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5097 if (pState->pWrite_buf)
5098 pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5101 status = pState->status;
5104 pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5106 return status == TINFL_STATUS_DONE;
5109 #ifndef MINIZ_NO_STDIO
5110 static size_t mz_zip_file_write_callback(
void *pOpaque, mz_uint64 ofs,
const void *pBuf,
size_t n)
5114 return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5117 mz_bool mz_zip_reader_extract_to_file(
mz_zip_archive *pZip, mz_uint file_index,
const char *pDst_filename, mz_uint flags)
5123 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5126 if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5127 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5129 pFile = MZ_FOPEN(pDst_filename,
"wb");
5131 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5133 status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5135 if (MZ_FCLOSE(pFile) == EOF)
5138 mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5143 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5145 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5151 mz_bool mz_zip_reader_extract_file_to_file(
mz_zip_archive *pZip,
const char *pArchive_filename,
const char *pDst_filename, mz_uint flags)
5153 mz_uint32 file_index;
5154 if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5157 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5160 mz_bool mz_zip_reader_extract_to_cfile(
mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
5164 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5167 if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5168 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5170 return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5173 mz_bool mz_zip_reader_extract_file_to_cfile(
mz_zip_archive *pZip,
const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5175 mz_uint32 file_index;
5176 if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5179 return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5183 static size_t mz_zip_compute_crc32_callback(
void *pOpaque, mz_uint64 file_ofs,
const void *pBuf,
size_t n)
5185 mz_uint32 *p = (mz_uint32 *)pOpaque;
5187 *p = (mz_uint32)mz_crc32(*p, (
const mz_uint8 *)pBuf, n);
5191 mz_bool mz_zip_validate_file(
mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5195 const mz_uint8 *pCentral_dir_header;
5196 mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5197 mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5198 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
5199 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5200 mz_uint64 local_header_ofs = 0;
5201 mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5202 mz_uint64 local_header_comp_size, local_header_uncomp_size;
5203 mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5204 mz_bool has_data_descriptor;
5205 mz_uint32 local_header_bit_flags;
5208 mz_zip_array_init(&file_data_array, 1);
5210 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5211 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5213 if (file_index > pZip->m_total_files)
5214 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5216 pState = pZip->m_pState;
5218 pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5220 if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5224 if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5228 if (file_stat.m_is_encrypted)
5229 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5232 if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5233 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5235 if (!file_stat.m_is_supported)
5236 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5239 local_header_ofs = file_stat.m_local_header_ofs;
5240 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)
5241 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5243 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5244 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5246 local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5247 local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5248 local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5249 local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5250 local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5251 local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5252 has_data_descriptor = (local_header_bit_flags & 8) != 0;
5254 if (local_header_filename_len != strlen(file_stat.m_filename))
5255 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5257 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)
5258 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5260 if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5261 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5263 if (local_header_filename_len)
5265 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)
5267 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5268 goto handle_failure;
5272 if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5274 mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5275 goto handle_failure;
5279 if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5281 mz_uint32 extra_size_remaining = local_header_extra_len;
5282 const mz_uint8 *pExtra_data = (
const mz_uint8 *)file_data_array.m_p;
5284 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)
5286 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5287 goto handle_failure;
5292 mz_uint32 field_id, field_data_size, field_total_size;
5294 if (extra_size_remaining < (
sizeof(mz_uint16) * 2))
5295 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5297 field_id = MZ_READ_LE16(pExtra_data);
5298 field_data_size = MZ_READ_LE16(pExtra_data +
sizeof(mz_uint16));
5299 field_total_size = field_data_size +
sizeof(mz_uint16) * 2;
5301 if (field_total_size > extra_size_remaining)
5302 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5304 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5306 const mz_uint8 *pSrc_field_data = pExtra_data +
sizeof(mz_uint32);
5308 if (field_data_size <
sizeof(mz_uint64) * 2)
5310 mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5311 goto handle_failure;
5314 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5315 local_header_comp_size = MZ_READ_LE64(pSrc_field_data +
sizeof(mz_uint64));
5317 found_zip64_ext_data_in_ldir = MZ_TRUE;
5321 pExtra_data += field_total_size;
5322 extra_size_remaining -= field_total_size;
5323 }
while (extra_size_remaining);
5328 if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5330 mz_uint8 descriptor_buf[32];
5332 const mz_uint8 *pSrc;
5333 mz_uint32 file_crc32;
5334 mz_uint64 comp_size = 0, uncomp_size = 0;
5336 mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5338 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))
5340 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5341 goto handle_failure;
5344 has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5345 pSrc = has_id ? (descriptor_buf +
sizeof(mz_uint32)) : descriptor_buf;
5347 file_crc32 = MZ_READ_LE32(pSrc);
5349 if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5351 comp_size = MZ_READ_LE64(pSrc +
sizeof(mz_uint32));
5352 uncomp_size = MZ_READ_LE64(pSrc +
sizeof(mz_uint32) +
sizeof(mz_uint64));
5356 comp_size = MZ_READ_LE32(pSrc +
sizeof(mz_uint32));
5357 uncomp_size = MZ_READ_LE32(pSrc +
sizeof(mz_uint32) +
sizeof(mz_uint32));
5360 if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5362 mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5363 goto handle_failure;
5368 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))
5370 mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5371 goto handle_failure;
5375 mz_zip_array_clear(pZip, &file_data_array);
5377 if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5379 if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5383 if (uncomp_crc32 != file_stat.m_crc32)
5385 mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5393 mz_zip_array_clear(pZip, &file_data_array);
5397 mz_bool mz_zip_validate_archive(
mz_zip_archive *pZip, mz_uint flags)
5402 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5403 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5405 pState = pZip->m_pState;
5408 if (!pState->m_zip64)
5410 if (pZip->m_total_files > MZ_UINT16_MAX)
5411 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5413 if (pZip->m_archive_size > MZ_UINT32_MAX)
5414 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5418 if (pZip->m_total_files >= MZ_UINT32_MAX)
5419 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5421 if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5422 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5425 for (i = 0; i < pZip->m_total_files; i++)
5427 if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5429 mz_uint32 found_index;
5432 if (!mz_zip_reader_file_stat(pZip, i, &stat))
5435 if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5439 if (found_index != i)
5440 return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5443 if (!mz_zip_validate_file(pZip, i, flags))
5450 mz_bool mz_zip_validate_mem_archive(
const void *pMem,
size_t size, mz_uint flags, mz_zip_error *pErr)
5452 mz_bool success = MZ_TRUE;
5454 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5456 if ((!pMem) || (!size))
5459 *pErr = MZ_ZIP_INVALID_PARAMETER;
5463 mz_zip_zero_struct(&zip);
5465 if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5468 *pErr = zip.m_last_error;
5472 if (!mz_zip_validate_archive(&zip, flags))
5474 actual_err = zip.m_last_error;
5478 if (!mz_zip_reader_end_internal(&zip, success))
5481 actual_err = zip.m_last_error;
5491 #ifndef MINIZ_NO_STDIO
5492 mz_bool mz_zip_validate_file_archive(
const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5494 mz_bool success = MZ_TRUE;
5496 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5501 *pErr = MZ_ZIP_INVALID_PARAMETER;
5505 mz_zip_zero_struct(&zip);
5507 if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5510 *pErr = zip.m_last_error;
5514 if (!mz_zip_validate_archive(&zip, flags))
5516 actual_err = zip.m_last_error;
5520 if (!mz_zip_reader_end_internal(&zip, success))
5523 actual_err = zip.m_last_error;
5536 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5538 static MZ_FORCEINLINE
void mz_write_le16(mz_uint8 *p, mz_uint16 v)
5541 p[1] = (mz_uint8)(v >> 8);
5543 static MZ_FORCEINLINE
void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5546 p[1] = (mz_uint8)(v >> 8);
5547 p[2] = (mz_uint8)(v >> 16);
5548 p[3] = (mz_uint8)(v >> 24);
5550 static MZ_FORCEINLINE
void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5552 mz_write_le32(p, (mz_uint32)v);
5553 mz_write_le32(p +
sizeof(mz_uint32), (mz_uint32)(v >> 32));
5556 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5557 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5558 #define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5560 static size_t mz_zip_heap_write_func(
void *pOpaque, mz_uint64 file_ofs,
const void *pBuf,
size_t n)
5564 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5570 if ((
sizeof(
size_t) ==
sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5572 mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5576 if (new_size > pState->m_mem_capacity)
5579 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5581 while (new_capacity < new_size)
5584 if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5586 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5590 pState->m_pMem = pNew_block;
5591 pState->m_mem_capacity = new_capacity;
5593 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5594 pState->m_mem_size = (size_t)new_size;
5598 static mz_bool mz_zip_writer_end_internal(
mz_zip_archive *pZip, mz_bool set_last_error)
5601 mz_bool status = MZ_TRUE;
5603 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)))
5606 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5610 pState = pZip->m_pState;
5611 pZip->m_pState = NULL;
5612 mz_zip_array_clear(pZip, &pState->m_central_dir);
5613 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5614 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5616 #ifndef MINIZ_NO_STDIO
5617 if (pState->m_pFile)
5619 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5621 if (MZ_FCLOSE(pState->m_pFile) == EOF)
5624 mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5629 pState->m_pFile = NULL;
5633 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5635 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5636 pState->m_pMem = NULL;
5639 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5640 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5644 mz_bool mz_zip_writer_init_v2(
mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5646 mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5648 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5649 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5651 if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5654 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5657 if (pZip->m_file_offset_alignment)
5660 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5661 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5664 if (!pZip->m_pAlloc)
5665 pZip->m_pAlloc = miniz_def_alloc_func;
5667 pZip->m_pFree = miniz_def_free_func;
5668 if (!pZip->m_pRealloc)
5669 pZip->m_pRealloc = miniz_def_realloc_func;
5671 pZip->m_archive_size = existing_size;
5672 pZip->m_central_directory_file_ofs = 0;
5673 pZip->m_total_files = 0;
5676 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5680 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
sizeof(mz_uint8));
5681 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
sizeof(mz_uint32));
5682 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
sizeof(mz_uint32));
5684 pZip->m_pState->m_zip64 = zip64;
5685 pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5687 pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5688 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5693 mz_bool mz_zip_writer_init(
mz_zip_archive *pZip, mz_uint64 existing_size)
5695 return mz_zip_writer_init_v2(pZip, existing_size, 0);
5698 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)
5700 pZip->m_pWrite = mz_zip_heap_write_func;
5701 pZip->m_pNeeds_keepalive = NULL;
5703 if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5704 pZip->m_pRead = mz_zip_mem_read_func;
5706 pZip->m_pIO_opaque = pZip;
5708 if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5711 pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5713 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5715 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5717 mz_zip_writer_end_internal(pZip, MZ_FALSE);
5718 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5720 pZip->m_pState->m_mem_capacity = initial_allocation_size;
5726 mz_bool mz_zip_writer_init_heap(
mz_zip_archive *pZip,
size_t size_to_reserve_at_beginning,
size_t initial_allocation_size)
5728 return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5731 #ifndef MINIZ_NO_STDIO
5732 static size_t mz_zip_file_write_func(
void *pOpaque, mz_uint64 file_ofs,
const void *pBuf,
size_t n)
5735 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5737 file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5739 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))))
5741 mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5745 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5748 mz_bool mz_zip_writer_init_file(
mz_zip_archive *pZip,
const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5750 return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5753 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)
5757 pZip->m_pWrite = mz_zip_file_write_func;
5758 pZip->m_pNeeds_keepalive = NULL;
5760 if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5761 pZip->m_pRead = mz_zip_file_read_func;
5763 pZip->m_pIO_opaque = pZip;
5765 if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5768 if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ?
"w+b" :
"wb")))
5770 mz_zip_writer_end(pZip);
5771 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5774 pZip->m_pState->m_pFile = pFile;
5775 pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5777 if (size_to_reserve_at_beginning)
5779 mz_uint64 cur_ofs = 0;
5786 size_t n = (size_t)MZ_MIN(
sizeof(buf), size_to_reserve_at_beginning);
5787 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5789 mz_zip_writer_end(pZip);
5790 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5793 size_to_reserve_at_beginning -= n;
5794 }
while (size_to_reserve_at_beginning);
5800 mz_bool mz_zip_writer_init_cfile(
mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5802 pZip->m_pWrite = mz_zip_file_write_func;
5803 pZip->m_pNeeds_keepalive = NULL;
5805 if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5806 pZip->m_pRead = mz_zip_file_read_func;
5808 pZip->m_pIO_opaque = pZip;
5810 if (!mz_zip_writer_init_v2(pZip, 0, flags))
5813 pZip->m_pState->m_pFile = pFile;
5814 pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5815 pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5821 mz_bool mz_zip_writer_init_from_reader_v2(
mz_zip_archive *pZip,
const char *pFilename, mz_uint flags)
5825 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5826 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5828 if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5831 if (!pZip->m_pState->m_zip64)
5832 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5836 if (pZip->m_pState->m_zip64)
5838 if (pZip->m_total_files == MZ_UINT32_MAX)
5839 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5843 if (pZip->m_total_files == MZ_UINT16_MAX)
5844 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5846 if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
5847 return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5850 pState = pZip->m_pState;
5852 if (pState->m_pFile)
5854 #ifdef MINIZ_NO_STDIO
5856 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5858 if (pZip->m_pIO_opaque != pZip)
5859 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5861 if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5864 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5867 if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename,
"r+b", pState->m_pFile)))
5870 mz_zip_reader_end_internal(pZip, MZ_FALSE);
5871 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5875 pZip->m_pWrite = mz_zip_file_write_func;
5876 pZip->m_pNeeds_keepalive = NULL;
5879 else if (pState->m_pMem)
5882 if (pZip->m_pIO_opaque != pZip)
5883 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5885 pState->m_mem_capacity = pState->m_mem_size;
5886 pZip->m_pWrite = mz_zip_heap_write_func;
5887 pZip->m_pNeeds_keepalive = NULL;
5890 else if (!pZip->m_pWrite)
5891 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5895 pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5896 pZip->m_central_directory_file_ofs = 0;
5901 mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
5903 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5908 mz_bool mz_zip_writer_init_from_reader(
mz_zip_archive *pZip,
const char *pFilename)
5910 return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
5914 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)
5916 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
5922 mz_uint64 m_cur_archive_file_ofs;
5923 mz_uint64 m_comp_size;
5926 static mz_bool mz_zip_writer_add_put_buf_callback(
const void *pBuf,
int len,
void *pUser)
5929 if ((
int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
5932 pState->m_cur_archive_file_ofs += len;
5933 pState->m_comp_size += len;
5937 #define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
5938 #define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
5939 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)
5941 mz_uint8 *pDst = pBuf;
5942 mz_uint32 field_size = 0;
5944 MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
5945 MZ_WRITE_LE16(pDst + 2, 0);
5946 pDst +=
sizeof(mz_uint16) * 2;
5950 MZ_WRITE_LE64(pDst, *pUncomp_size);
5951 pDst +=
sizeof(mz_uint64);
5952 field_size +=
sizeof(mz_uint64);
5957 MZ_WRITE_LE64(pDst, *pComp_size);
5958 pDst +=
sizeof(mz_uint64);
5959 field_size +=
sizeof(mz_uint64);
5962 if (pLocal_header_ofs)
5964 MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
5965 pDst +=
sizeof(mz_uint64);
5966 field_size +=
sizeof(mz_uint64);
5969 MZ_WRITE_LE16(pBuf + 2, field_size);
5971 return (mz_uint32)(pDst - pBuf);
5974 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)
5977 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5978 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5979 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5980 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5981 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5982 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5983 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5984 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5985 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
5986 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
5987 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
5988 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
5992 static mz_bool mz_zip_writer_create_central_dir_header(
mz_zip_archive *pZip, mz_uint8 *pDst,
5993 mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
5994 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
5995 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
5996 mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
5999 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6000 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6001 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6002 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6003 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6004 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6005 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6006 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6007 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6008 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6009 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6010 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6011 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6012 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6013 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
6017 static mz_bool mz_zip_writer_add_to_central_dir(
mz_zip_archive *pZip,
const char *pFilename, mz_uint16 filename_size,
6018 const void *pExtra, mz_uint16 extra_size,
const void *pComment, mz_uint16 comment_size,
6019 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6020 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6021 mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
6022 const char *user_extra_data, mz_uint user_extra_data_len)
6025 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6026 size_t orig_central_dir_size = pState->m_central_dir.m_size;
6027 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6029 if (!pZip->m_pState->m_zip64)
6031 if (local_header_ofs > 0xFFFFFFFF)
6032 return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6036 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)
6037 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6039 if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(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))
6040 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6042 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6043 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6044 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6045 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6046 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6047 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1)))
6050 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6051 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6057 static mz_bool mz_zip_writer_validate_archive_name(
const char *pArchive_name)
6060 if (*pArchive_name ==
'/')
6068 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(
mz_zip_archive *pZip)
6071 if (!pZip->m_file_offset_alignment)
6073 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6074 return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6077 static mz_bool mz_zip_writer_write_zeros(
mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
6080 memset(buf, 0, MZ_MIN(
sizeof(buf), n));
6083 mz_uint32 s = MZ_MIN(
sizeof(buf), n);
6084 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6085 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6093 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,
6094 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6096 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);
6099 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,
6100 mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6101 const char *user_extra_data, mz_uint user_extra_data_len,
const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6103 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6104 mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6105 mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6106 size_t archive_name_size;
6107 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6109 mz_bool store_data_uncompressed;
6111 mz_uint8 *pExtra_data = NULL;
6112 mz_uint32 extra_size = 0;
6113 mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6114 mz_uint16 bit_flags = 0;
6116 if ((
int)level_and_flags < 0)
6117 level_and_flags = MZ_DEFAULT_LEVEL;
6119 if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6120 bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6122 if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6123 bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6125 level = level_and_flags & 0xF;
6126 store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6128 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))
6129 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6131 pState = pZip->m_pState;
6133 if (pState->m_zip64)
6135 if (pZip->m_total_files == MZ_UINT32_MAX)
6136 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6140 if (pZip->m_total_files == MZ_UINT16_MAX)
6142 pState->m_zip64 = MZ_TRUE;
6145 if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6147 pState->m_zip64 = MZ_TRUE;
6152 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6153 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6155 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6156 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6158 #ifndef MINIZ_NO_TIME
6159 if (last_modified != NULL)
6161 mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6167 mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6171 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6173 uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (
const mz_uint8 *)pBuf, buf_size);
6174 uncomp_size = buf_size;
6175 if (uncomp_size <= 3)
6178 store_data_uncompressed = MZ_TRUE;
6182 archive_name_size = strlen(pArchive_name);
6183 if (archive_name_size > MZ_UINT16_MAX)
6184 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6186 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6189 if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6190 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6192 if (!pState->m_zip64)
6195 if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6196 + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6197 pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6198 + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6200 pState->m_zip64 = MZ_TRUE;
6205 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] ==
'/'))
6208 ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6211 if ((buf_size) || (uncomp_size))
6212 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6216 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)))
6217 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6219 if ((!store_data_uncompressed) && (buf_size))
6222 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6225 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6227 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6231 local_dir_header_ofs += num_alignment_padding_bytes;
6232 if (pZip->m_file_offset_alignment)
6234 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6236 cur_archive_file_ofs += num_alignment_padding_bytes;
6238 MZ_CLEAR_OBJ(local_dir_header);
6240 if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6242 method = MZ_DEFLATED;
6245 if (pState->m_zip64)
6247 if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6249 pExtra_data = extra_data;
6250 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6251 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6254 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date))
6255 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6257 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
sizeof(local_dir_header)) !=
sizeof(local_dir_header))
6258 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6260 cur_archive_file_ofs +=
sizeof(local_dir_header);
6262 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6264 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6265 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6267 cur_archive_file_ofs += archive_name_size;
6269 if (pExtra_data != NULL)
6271 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6272 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6274 cur_archive_file_ofs += extra_size;
6279 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6280 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6281 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
6282 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6284 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
sizeof(local_dir_header)) !=
sizeof(local_dir_header))
6285 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6287 cur_archive_file_ofs +=
sizeof(local_dir_header);
6289 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6291 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6292 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6294 cur_archive_file_ofs += archive_name_size;
6297 if (user_extra_data_len > 0)
6299 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6300 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6302 cur_archive_file_ofs += user_extra_data_len;
6305 if (store_data_uncompressed)
6307 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6309 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6310 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6313 cur_archive_file_ofs += buf_size;
6314 comp_size = buf_size;
6320 state.m_pZip = pZip;
6321 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6322 state.m_comp_size = 0;
6324 if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
6325 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6327 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6328 return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6331 comp_size = state.m_comp_size;
6332 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6335 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6340 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6341 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6343 MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6345 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6346 MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6347 if (pExtra_data == NULL)
6349 if (comp_size > MZ_UINT32_MAX)
6350 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6352 MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6353 MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6357 MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6358 MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6359 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6362 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6365 cur_archive_file_ofs += local_dir_footer_size;
6368 if (pExtra_data != NULL)
6370 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6371 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6374 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6375 comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6376 user_extra_data_central, user_extra_data_central_len))
6379 pZip->m_total_files++;
6380 pZip->m_archive_size = cur_archive_file_ofs;
6385 mz_bool mz_zip_writer_add_read_buf_callback(
mz_zip_archive *pZip,
const char *pArchive_name, mz_file_read_func read_callback,
void* callback_opaque, mz_uint64 size_to_add,
const MZ_TIME_T *pFile_time,
const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6386 const char *user_extra_data, mz_uint user_extra_data_len,
const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6388 mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6389 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6390 mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6391 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
6392 size_t archive_name_size;
6393 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6394 mz_uint8 *pExtra_data = NULL;
6395 mz_uint32 extra_size = 0;
6396 mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6398 mz_uint64 file_ofs = 0;
6400 if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6401 gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6403 if ((
int)level_and_flags < 0)
6404 level_and_flags = MZ_DEFAULT_LEVEL;
6405 level = level_and_flags & 0xF;
6408 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6409 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6411 pState = pZip->m_pState;
6413 if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6417 pState->m_zip64 = MZ_TRUE;
6421 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6422 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6424 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6425 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6427 if (pState->m_zip64)
6429 if (pZip->m_total_files == MZ_UINT32_MAX)
6430 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6434 if (pZip->m_total_files == MZ_UINT16_MAX)
6436 pState->m_zip64 = MZ_TRUE;
6441 archive_name_size = strlen(pArchive_name);
6442 if (archive_name_size > MZ_UINT16_MAX)
6443 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6445 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6448 if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6449 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6451 if (!pState->m_zip64)
6454 if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6455 + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6456 + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6458 pState->m_zip64 = MZ_TRUE;
6463 #ifndef MINIZ_NO_TIME
6466 mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6470 if (uncomp_size <= 3)
6473 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6475 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6478 cur_archive_file_ofs += num_alignment_padding_bytes;
6479 local_dir_header_ofs = cur_archive_file_ofs;
6481 if (pZip->m_file_offset_alignment)
6483 MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6486 if (uncomp_size && level)
6488 method = MZ_DEFLATED;
6491 MZ_CLEAR_OBJ(local_dir_header);
6492 if (pState->m_zip64)
6494 if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6496 pExtra_data = extra_data;
6497 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6498 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6501 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date))
6502 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6504 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header,
sizeof(local_dir_header)) !=
sizeof(local_dir_header))
6505 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6507 cur_archive_file_ofs +=
sizeof(local_dir_header);
6509 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6511 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6514 cur_archive_file_ofs += archive_name_size;
6516 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6517 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6519 cur_archive_file_ofs += extra_size;
6523 if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6524 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6525 if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6526 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6528 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header,
sizeof(local_dir_header)) !=
sizeof(local_dir_header))
6529 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6531 cur_archive_file_ofs +=
sizeof(local_dir_header);
6533 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6535 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6538 cur_archive_file_ofs += archive_name_size;
6541 if (user_extra_data_len > 0)
6543 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6544 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6546 cur_archive_file_ofs += user_extra_data_len;
6551 mz_uint64 uncomp_remaining = uncomp_size;
6552 void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6555 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6560 while (uncomp_remaining)
6562 mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6563 if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
6565 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6566 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6569 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (
const mz_uint8 *)pRead_buf, n);
6570 uncomp_remaining -= n;
6571 cur_archive_file_ofs += n;
6573 comp_size = uncomp_size;
6577 mz_bool result = MZ_FALSE;
6582 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6583 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6586 state.m_pZip = pZip;
6587 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6588 state.m_comp_size = 0;
6590 if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
6592 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6593 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6594 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6599 size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6600 tdefl_status status;
6601 tdefl_flush flush = TDEFL_NO_FLUSH;
6603 if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size)
6605 mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6609 file_ofs += in_buf_size;
6610 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (
const mz_uint8 *)pRead_buf, in_buf_size);
6611 uncomp_remaining -= in_buf_size;
6613 if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6614 flush = TDEFL_FULL_FLUSH;
6616 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6617 if (status == TDEFL_STATUS_DONE)
6622 else if (status != TDEFL_STATUS_OKAY)
6624 mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6629 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6633 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6637 comp_size = state.m_comp_size;
6638 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6641 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6645 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6646 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6648 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6649 MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6650 if (pExtra_data == NULL)
6652 if (comp_size > MZ_UINT32_MAX)
6653 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6655 MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6656 MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6660 MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6661 MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6662 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6665 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6668 cur_archive_file_ofs += local_dir_footer_size;
6671 if (pExtra_data != NULL)
6673 extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6674 (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6677 if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size,
6678 uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6679 user_extra_data_central, user_extra_data_central_len))
6682 pZip->m_total_files++;
6683 pZip->m_archive_size = cur_archive_file_ofs;
6688 #ifndef MINIZ_NO_STDIO
6690 static size_t mz_file_read_func_stdio(
void *pOpaque, mz_uint64 file_ofs,
void *pBuf,
size_t n)
6692 MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6693 mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6695 if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6698 return MZ_FREAD(pBuf, 1, n, pSrc_file);
6701 mz_bool mz_zip_writer_add_cfile(
mz_zip_archive *pZip,
const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add,
const MZ_TIME_T *pFile_time,
const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6702 const char *user_extra_data, mz_uint user_extra_data_len,
const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6704 return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, size_to_add, pFile_time, pComment, comment_size, level_and_flags,
6705 user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6708 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)
6710 MZ_FILE *pSrc_file = NULL;
6711 mz_uint64 uncomp_size = 0;
6712 MZ_TIME_T file_modified_time;
6713 MZ_TIME_T *pFile_time = NULL;
6716 memset(&file_modified_time, 0,
sizeof(file_modified_time));
6718 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6719 pFile_time = &file_modified_time;
6720 if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6721 return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6724 pSrc_file = MZ_FOPEN(pSrc_filename,
"rb");
6726 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6728 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6729 uncomp_size = MZ_FTELL64(pSrc_file);
6730 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6732 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);
6734 MZ_FCLOSE(pSrc_file);
6740 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)
6743 if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6744 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6746 mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6748 if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6750 mz_uint8 new_ext_block[64];
6751 mz_uint8 *pDst = new_ext_block;
6752 mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6753 mz_write_le16(pDst +
sizeof(mz_uint16), 0);
6754 pDst +=
sizeof(mz_uint16) * 2;
6758 mz_write_le64(pDst, *pUncomp_size);
6759 pDst +=
sizeof(mz_uint64);
6764 mz_write_le64(pDst, *pComp_size);
6765 pDst +=
sizeof(mz_uint64);
6768 if (pLocal_header_ofs)
6770 mz_write_le64(pDst, *pLocal_header_ofs);
6771 pDst +=
sizeof(mz_uint64);
6776 mz_write_le32(pDst, *pDisk_start);
6777 pDst +=
sizeof(mz_uint32);
6780 mz_write_le16(new_ext_block +
sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) -
sizeof(mz_uint16) * 2));
6782 if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6783 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6786 if ((pExt) && (ext_len))
6788 mz_uint32 extra_size_remaining = ext_len;
6789 const mz_uint8 *pExtra_data = pExt;
6793 mz_uint32 field_id, field_data_size, field_total_size;
6795 if (extra_size_remaining < (
sizeof(mz_uint16) * 2))
6796 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6798 field_id = MZ_READ_LE16(pExtra_data);
6799 field_data_size = MZ_READ_LE16(pExtra_data +
sizeof(mz_uint16));
6800 field_total_size = field_data_size +
sizeof(mz_uint16) * 2;
6802 if (field_total_size > extra_size_remaining)
6803 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6805 if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6807 if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6808 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6811 pExtra_data += field_total_size;
6812 extra_size_remaining -= field_total_size;
6813 }
while (extra_size_remaining);
6822 mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6823 mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6824 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6825 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
sizeof(mz_uint32) - 1) /
sizeof(mz_uint32)];
6826 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6827 mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6828 size_t orig_central_dir_size;
6831 const mz_uint8 *pSrc_central_header;
6833 mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6834 mz_uint32 local_header_filename_size, local_header_extra_len;
6835 mz_uint64 local_header_comp_size, local_header_uncomp_size;
6836 mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6839 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6840 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6842 pState = pZip->m_pState;
6845 if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6846 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6849 if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
6850 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6852 if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
6853 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6855 src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6856 src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6857 src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
6858 src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
6861 if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
6862 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6864 num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6866 if (!pState->m_zip64)
6868 if (pZip->m_total_files == MZ_UINT16_MAX)
6869 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6874 if (pZip->m_total_files == MZ_UINT32_MAX)
6875 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6878 if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
6881 cur_src_file_ofs = src_file_stat.m_local_header_ofs;
6882 cur_dst_file_ofs = pZip->m_archive_size;
6885 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)
6886 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6888 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6889 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6891 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6894 local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
6895 local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6896 local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
6897 local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
6898 src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
6901 if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
6904 const mz_uint8 *pExtra_data;
6905 mz_uint32 extra_size_remaining = local_header_extra_len;
6907 mz_zip_array_init(&file_data_array, 1);
6908 if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
6910 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6913 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)
6915 mz_zip_array_clear(pZip, &file_data_array);
6916 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6919 pExtra_data = (
const mz_uint8 *)file_data_array.m_p;
6923 mz_uint32 field_id, field_data_size, field_total_size;
6925 if (extra_size_remaining < (
sizeof(mz_uint16) * 2))
6927 mz_zip_array_clear(pZip, &file_data_array);
6928 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6931 field_id = MZ_READ_LE16(pExtra_data);
6932 field_data_size = MZ_READ_LE16(pExtra_data +
sizeof(mz_uint16));
6933 field_total_size = field_data_size +
sizeof(mz_uint16) * 2;
6935 if (field_total_size > extra_size_remaining)
6937 mz_zip_array_clear(pZip, &file_data_array);
6938 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6941 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6943 const mz_uint8 *pSrc_field_data = pExtra_data +
sizeof(mz_uint32);
6945 if (field_data_size <
sizeof(mz_uint64) * 2)
6947 mz_zip_array_clear(pZip, &file_data_array);
6948 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6951 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
6952 local_header_comp_size = MZ_READ_LE64(pSrc_field_data +
sizeof(mz_uint64));
6954 found_zip64_ext_data_in_ldir = MZ_TRUE;
6958 pExtra_data += field_total_size;
6959 extra_size_remaining -= field_total_size;
6960 }
while (extra_size_remaining);
6962 mz_zip_array_clear(pZip, &file_data_array);
6965 if (!pState->m_zip64)
6969 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) +
6970 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;
6972 if (approx_new_archive_size >= MZ_UINT32_MAX)
6973 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6977 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
6980 cur_dst_file_ofs += num_alignment_padding_bytes;
6982 local_dir_header_ofs = cur_dst_file_ofs;
6983 if (pZip->m_file_offset_alignment)
6985 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6989 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)
6990 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6992 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6995 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)))))
6996 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6998 while (src_archive_bytes_remaining)
7000 n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7001 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7003 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7004 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7006 cur_src_file_ofs += n;
7008 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7010 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7011 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7013 cur_dst_file_ofs += n;
7015 src_archive_bytes_remaining -= n;
7019 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7023 if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7032 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (
sizeof(mz_uint32) * 6)) != (
sizeof(mz_uint32) * 6))
7034 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7035 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7038 n =
sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7045 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
sizeof(mz_uint32) * 4) !=
sizeof(mz_uint32) * 4)
7047 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7048 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7051 has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7053 if (pZip->m_pState->m_zip64)
7056 const mz_uint32 *pSrc_descriptor = (
const mz_uint32 *)((
const mz_uint8 *)pBuf + (has_id ?
sizeof(mz_uint32) : 0));
7057 const mz_uint32 src_crc32 = pSrc_descriptor[0];
7058 const mz_uint64 src_comp_size = pSrc_descriptor[1];
7059 const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
7061 mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
7062 mz_write_le32((mz_uint8 *)pBuf +
sizeof(mz_uint32) * 1, src_crc32);
7063 mz_write_le64((mz_uint8 *)pBuf +
sizeof(mz_uint32) * 2, src_comp_size);
7064 mz_write_le64((mz_uint8 *)pBuf +
sizeof(mz_uint32) * 4, src_uncomp_size);
7066 n =
sizeof(mz_uint32) * 6;
7071 n =
sizeof(mz_uint32) * (has_id ? 4 : 3);
7075 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7077 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7078 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7081 cur_src_file_ofs += n;
7082 cur_dst_file_ofs += n;
7084 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7087 orig_central_dir_size = pState->m_central_dir.m_size;
7089 memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7091 if (pState->m_zip64)
7094 const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7097 mz_zip_array_init(&new_ext_block,
sizeof(mz_uint8));
7099 MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7100 MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7101 MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
7103 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))
7105 mz_zip_array_clear(pZip, &new_ext_block);
7109 MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7111 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7113 mz_zip_array_clear(pZip, &new_ext_block);
7114 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7117 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7119 mz_zip_array_clear(pZip, &new_ext_block);
7120 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7121 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7124 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7126 mz_zip_array_clear(pZip, &new_ext_block);
7127 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7128 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7131 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))
7133 mz_zip_array_clear(pZip, &new_ext_block);
7134 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7135 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7138 mz_zip_array_clear(pZip, &new_ext_block);
7143 if (cur_dst_file_ofs > MZ_UINT32_MAX)
7144 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7146 if (local_dir_header_ofs >= MZ_UINT32_MAX)
7147 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7149 MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7151 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7152 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7154 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))
7156 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7157 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7162 if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7165 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7166 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7169 n = (mz_uint32)orig_central_dir_size;
7170 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7172 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7173 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7176 pZip->m_total_files++;
7177 pZip->m_archive_size = cur_dst_file_ofs;
7185 mz_uint64 central_dir_ofs, central_dir_size;
7188 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7189 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7191 pState = pZip->m_pState;
7193 if (pState->m_zip64)
7195 if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
7196 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7200 if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))
7201 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7204 central_dir_ofs = 0;
7205 central_dir_size = 0;
7206 if (pZip->m_total_files)
7209 central_dir_ofs = pZip->m_archive_size;
7210 central_dir_size = pState->m_central_dir.m_size;
7211 pZip->m_central_directory_file_ofs = central_dir_ofs;
7212 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)
7213 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7215 pZip->m_archive_size += central_dir_size;
7218 if (pState->m_zip64)
7221 mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7224 MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
7225 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE -
sizeof(mz_uint32) -
sizeof(mz_uint64));
7226 MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E);
7227 MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
7228 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
7229 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
7230 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7231 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7232 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
7233 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7235 pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
7239 MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
7240 MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7241 MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
7242 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
7243 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7245 pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
7250 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
7251 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7252 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7253 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
7254 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
7256 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
7257 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7259 #ifndef MINIZ_NO_STDIO
7260 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7261 return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7264 pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
7266 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
7270 mz_bool mz_zip_writer_finalize_heap_archive(
mz_zip_archive *pZip,
void **ppBuf,
size_t *pSize)
7272 if ((!ppBuf) || (!pSize))
7273 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7278 if ((!pZip) || (!pZip->m_pState))
7279 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7281 if (pZip->m_pWrite != mz_zip_heap_write_func)
7282 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7284 if (!mz_zip_writer_finalize_archive(pZip))
7287 *ppBuf = pZip->m_pState->m_pMem;
7288 *pSize = pZip->m_pState->m_mem_size;
7289 pZip->m_pState->m_pMem = NULL;
7290 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7297 return mz_zip_writer_end_internal(pZip, MZ_TRUE);
7300 #ifndef MINIZ_NO_STDIO
7301 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)
7303 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);
7306 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)
7308 mz_bool status, created_new_archive = MZ_FALSE;
7310 struct MZ_FILE_STAT_STRUCT file_stat;
7311 mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7313 mz_zip_zero_struct(&zip_archive);
7314 if ((
int)level_and_flags < 0)
7315 level_and_flags = MZ_DEFAULT_LEVEL;
7317 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7320 *pErr = MZ_ZIP_INVALID_PARAMETER;
7324 if (!mz_zip_writer_validate_archive_name(pArchive_name))
7327 *pErr = MZ_ZIP_INVALID_FILENAME;
7333 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7336 if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7339 *pErr = zip_archive.m_last_error;
7343 created_new_archive = MZ_TRUE;
7348 if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7351 *pErr = zip_archive.m_last_error;
7355 if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
7358 *pErr = zip_archive.m_last_error;
7360 mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7366 status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7367 actual_err = zip_archive.m_last_error;
7370 if (!mz_zip_writer_finalize_archive(&zip_archive))
7373 actual_err = zip_archive.m_last_error;
7378 if (!mz_zip_writer_end_internal(&zip_archive, status))
7381 actual_err = zip_archive.m_last_error;
7386 if ((!status) && (created_new_archive))
7389 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7390 (void)ignoredStatus;
7399 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)
7401 mz_uint32 file_index;
7408 if ((!pZip_filename) || (!pArchive_name))
7411 *pErr = MZ_ZIP_INVALID_PARAMETER;
7416 mz_zip_zero_struct(&zip_archive);
7417 if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7420 *pErr = zip_archive.m_last_error;
7425 if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7427 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7430 mz_zip_reader_end_internal(&zip_archive, p != NULL);
7433 *pErr = zip_archive.m_last_error;
7438 void *mz_zip_extract_archive_file_to_heap(
const char *pZip_filename,
const char *pArchive_name,
size_t *pSize, mz_uint flags)
7440 return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7451 return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7456 return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7459 mz_zip_error mz_zip_set_last_error(
mz_zip_archive *pZip, mz_zip_error err_num)
7461 mz_zip_error prev_err;
7464 return MZ_ZIP_INVALID_PARAMETER;
7466 prev_err = pZip->m_last_error;
7468 pZip->m_last_error = err_num;
7475 return MZ_ZIP_INVALID_PARAMETER;
7477 return pZip->m_last_error;
7482 return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
7487 mz_zip_error prev_err;
7490 return MZ_ZIP_INVALID_PARAMETER;
7492 prev_err = pZip->m_last_error;
7494 pZip->m_last_error = MZ_ZIP_NO_ERROR;
7498 const char *mz_zip_get_error_string(mz_zip_error mz_err)
7502 case MZ_ZIP_NO_ERROR:
7504 case MZ_ZIP_UNDEFINED_ERROR:
7505 return "undefined error";
7506 case MZ_ZIP_TOO_MANY_FILES:
7507 return "too many files";
7508 case MZ_ZIP_FILE_TOO_LARGE:
7509 return "file too large";
7510 case MZ_ZIP_UNSUPPORTED_METHOD:
7511 return "unsupported method";
7512 case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
7513 return "unsupported encryption";
7514 case MZ_ZIP_UNSUPPORTED_FEATURE:
7515 return "unsupported feature";
7516 case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
7517 return "failed finding central directory";
7518 case MZ_ZIP_NOT_AN_ARCHIVE:
7519 return "not a ZIP archive";
7520 case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
7521 return "invalid header or archive is corrupted";
7522 case MZ_ZIP_UNSUPPORTED_MULTIDISK:
7523 return "unsupported multidisk archive";
7524 case MZ_ZIP_DECOMPRESSION_FAILED:
7525 return "decompression failed or archive is corrupted";
7526 case MZ_ZIP_COMPRESSION_FAILED:
7527 return "compression failed";
7528 case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
7529 return "unexpected decompressed size";
7530 case MZ_ZIP_CRC_CHECK_FAILED:
7531 return "CRC-32 check failed";
7532 case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
7533 return "unsupported central directory size";
7534 case MZ_ZIP_ALLOC_FAILED:
7535 return "allocation failed";
7536 case MZ_ZIP_FILE_OPEN_FAILED:
7537 return "file open failed";
7538 case MZ_ZIP_FILE_CREATE_FAILED:
7539 return "file create failed";
7540 case MZ_ZIP_FILE_WRITE_FAILED:
7541 return "file write failed";
7542 case MZ_ZIP_FILE_READ_FAILED:
7543 return "file read failed";
7544 case MZ_ZIP_FILE_CLOSE_FAILED:
7545 return "file close failed";
7546 case MZ_ZIP_FILE_SEEK_FAILED:
7547 return "file seek failed";
7548 case MZ_ZIP_FILE_STAT_FAILED:
7549 return "file stat failed";
7550 case MZ_ZIP_INVALID_PARAMETER:
7551 return "invalid parameter";
7552 case MZ_ZIP_INVALID_FILENAME:
7553 return "invalid filename";
7554 case MZ_ZIP_BUF_TOO_SMALL:
7555 return "buffer too small";
7556 case MZ_ZIP_INTERNAL_ERROR:
7557 return "internal error";
7558 case MZ_ZIP_FILE_NOT_FOUND:
7559 return "file not found";
7560 case MZ_ZIP_ARCHIVE_TOO_LARGE:
7561 return "archive is too large";
7562 case MZ_ZIP_VALIDATION_FAILED:
7563 return "validation failed";
7564 case MZ_ZIP_WRITE_CALLBACK_FAILED:
7565 return "write calledback failed";
7570 return "unknown error";
7576 if ((!pZip) || (!pZip->m_pState))
7579 return pZip->m_pState->m_zip64;
7584 if ((!pZip) || (!pZip->m_pState))
7587 return pZip->m_pState->m_central_dir.m_size;
7592 return pZip ? pZip->m_total_files : 0;
7599 return pZip->m_archive_size;
7602 mz_uint64 mz_zip_get_archive_file_start_offset(
mz_zip_archive *pZip)
7604 if ((!pZip) || (!pZip->m_pState))
7606 return pZip->m_pState->m_file_archive_start_ofs;
7611 if ((!pZip) || (!pZip->m_pState))
7613 return pZip->m_pState->m_pFile;
7616 size_t mz_zip_read_archive_data(
mz_zip_archive *pZip, mz_uint64 file_ofs,
void *pBuf,
size_t n)
7618 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7619 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7621 return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7624 mz_uint mz_zip_reader_get_filename(
mz_zip_archive *pZip, mz_uint file_index,
char *pFilename, mz_uint filename_buf_size)
7627 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7630 if (filename_buf_size)
7631 pFilename[0] =
'\0';
7632 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7635 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7636 if (filename_buf_size)
7638 n = MZ_MIN(n, filename_buf_size - 1);
7639 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7640 pFilename[n] =
'\0';
7647 return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7655 if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7656 return mz_zip_reader_end(pZip);
7657 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7658 else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
7659 return mz_zip_writer_end(pZip);