]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/common/miniz.c
Q3map2:
[xonotic/netradiant.git] / tools / quake3 / common / miniz.c
1 #include "miniz.h"
2
3 #ifndef MINIZ_HEADER_FILE_ONLY
4
5 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
6 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
7 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
8
9 #include <string.h>
10 #include <assert.h>
11
12 #define MZ_ASSERT(x) assert(x)
13
14 #ifdef MINIZ_NO_MALLOC
15   #define MZ_MALLOC(x) NULL
16   #define MZ_FREE(x) (void)x, ((void)0)
17   #define MZ_REALLOC(p, x) NULL
18 #else
19   #define MZ_MALLOC(x) malloc(x)
20   #define MZ_FREE(x) free(x)
21   #define MZ_REALLOC(p, x) realloc(p, x)
22 #endif
23
24 #define MZ_MAX(a,b) (((a)>(b))?(a):(b))
25 #define MZ_MIN(a,b) (((a)<(b))?(a):(b))
26 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
27
28 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
29   #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
30   #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
31 #else
32   #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
33   #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
34 #endif
35
36 #ifdef _MSC_VER
37   #define MZ_FORCEINLINE __forceinline
38 #elif defined(__GNUC__)
39   #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
40 #else
41   #define MZ_FORCEINLINE inline
42 #endif
43
44 #ifdef __cplusplus
45   extern "C" {
46 #endif
47
48 // ------------------- zlib-style API's
49
50 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
51 {
52   mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
53   if (!ptr) return MZ_ADLER32_INIT;
54   while (buf_len) {
55     for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
56       s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
57       s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
58     }
59     for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
60     s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
61   }
62   return (s2 << 16) + s1;
63 }
64
65 // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/
66 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
67 {
68   static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
69     0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
70   mz_uint32 crcu32 = (mz_uint32)crc;
71   if (!ptr) return MZ_CRC32_INIT;
72   crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; }
73   return ~crcu32;
74 }
75
76 void mz_free(void *p)
77 {
78   MZ_FREE(p);
79 }
80
81 #ifndef MINIZ_NO_ZLIB_APIS
82
83 static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
84 static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
85 static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); }
86
87 const char *mz_version(void)
88 {
89   return MZ_VERSION;
90 }
91
92 int mz_deflateInit(mz_streamp pStream, int level)
93 {
94   return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
95 }
96
97 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
98 {
99   tdefl_compressor *pComp;
100   mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
101
102   if (!pStream) return MZ_STREAM_ERROR;
103   if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR;
104
105   pStream->data_type = 0;
106   pStream->adler = MZ_ADLER32_INIT;
107   pStream->msg = NULL;
108   pStream->reserved = 0;
109   pStream->total_in = 0;
110   pStream->total_out = 0;
111   if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
112   if (!pStream->zfree) pStream->zfree = def_free_func;
113
114   pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
115   if (!pComp)
116     return MZ_MEM_ERROR;
117
118   pStream->state = (struct mz_internal_state *)pComp;
119
120   if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
121   {
122     mz_deflateEnd(pStream);
123     return MZ_PARAM_ERROR;
124   }
125
126   return MZ_OK;
127 }
128
129 int mz_deflateReset(mz_streamp pStream)
130 {
131   if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
132   pStream->total_in = pStream->total_out = 0;
133   tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
134   return MZ_OK;
135 }
136
137 int mz_deflate(mz_streamp pStream, int flush)
138 {
139   size_t in_bytes, out_bytes;
140   mz_ulong orig_total_in, orig_total_out;
141   int mz_status = MZ_OK;
142
143   if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
144   if (!pStream->avail_out) return MZ_BUF_ERROR;
145
146   if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
147
148   if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
149     return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
150
151   orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
152   for ( ; ; )
153   {
154     tdefl_status defl_status;
155     in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
156
157     defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
158     pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
159     pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
160
161     pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
162     pStream->total_out += (mz_uint)out_bytes;
163
164     if (defl_status < 0)
165     {
166       mz_status = MZ_STREAM_ERROR;
167       break;
168     }
169     else if (defl_status == TDEFL_STATUS_DONE)
170     {
171       mz_status = MZ_STREAM_END;
172       break;
173     }
174     else if (!pStream->avail_out)
175       break;
176     else if ((!pStream->avail_in) && (flush != MZ_FINISH))
177     {
178       if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
179         break;
180       return MZ_BUF_ERROR; // Can't make forward progress without some input.
181     }
182   }
183   return mz_status;
184 }
185
186 int mz_deflateEnd(mz_streamp pStream)
187 {
188   if (!pStream) return MZ_STREAM_ERROR;
189   if (pStream->state)
190   {
191     pStream->zfree(pStream->opaque, pStream->state);
192     pStream->state = NULL;
193   }
194   return MZ_OK;
195 }
196
197 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
198 {
199   (void)pStream;
200   // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.)
201   return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
202 }
203
204 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
205 {
206   int status;
207   mz_stream stream;
208   memset(&stream, 0, sizeof(stream));
209
210   // In case mz_ulong is 64-bits (argh I hate longs).
211   if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
212
213   stream.next_in = pSource;
214   stream.avail_in = (mz_uint32)source_len;
215   stream.next_out = pDest;
216   stream.avail_out = (mz_uint32)*pDest_len;
217
218   status = mz_deflateInit(&stream, level);
219   if (status != MZ_OK) return status;
220
221   status = mz_deflate(&stream, MZ_FINISH);
222   if (status != MZ_STREAM_END)
223   {
224     mz_deflateEnd(&stream);
225     return (status == MZ_OK) ? MZ_BUF_ERROR : status;
226   }
227
228   *pDest_len = stream.total_out;
229   return mz_deflateEnd(&stream);
230 }
231
232 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
233 {
234   return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
235 }
236
237 mz_ulong mz_compressBound(mz_ulong source_len)
238 {
239   return mz_deflateBound(NULL, source_len);
240 }
241
242 typedef struct
243 {
244   tinfl_decompressor m_decomp;
245   mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
246   mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
247   tinfl_status m_last_status;
248 } inflate_state;
249
250 int mz_inflateInit2(mz_streamp pStream, int window_bits)
251 {
252   inflate_state *pDecomp;
253   if (!pStream) return MZ_STREAM_ERROR;
254   if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
255
256   pStream->data_type = 0;
257   pStream->adler = 0;
258   pStream->msg = NULL;
259   pStream->total_in = 0;
260   pStream->total_out = 0;
261   pStream->reserved = 0;
262   if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
263   if (!pStream->zfree) pStream->zfree = def_free_func;
264
265   pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
266   if (!pDecomp) return MZ_MEM_ERROR;
267
268   pStream->state = (struct mz_internal_state *)pDecomp;
269
270   tinfl_init(&pDecomp->m_decomp);
271   pDecomp->m_dict_ofs = 0;
272   pDecomp->m_dict_avail = 0;
273   pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
274   pDecomp->m_first_call = 1;
275   pDecomp->m_has_flushed = 0;
276   pDecomp->m_window_bits = window_bits;
277
278   return MZ_OK;
279 }
280
281 int mz_inflateInit(mz_streamp pStream)
282 {
283    return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
284 }
285
286 int mz_inflate(mz_streamp pStream, int flush)
287 {
288   inflate_state* pState;
289   mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
290   size_t in_bytes, out_bytes, orig_avail_in;
291   tinfl_status status;
292
293   if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
294   if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
295   if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
296
297   pState = (inflate_state*)pStream->state;
298   if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
299   orig_avail_in = pStream->avail_in;
300
301   first_call = pState->m_first_call; pState->m_first_call = 0;
302   if (pState->m_last_status < 0) return MZ_DATA_ERROR;
303
304   if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
305   pState->m_has_flushed |= (flush == MZ_FINISH);
306
307   if ((flush == MZ_FINISH) && (first_call))
308   {
309     // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
310     decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
311     in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
312     status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
313     pState->m_last_status = status;
314     pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
315     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
316     pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
317
318     if (status < 0)
319       return MZ_DATA_ERROR;
320     else if (status != TINFL_STATUS_DONE)
321     {
322       pState->m_last_status = TINFL_STATUS_FAILED;
323       return MZ_BUF_ERROR;
324     }
325     return MZ_STREAM_END;
326   }
327   // flush != MZ_FINISH then we must assume there's more input.
328   if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
329
330   if (pState->m_dict_avail)
331   {
332     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
333     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
334     pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
335     pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
336     return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
337   }
338
339   for ( ; ; )
340   {
341     in_bytes = pStream->avail_in;
342     out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
343
344     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);
345     pState->m_last_status = status;
346
347     pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
348     pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
349
350     pState->m_dict_avail = (mz_uint)out_bytes;
351
352     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
353     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
354     pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
355     pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
356
357     if (status < 0)
358        return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
359     else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
360       return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
361     else if (flush == MZ_FINISH)
362     {
363        // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
364        if (status == TINFL_STATUS_DONE)
365           return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
366        // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong.
367        else if (!pStream->avail_out)
368           return MZ_BUF_ERROR;
369     }
370     else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
371       break;
372   }
373
374   return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
375 }
376
377 int mz_inflateEnd(mz_streamp pStream)
378 {
379   if (!pStream)
380     return MZ_STREAM_ERROR;
381   if (pStream->state)
382   {
383     pStream->zfree(pStream->opaque, pStream->state);
384     pStream->state = NULL;
385   }
386   return MZ_OK;
387 }
388
389 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
390 {
391   mz_stream stream;
392   int status;
393   memset(&stream, 0, sizeof(stream));
394
395   // In case mz_ulong is 64-bits (argh I hate longs).
396   if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
397
398   stream.next_in = pSource;
399   stream.avail_in = (mz_uint32)source_len;
400   stream.next_out = pDest;
401   stream.avail_out = (mz_uint32)*pDest_len;
402
403   status = mz_inflateInit(&stream);
404   if (status != MZ_OK)
405     return status;
406
407   status = mz_inflate(&stream, MZ_FINISH);
408   if (status != MZ_STREAM_END)
409   {
410     mz_inflateEnd(&stream);
411     return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
412   }
413   *pDest_len = stream.total_out;
414
415   return mz_inflateEnd(&stream);
416 }
417
418 const char *mz_error(int err)
419 {
420   static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
421   {
422     { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
423     { 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" }
424   };
425   mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc;
426   return NULL;
427 }
428
429 #endif //MINIZ_NO_ZLIB_APIS
430
431 // ------------------- Low-level Decompression (completely independent from all compression API's)
432
433 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
434 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
435
436 #define TINFL_CR_BEGIN switch(r->m_state) { case 0:
437 #define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
438 #define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
439 #define TINFL_CR_FINISH }
440
441 // TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
442 // reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
443 #define TINFL_GET_BYTE(state_index, c) do { \
444   if (pIn_buf_cur >= pIn_buf_end) { \
445     for ( ; ; ) { \
446       if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
447         TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
448         if (pIn_buf_cur < pIn_buf_end) { \
449           c = *pIn_buf_cur++; \
450           break; \
451         } \
452       } else { \
453         c = 0; \
454         break; \
455       } \
456     } \
457   } else c = *pIn_buf_cur++; } MZ_MACRO_END
458
459 #define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
460 #define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
461 #define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
462
463 // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
464 // It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
465 // Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
466 // bit buffer contains >=15 bits (deflate's max. Huffman code size).
467 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
468   do { \
469     temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
470     if (temp >= 0) { \
471       code_len = temp >> 9; \
472       if ((code_len) && (num_bits >= code_len)) \
473       break; \
474     } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
475        code_len = TINFL_FAST_LOOKUP_BITS; \
476        do { \
477           temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
478        } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
479     } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
480   } while (num_bits < 15);
481
482 // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
483 // beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
484 // decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
485 // The slow path is only executed at the very end of the input buffer.
486 #define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
487   int temp; mz_uint code_len, c; \
488   if (num_bits < 15) { \
489     if ((pIn_buf_end - pIn_buf_cur) < 2) { \
490        TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
491     } else { \
492        bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
493     } \
494   } \
495   if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
496     code_len = temp >> 9, temp &= 511; \
497   else { \
498     code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
499   } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
500
501 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)
502 {
503   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 };
504   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 };
505   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};
506   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};
507   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 };
508   static const int s_min_table_sizes[3] = { 257, 1, 4 };
509
510   tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
511   const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
512   mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
513   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;
514
515   // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
516   if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
517
518   num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
519   TINFL_CR_BEGIN
520
521   bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
522   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
523   {
524     TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
525     counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
526     if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
527     if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
528   }
529
530   do
531   {
532     TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
533     if (r->m_type == 0)
534     {
535       TINFL_SKIP_BITS(5, num_bits & 7);
536       for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
537       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)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
538       while ((counter) && (num_bits))
539       {
540         TINFL_GET_BITS(51, dist, 8);
541         while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
542         *pOut_buf_cur++ = (mz_uint8)dist;
543         counter--;
544       }
545       while (counter)
546       {
547         size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
548         while (pIn_buf_cur >= pIn_buf_end)
549         {
550           if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
551           {
552             TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
553           }
554           else
555           {
556             TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
557           }
558         }
559         n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
560         TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
561       }
562     }
563     else if (r->m_type == 3)
564     {
565       TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
566     }
567     else
568     {
569       if (r->m_type == 1)
570       {
571         mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
572         r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
573         for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
574       }
575       else
576       {
577         for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
578         MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
579         r->m_table_sizes[2] = 19;
580       }
581       for ( ; (int)r->m_type >= 0; r->m_type--)
582       {
583         int tree_next, tree_cur; tinfl_huff_table *pTable;
584         mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
585         for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
586         used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
587         for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
588         if ((65536 != total) && (used_syms > 1))
589         {
590           TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
591         }
592         for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
593         {
594           mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
595           cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
596           if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
597           if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
598           rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
599           for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
600           {
601             tree_cur -= ((rev_code >>= 1) & 1);
602             if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
603           }
604           tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
605         }
606         if (r->m_type == 2)
607         {
608           for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
609           {
610             mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
611             if ((dist == 16) && (!counter))
612             {
613               TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
614             }
615             num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
616             TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
617           }
618           if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
619           {
620             TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
621           }
622           TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
623         }
624       }
625       for ( ; ; )
626       {
627         mz_uint8 *pSrc;
628         for ( ; ; )
629         {
630           if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
631           {
632             TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
633             if (counter >= 256)
634               break;
635             while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
636             *pOut_buf_cur++ = (mz_uint8)counter;
637           }
638           else
639           {
640             int sym2; mz_uint code_len;
641 #if TINFL_USE_64BIT_BITBUF
642             if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
643 #else
644             if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
645 #endif
646             if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
647               code_len = sym2 >> 9;
648             else
649             {
650               code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
651             }
652             counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
653             if (counter & 256)
654               break;
655
656 #if !TINFL_USE_64BIT_BITBUF
657             if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
658 #endif
659             if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
660               code_len = sym2 >> 9;
661             else
662             {
663               code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
664             }
665             bit_buf >>= code_len; num_bits -= code_len;
666
667             pOut_buf_cur[0] = (mz_uint8)counter;
668             if (sym2 & 256)
669             {
670               pOut_buf_cur++;
671               counter = sym2;
672               break;
673             }
674             pOut_buf_cur[1] = (mz_uint8)sym2;
675             pOut_buf_cur += 2;
676           }
677         }
678         if ((counter &= 511) == 256) break;
679
680         num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
681         if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
682
683         TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
684         num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
685         if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
686
687         dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
688         if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
689         {
690           TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
691         }
692
693         pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
694
695         if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
696         {
697           while (counter--)
698           {
699             while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
700             *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
701           }
702           continue;
703         }
704 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
705         else if ((counter >= 9) && (counter <= dist))
706         {
707           const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
708           do
709           {
710             ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
711             ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
712             pOut_buf_cur += 8;
713           } while ((pSrc += 8) < pSrc_end);
714           if ((counter &= 7) < 3)
715           {
716             if (counter)
717             {
718               pOut_buf_cur[0] = pSrc[0];
719               if (counter > 1)
720                 pOut_buf_cur[1] = pSrc[1];
721               pOut_buf_cur += counter;
722             }
723             continue;
724           }
725         }
726 #endif
727         do
728         {
729           pOut_buf_cur[0] = pSrc[0];
730           pOut_buf_cur[1] = pSrc[1];
731           pOut_buf_cur[2] = pSrc[2];
732           pOut_buf_cur += 3; pSrc += 3;
733         } while ((int)(counter -= 3) > 2);
734         if ((int)counter > 0)
735         {
736           pOut_buf_cur[0] = pSrc[0];
737           if ((int)counter > 1)
738             pOut_buf_cur[1] = pSrc[1];
739           pOut_buf_cur += counter;
740         }
741       }
742     }
743   } while (!(r->m_final & 1));
744   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
745   {
746     TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
747   }
748   TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
749   TINFL_CR_FINISH
750
751 common_exit:
752   r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
753   *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
754   if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
755   {
756     const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
757     mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
758     while (buf_len)
759     {
760       for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
761       {
762         s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
763         s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
764       }
765       for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
766       s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
767     }
768     r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
769   }
770   return status;
771 }
772
773 // Higher level helper functions.
774 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
775 {
776   tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
777   *pOut_len = 0;
778   tinfl_init(&decomp);
779   for ( ; ; )
780   {
781     size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
782     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,
783       (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
784     if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
785     {
786       MZ_FREE(pBuf); *pOut_len = 0; return NULL;
787     }
788     src_buf_ofs += src_buf_size;
789     *pOut_len += dst_buf_size;
790     if (status == TINFL_STATUS_DONE) break;
791     new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
792     pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
793     if (!pNew_buf)
794     {
795       MZ_FREE(pBuf); *pOut_len = 0; return NULL;
796     }
797     pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
798   }
799   return pBuf;
800 }
801
802 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)
803 {
804   tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
805   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);
806   return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
807 }
808
809 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)
810 {
811   int result = 0;
812   tinfl_decompressor decomp;
813   mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
814   if (!pDict)
815     return TINFL_STATUS_FAILED;
816   tinfl_init(&decomp);
817   for ( ; ; )
818   {
819     size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
820     tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
821       (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
822     in_buf_ofs += in_buf_size;
823     if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
824       break;
825     if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
826     {
827       result = (status == TINFL_STATUS_DONE);
828       break;
829     }
830     dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
831   }
832   MZ_FREE(pDict);
833   *pIn_buf_size = in_buf_ofs;
834   return result;
835 }
836
837 // ------------------- Low-level Compression (independent from all decompression API's)
838
839 // Purposely making these tables static for faster init and thread safety.
840 static const mz_uint16 s_tdefl_len_sym[256] = {
841   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,
842   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,
843   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,
844   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,
845   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,
846   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,
847   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,
848   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 };
849
850 static const mz_uint8 s_tdefl_len_extra[256] = {
851   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,
852   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,
853   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
854   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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 };
855
856 static const mz_uint8 s_tdefl_small_dist_sym[512] = {
857   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,
858   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,
859   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,
860   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,
861   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,
862   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,
863   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,
864   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,
865   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,
866   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,
867   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,
868   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 };
869
870 static const mz_uint8 s_tdefl_small_dist_extra[512] = {
871   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,
872   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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,
873   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,
874   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,
875   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
876   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
877   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
878   7,7,7,7,7,7,7,7 };
879
880 static const mz_uint8 s_tdefl_large_dist_sym[128] = {
881   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,
882   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,
883   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 };
884
885 static const mz_uint8 s_tdefl_large_dist_extra[128] = {
886   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,
887   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,
888   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 };
889
890 // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
891 typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
892 static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
893 {
894   mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist);
895   for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
896   while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
897   for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
898   {
899     const mz_uint32* pHist = &hist[pass << 8];
900     mz_uint offsets[256], cur_ofs = 0;
901     for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
902     for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
903     { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
904   }
905   return pCur_syms;
906 }
907
908 // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
909 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
910 {
911   int root, leaf, next, avbl, used, dpth;
912   if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
913   A[0].m_key += A[1].m_key; root = 0; leaf = 2;
914   for (next=1; next < n-1; next++)
915   {
916     if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
917     if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
918   }
919   A[n-2].m_key = 0; for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
920   avbl = 1; used = dpth = 0; root = n-2; next = n-1;
921   while (avbl>0)
922   {
923     while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
924     while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
925     avbl = 2*used; dpth++; used = 0;
926   }
927 }
928
929 // Limits canonical Huffman code table's max code size.
930 enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
931 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
932 {
933   int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
934   for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
935   for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
936   while (total != (1UL << max_code_size))
937   {
938     pNum_codes[max_code_size]--;
939     for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
940     total--;
941   }
942 }
943
944 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
945 {
946   int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes);
947   if (static_table)
948   {
949     for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
950   }
951   else
952   {
953     tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
954     int num_used_syms = 0;
955     const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
956     for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; }
957
958     pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
959
960     for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
961
962     tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
963
964     MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
965     for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
966       for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
967   }
968
969   next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
970
971   for (i = 0; i < table_len; i++)
972   {
973     mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
974     code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
975     d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
976   }
977 }
978
979 #define TDEFL_PUT_BITS(b, l) do { \
980   mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
981   d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
982   while (d->m_bits_in >= 8) { \
983     if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
984       *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
985       d->m_bit_buffer >>= 8; \
986       d->m_bits_in -= 8; \
987   } \
988 } MZ_MACRO_END
989
990 #define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
991   if (rle_repeat_count < 3) { \
992     d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
993     while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
994   } else { \
995     d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
996 } rle_repeat_count = 0; } }
997
998 #define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
999   if (rle_z_count < 3) { \
1000     d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \
1001   } else if (rle_z_count <= 10) { \
1002     d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
1003   } else { \
1004     d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
1005 } rle_z_count = 0; } }
1006
1007 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 };
1008
1009 static void tdefl_start_dynamic_block(tdefl_compressor *d)
1010 {
1011   int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
1012   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;
1013
1014   d->m_huff_count[0][256] = 1;
1015
1016   tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
1017   tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
1018
1019   for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
1020   for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
1021
1022   memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1023   memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1024   total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
1025
1026   memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1027   for (i = 0; i < total_code_sizes_to_pack; i++)
1028   {
1029     mz_uint8 code_size = code_sizes_to_pack[i];
1030     if (!code_size)
1031     {
1032       TDEFL_RLE_PREV_CODE_SIZE();
1033       if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
1034     }
1035     else
1036     {
1037       TDEFL_RLE_ZERO_CODE_SIZE();
1038       if (code_size != prev_code_size)
1039       {
1040         TDEFL_RLE_PREV_CODE_SIZE();
1041         d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size;
1042       }
1043       else if (++rle_repeat_count == 6)
1044       {
1045         TDEFL_RLE_PREV_CODE_SIZE();
1046       }
1047     }
1048     prev_code_size = code_size;
1049   }
1050   if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
1051
1052   tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1053
1054   TDEFL_PUT_BITS(2, 2);
1055
1056   TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1057   TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1058
1059   for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break;
1060   num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1061   for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1062
1063   for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
1064   {
1065     mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1066     TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1067     if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1068   }
1069 }
1070
1071 static void tdefl_start_static_block(tdefl_compressor *d)
1072 {
1073   mz_uint i;
1074   mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1075
1076   for (i = 0; i <= 143; ++i) *p++ = 8;
1077   for ( ; i <= 255; ++i) *p++ = 9;
1078   for ( ; i <= 279; ++i) *p++ = 7;
1079   for ( ; i <= 287; ++i) *p++ = 8;
1080
1081   memset(d->m_huff_code_sizes[1], 5, 32);
1082
1083   tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1084   tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1085
1086   TDEFL_PUT_BITS(1, 2);
1087 }
1088
1089 static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1090
1091 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
1092 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1093 {
1094   mz_uint flags;
1095   mz_uint8 *pLZ_codes;
1096   mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1097   mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1098   mz_uint64 bit_buffer = d->m_bit_buffer;
1099   mz_uint bits_in = d->m_bits_in;
1100
1101 #define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
1102
1103   flags = 1;
1104   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1105   {
1106     if (flags == 1)
1107       flags = *pLZ_codes++ | 0x100;
1108
1109     if (flags & 1)
1110     {
1111       mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1112       mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
1113
1114       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1115       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]]);
1116       TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1117
1118       // This sequence coaxes MSVC into using cmov's vs. jmp's.
1119       s0 = s_tdefl_small_dist_sym[match_dist & 511];
1120       n0 = s_tdefl_small_dist_extra[match_dist & 511];
1121       s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1122       n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1123       sym = (match_dist < 512) ? s0 : s1;
1124       num_extra_bits = (match_dist < 512) ? n0 : n1;
1125
1126       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1127       TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1128       TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1129     }
1130     else
1131     {
1132       mz_uint lit = *pLZ_codes++;
1133       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1134       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1135
1136       if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1137       {
1138         flags >>= 1;
1139         lit = *pLZ_codes++;
1140         MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1141         TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1142
1143         if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1144         {
1145           flags >>= 1;
1146           lit = *pLZ_codes++;
1147           MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1148           TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1149         }
1150       }
1151     }
1152
1153     if (pOutput_buf >= d->m_pOutput_buf_end)
1154       return MZ_FALSE;
1155
1156     *(mz_uint64*)pOutput_buf = bit_buffer;
1157     pOutput_buf += (bits_in >> 3);
1158     bit_buffer >>= (bits_in & ~7);
1159     bits_in &= 7;
1160   }
1161
1162 #undef TDEFL_PUT_BITS_FAST
1163
1164   d->m_pOutput_buf = pOutput_buf;
1165   d->m_bits_in = 0;
1166   d->m_bit_buffer = 0;
1167
1168   while (bits_in)
1169   {
1170     mz_uint32 n = MZ_MIN(bits_in, 16);
1171     TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1172     bit_buffer >>= n;
1173     bits_in -= n;
1174   }
1175
1176   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1177
1178   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1179 }
1180 #else
1181 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1182 {
1183   mz_uint flags;
1184   mz_uint8 *pLZ_codes;
1185
1186   flags = 1;
1187   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1188   {
1189     if (flags == 1)
1190       flags = *pLZ_codes++ | 0x100;
1191     if (flags & 1)
1192     {
1193       mz_uint sym, num_extra_bits;
1194       mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
1195
1196       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1197       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]]);
1198       TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1199
1200       if (match_dist < 512)
1201       {
1202         sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1203       }
1204       else
1205       {
1206         sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1207       }
1208       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1209       TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1210       TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1211     }
1212     else
1213     {
1214       mz_uint lit = *pLZ_codes++;
1215       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1216       TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1217     }
1218   }
1219
1220   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1221
1222   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1223 }
1224 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
1225
1226 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
1227 {
1228   if (static_block)
1229     tdefl_start_static_block(d);
1230   else
1231     tdefl_start_dynamic_block(d);
1232   return tdefl_compress_lz_codes(d);
1233 }
1234
1235 static int tdefl_flush_block(tdefl_compressor *d, int flush)
1236 {
1237   mz_uint saved_bit_buf, saved_bits_in;
1238   mz_uint8 *pSaved_output_buf;
1239   mz_bool comp_block_succeeded = MZ_FALSE;
1240   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;
1241   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;
1242
1243   d->m_pOutput_buf = pOutput_buf_start;
1244   d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1245
1246   MZ_ASSERT(!d->m_output_flush_remaining);
1247   d->m_output_flush_ofs = 0;
1248   d->m_output_flush_remaining = 0;
1249
1250   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1251   d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1252
1253   if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1254   {
1255     TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
1256   }
1257
1258   TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1259
1260   pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
1261
1262   if (!use_raw_block)
1263     comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1264
1265   // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
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) )
1268   {
1269     mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1270     TDEFL_PUT_BITS(0, 2);
1271     if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
1272     for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1273     {
1274       TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1275     }
1276     for (i = 0; i < d->m_total_lz_bytes; ++i)
1277     {
1278       TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1279     }
1280   }
1281   // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
1282   else if (!comp_block_succeeded)
1283   {
1284     d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1285     tdefl_compress_block(d, MZ_TRUE);
1286   }
1287
1288   if (flush)
1289   {
1290     if (flush == TDEFL_FINISH)
1291     {
1292       if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
1293       if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } }
1294     }
1295     else
1296     {
1297       mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); }
1298     }
1299   }
1300
1301   MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1302
1303   memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1304   memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1305
1306   d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++;
1307
1308   if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1309   {
1310     if (d->m_pPut_buf_func)
1311     {
1312       *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1313       if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1314         return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1315     }
1316     else if (pOutput_buf_start == d->m_output_buf)
1317     {
1318       int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1319       memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1320       d->m_out_buf_ofs += bytes_to_copy;
1321       if ((n -= bytes_to_copy) != 0)
1322       {
1323         d->m_output_flush_ofs = bytes_to_copy;
1324         d->m_output_flush_remaining = n;
1325       }
1326     }
1327     else
1328     {
1329       d->m_out_buf_ofs += n;
1330     }
1331   }
1332
1333   return d->m_output_flush_remaining;
1334 }
1335
1336 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1337 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
1338 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)
1339 {
1340   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1341   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1342   const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
1343   mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
1344   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
1345   for ( ; ; )
1346   {
1347     for ( ; ; )
1348     {
1349       if (--num_probes_left == 0) return;
1350       #define TDEFL_PROBE \
1351         next_probe_pos = d->m_next[probe_pos]; \
1352         if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
1353         probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1354         if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
1355       TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
1356     }
1357     if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
1358     do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
1359                    (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
1360     if (!probe_len)
1361     {
1362       *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
1363     }
1364     else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
1365     {
1366       *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
1367       c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1368     }
1369   }
1370 }
1371 #else
1372 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)
1373 {
1374   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1375   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1376   const mz_uint8 *s = d->m_dict + pos, *p, *q;
1377   mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1378   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
1379   for ( ; ; )
1380   {
1381     for ( ; ; )
1382     {
1383       if (--num_probes_left == 0) return;
1384       #define TDEFL_PROBE \
1385         next_probe_pos = d->m_next[probe_pos]; \
1386         if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
1387         probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1388         if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
1389       TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
1390     }
1391     if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
1392     if (probe_len > match_len)
1393     {
1394       *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
1395       c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
1396     }
1397   }
1398 }
1399 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1400
1401 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1402 static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1403 {
1404   // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
1405   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;
1406   mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1407   mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1408
1409   while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1410   {
1411     const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1412     mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1413     mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1414     d->m_src_buf_left -= num_bytes_to_process;
1415     lookahead_size += num_bytes_to_process;
1416
1417     while (num_bytes_to_process)
1418     {
1419       mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1420       memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1421       if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1422         memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1423       d->m_pSrc += n;
1424       dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1425       num_bytes_to_process -= n;
1426     }
1427
1428     dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1429     if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
1430
1431     while (lookahead_size >= 4)
1432     {
1433       mz_uint cur_match_dist, cur_match_len = 1;
1434       mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1435       mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
1436       mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1437       mz_uint probe_pos = d->m_hash[hash];
1438       d->m_hash[hash] = (mz_uint16)lookahead_pos;
1439
1440       if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1441       {
1442         const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1443         const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1444         mz_uint32 probe_len = 32;
1445         do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
1446           (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
1447         cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1448         if (!probe_len)
1449           cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1450
1451         if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
1452         {
1453           cur_match_len = 1;
1454           *pLZ_code_buf++ = (mz_uint8)first_trigram;
1455           *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1456           d->m_huff_count[0][(mz_uint8)first_trigram]++;
1457         }
1458         else
1459         {
1460           mz_uint32 s0, s1;
1461           cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1462
1463           MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1464
1465           cur_match_dist--;
1466
1467           pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1468           *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1469           pLZ_code_buf += 3;
1470           *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1471
1472           s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1473           s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1474           d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1475
1476           d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1477         }
1478       }
1479       else
1480       {
1481         *pLZ_code_buf++ = (mz_uint8)first_trigram;
1482         *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1483         d->m_huff_count[0][(mz_uint8)first_trigram]++;
1484       }
1485
1486       if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
1487
1488       total_lz_bytes += cur_match_len;
1489       lookahead_pos += cur_match_len;
1490       dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
1491       cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1492       MZ_ASSERT(lookahead_size >= cur_match_len);
1493       lookahead_size -= cur_match_len;
1494
1495       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1496       {
1497         int n;
1498         d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
1499         d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
1500         if ((n = tdefl_flush_block(d, 0)) != 0)
1501           return (n < 0) ? MZ_FALSE : MZ_TRUE;
1502         total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
1503       }
1504     }
1505
1506     while (lookahead_size)
1507     {
1508       mz_uint8 lit = d->m_dict[cur_pos];
1509
1510       total_lz_bytes++;
1511       *pLZ_code_buf++ = lit;
1512       *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1513       if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
1514
1515       d->m_huff_count[0][lit]++;
1516
1517       lookahead_pos++;
1518       dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
1519       cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1520       lookahead_size--;
1521
1522       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1523       {
1524         int n;
1525         d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
1526         d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
1527         if ((n = tdefl_flush_block(d, 0)) != 0)
1528           return (n < 0) ? MZ_FALSE : MZ_TRUE;
1529         total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left;
1530       }
1531     }
1532   }
1533
1534   d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
1535   d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left;
1536   return MZ_TRUE;
1537 }
1538 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1539
1540 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
1541 {
1542   d->m_total_lz_bytes++;
1543   *d->m_pLZ_code_buf++ = lit;
1544   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
1545   d->m_huff_count[0][lit]++;
1546 }
1547
1548 static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1549 {
1550   mz_uint32 s0, s1;
1551
1552   MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1553
1554   d->m_total_lz_bytes += match_len;
1555
1556   d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1557
1558   match_dist -= 1;
1559   d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1560   d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
1561
1562   *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; }
1563
1564   s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1565   d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1566
1567   if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1568 }
1569
1570 static mz_bool tdefl_compress_normal(tdefl_compressor *d)
1571 {
1572   const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
1573   tdefl_flush flush = d->m_flush;
1574
1575   while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1576   {
1577     mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1578     // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
1579     if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1580     {
1581       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;
1582       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];
1583       mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1584       const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1585       src_buf_left -= num_bytes_to_process;
1586       d->m_lookahead_size += num_bytes_to_process;
1587       while (pSrc != pSrc_end)
1588       {
1589         mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1590         hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1591         d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
1592         dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
1593       }
1594     }
1595     else
1596     {
1597       while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1598       {
1599         mz_uint8 c = *pSrc++;
1600         mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1601         src_buf_left--;
1602         d->m_dict[dst_pos] = c;
1603         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1604           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1605         if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1606         {
1607           mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1608           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);
1609           d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
1610         }
1611       }
1612     }
1613     d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1614     if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1615       break;
1616
1617     // Simple lazy/greedy parsing state machine.
1618     len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1619     if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1620     {
1621       if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1622       {
1623         mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1624         cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; }
1625         if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
1626       }
1627     }
1628     else
1629     {
1630       tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1631     }
1632     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)))
1633     {
1634       cur_match_dist = cur_match_len = 0;
1635     }
1636     if (d->m_saved_match_len)
1637     {
1638       if (cur_match_len > d->m_saved_match_len)
1639       {
1640         tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1641         if (cur_match_len >= 128)
1642         {
1643           tdefl_record_match(d, cur_match_len, cur_match_dist);
1644           d->m_saved_match_len = 0; len_to_move = cur_match_len;
1645         }
1646         else
1647         {
1648           d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
1649         }
1650       }
1651       else
1652       {
1653         tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1654         len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
1655       }
1656     }
1657     else if (!cur_match_dist)
1658       tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1659     else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1660     {
1661       tdefl_record_match(d, cur_match_len, cur_match_dist);
1662       len_to_move = cur_match_len;
1663     }
1664     else
1665     {
1666       d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len;
1667     }
1668     // Move the lookahead forward by len_to_move bytes.
1669     d->m_lookahead_pos += len_to_move;
1670     MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1671     d->m_lookahead_size -= len_to_move;
1672     d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
1673     // Check if it's time to flush the current LZ codes to the internal output buffer.
1674     if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1675          ( (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))) )
1676     {
1677       int n;
1678       d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
1679       if ((n = tdefl_flush_block(d, 0)) != 0)
1680         return (n < 0) ? MZ_FALSE : MZ_TRUE;
1681     }
1682   }
1683
1684   d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
1685   return MZ_TRUE;
1686 }
1687
1688 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
1689 {
1690   if (d->m_pIn_buf_size)
1691   {
1692     *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1693   }
1694
1695   if (d->m_pOut_buf_size)
1696   {
1697     size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1698     memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1699     d->m_output_flush_ofs += (mz_uint)n;
1700     d->m_output_flush_remaining -= (mz_uint)n;
1701     d->m_out_buf_ofs += n;
1702
1703     *d->m_pOut_buf_size = d->m_out_buf_ofs;
1704   }
1705
1706   return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1707 }
1708
1709 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)
1710 {
1711   if (!d)
1712   {
1713     if (pIn_buf_size) *pIn_buf_size = 0;
1714     if (pOut_buf_size) *pOut_buf_size = 0;
1715     return TDEFL_STATUS_BAD_PARAM;
1716   }
1717
1718   d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size;
1719   d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size;
1720   d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1721   d->m_out_buf_ofs = 0;
1722   d->m_flush = flush;
1723
1724   if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1725         (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) )
1726   {
1727     if (pIn_buf_size) *pIn_buf_size = 0;
1728     if (pOut_buf_size) *pOut_buf_size = 0;
1729     return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1730   }
1731   d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1732
1733   if ((d->m_output_flush_remaining) || (d->m_finished))
1734     return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1735
1736 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1737   if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1738       ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1739       ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
1740   {
1741     if (!tdefl_compress_fast(d))
1742       return d->m_prev_return_status;
1743   }
1744   else
1745 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1746   {
1747     if (!tdefl_compress_normal(d))
1748       return d->m_prev_return_status;
1749   }
1750
1751   if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1752     d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1753
1754   if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1755   {
1756     if (tdefl_flush_block(d, flush) < 0)
1757       return d->m_prev_return_status;
1758     d->m_finished = (flush == TDEFL_FINISH);
1759     if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; }
1760   }
1761
1762   return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1763 }
1764
1765 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1766 {
1767   MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1768 }
1769
1770 tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1771 {
1772   d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user;
1773   d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
1774   d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
1775   if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash);
1776   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;
1777   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;
1778   d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8;
1779   d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY;
1780   d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1;
1781   d->m_pIn_buf = NULL; d->m_pOut_buf = NULL;
1782   d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL;
1783   d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0;
1784   memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1785   memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1786   return TDEFL_STATUS_OKAY;
1787 }
1788
1789 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
1790 {
1791   return d->m_prev_return_status;
1792 }
1793
1794 mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
1795 {
1796   return d->m_adler32;
1797 }
1798
1799 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)
1800 {
1801   tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE;
1802   pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE;
1803   succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
1804   succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
1805   MZ_FREE(pComp); return succeeded;
1806 }
1807
1808 typedef struct
1809 {
1810   size_t m_size, m_capacity;
1811   mz_uint8 *m_pBuf;
1812   mz_bool m_expandable;
1813 } tdefl_output_buffer;
1814
1815 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
1816 {
1817   tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
1818   size_t new_size = p->m_size + len;
1819   if (new_size > p->m_capacity)
1820   {
1821     size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE;
1822     do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity);
1823     pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE;
1824     p->m_pBuf = pNew_buf; p->m_capacity = new_capacity;
1825   }
1826   memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size;
1827   return MZ_TRUE;
1828 }
1829
1830 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
1831 {
1832   tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
1833   if (!pOut_len) return MZ_FALSE; else *pOut_len = 0;
1834   out_buf.m_expandable = MZ_TRUE;
1835   if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL;
1836   *pOut_len = out_buf.m_size; return out_buf.m_pBuf;
1837 }
1838
1839 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)
1840 {
1841   tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf);
1842   if (!pOut_buf) return 0;
1843   out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len;
1844   if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0;
1845   return out_buf.m_size;
1846 }
1847
1848 #ifndef MINIZ_NO_ZLIB_APIS
1849 static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
1850
1851 // level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files).
1852 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
1853 {
1854   mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
1855   if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
1856
1857   if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
1858   else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES;
1859   else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK;
1860   else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
1861   else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES;
1862
1863   return comp_flags;
1864 }
1865 #endif //MINIZ_NO_ZLIB_APIS
1866
1867 #ifdef _MSC_VER
1868 #pragma warning (push)
1869 #pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal)
1870 #endif
1871
1872 // Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
1873 // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
1874 // This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
1875 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)
1876 {
1877   // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
1878   static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32,  16, 32, 128, 256,  512, 768, 1500 };
1879   tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0;
1880   if (!pComp) return NULL;
1881   MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
1882   // write dummy header
1883   for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
1884   // compress image data
1885   tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
1886   for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
1887   if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
1888   // write real header
1889   *pLen_out = out_buf.m_size-41;
1890   {
1891     static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
1892     mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1893       0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0,
1894       (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54};
1895     c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24);
1896     memcpy(out_buf.m_pBuf, pnghdr, 41);
1897   }
1898   // write footer (IDAT CRC-32, followed by IEND chunk)
1899   if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
1900   c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
1901   // compute final size of file, grab compressed data buffer and return
1902   *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf;
1903 }
1904 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
1905 {
1906   // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
1907   return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
1908 }
1909
1910 #ifdef _MSC_VER
1911 #pragma warning (pop)
1912 #endif
1913
1914 // ------------------- .ZIP archive reading
1915
1916 #ifndef MINIZ_NO_ARCHIVE_APIS
1917
1918 #ifdef MINIZ_NO_STDIO
1919   #define MZ_FILE void *
1920 #else
1921   #include <stdio.h>
1922   #include <sys/stat.h>
1923
1924   #if defined(_MSC_VER) || defined(__MINGW64__)
1925     static FILE *mz_fopen(const char *pFilename, const char *pMode)
1926     {
1927       FILE* pFile = NULL;
1928       fopen_s(&pFile, pFilename, pMode);
1929       return pFile;
1930     }
1931     static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
1932     {
1933       FILE* pFile = NULL;
1934       if (freopen_s(&pFile, pPath, pMode, pStream))
1935         return NULL;
1936       return pFile;
1937     }
1938     #ifndef MINIZ_NO_TIME
1939       #include <sys/utime.h>
1940     #endif
1941     #define MZ_FILE FILE
1942     #define MZ_FOPEN mz_fopen
1943     #define MZ_FCLOSE fclose
1944     #define MZ_FREAD fread
1945     #define MZ_FWRITE fwrite
1946     #define MZ_FTELL64 _ftelli64
1947     #define MZ_FSEEK64 _fseeki64
1948     #define MZ_FILE_STAT_STRUCT _stat
1949     #define MZ_FILE_STAT _stat
1950     #define MZ_FFLUSH fflush
1951     #define MZ_FREOPEN mz_freopen
1952     #define MZ_DELETE_FILE remove
1953   #elif defined(__MINGW32__)
1954     #ifndef MINIZ_NO_TIME
1955       #include <sys/utime.h>
1956     #endif
1957     #define MZ_FILE FILE
1958     #define MZ_FOPEN(f, m) fopen(f, m)
1959     #define MZ_FCLOSE fclose
1960     #define MZ_FREAD fread
1961     #define MZ_FWRITE fwrite
1962     #define MZ_FTELL64 ftello64
1963     #define MZ_FSEEK64 fseeko64
1964     #define MZ_FILE_STAT_STRUCT _stat
1965     #define MZ_FILE_STAT _stat
1966     #define MZ_FFLUSH fflush
1967     #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
1968     #define MZ_DELETE_FILE remove
1969   #elif defined(__TINYC__)
1970     #ifndef MINIZ_NO_TIME
1971       #include <sys/utime.h>
1972     #endif
1973     #define MZ_FILE FILE
1974     #define MZ_FOPEN(f, m) fopen(f, m)
1975     #define MZ_FCLOSE fclose
1976     #define MZ_FREAD fread
1977     #define MZ_FWRITE fwrite
1978     #define MZ_FTELL64 ftell
1979     #define MZ_FSEEK64 fseek
1980     #define MZ_FILE_STAT_STRUCT stat
1981     #define MZ_FILE_STAT stat
1982     #define MZ_FFLUSH fflush
1983     #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
1984     #define MZ_DELETE_FILE remove
1985   #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
1986     #ifndef MINIZ_NO_TIME
1987       #include <utime.h>
1988     #endif
1989     #define MZ_FILE FILE
1990     #define MZ_FOPEN(f, m) fopen64(f, m)
1991     #define MZ_FCLOSE fclose
1992     #define MZ_FREAD fread
1993     #define MZ_FWRITE fwrite
1994     #define MZ_FTELL64 ftello64
1995     #define MZ_FSEEK64 fseeko64
1996     #define MZ_FILE_STAT_STRUCT stat64
1997     #define MZ_FILE_STAT stat64
1998     #define MZ_FFLUSH fflush
1999     #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
2000     #define MZ_DELETE_FILE remove
2001   #else
2002     #ifndef MINIZ_NO_TIME
2003       #include <utime.h>
2004     #endif
2005     #define MZ_FILE FILE
2006     #define MZ_FOPEN(f, m) fopen(f, m)
2007     #define MZ_FCLOSE fclose
2008     #define MZ_FREAD fread
2009     #define MZ_FWRITE fwrite
2010     #define MZ_FTELL64 ftello
2011     #define MZ_FSEEK64 fseeko
2012     #define MZ_FILE_STAT_STRUCT stat
2013     #define MZ_FILE_STAT stat
2014     #define MZ_FFLUSH fflush
2015     #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2016     #define MZ_DELETE_FILE remove
2017   #endif // #ifdef _MSC_VER
2018 #endif // #ifdef MINIZ_NO_STDIO
2019
2020 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
2021
2022 // Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff.
2023 enum
2024 {
2025   // ZIP archive identifiers and record sizes
2026   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
2027   MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
2028   // Central directory header record offsets
2029   MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
2030   MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16,
2031   MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
2032   MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
2033   // Local directory header offsets
2034   MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10,
2035   MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
2036   MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
2037   // End of central directory offsets
2038   MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
2039   MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
2040 };
2041
2042 typedef struct
2043 {
2044   void *m_p;
2045   size_t m_size, m_capacity;
2046   mz_uint m_element_size;
2047 } mz_zip_array;
2048
2049 struct mz_zip_internal_state_tag
2050 {
2051   mz_zip_array m_central_dir;
2052   mz_zip_array m_central_dir_offsets;
2053   mz_zip_array m_sorted_central_dir_offsets;
2054   MZ_FILE *m_pFile;
2055   void *m_pMem;
2056   size_t m_mem_size;
2057   size_t m_mem_capacity;
2058 };
2059
2060 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
2061 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
2062
2063 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
2064 {
2065   pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
2066   memset(pArray, 0, sizeof(mz_zip_array));
2067 }
2068
2069 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
2070 {
2071   void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE;
2072   if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; }
2073   if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE;
2074   pArray->m_p = pNew_p; pArray->m_capacity = new_capacity;
2075   return MZ_TRUE;
2076 }
2077
2078 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
2079 {
2080   if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; }
2081   return MZ_TRUE;
2082 }
2083
2084 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
2085 {
2086   if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; }
2087   pArray->m_size = new_size;
2088   return MZ_TRUE;
2089 }
2090
2091 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
2092 {
2093   return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
2094 }
2095
2096 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
2097 {
2098   size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE;
2099   memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
2100   return MZ_TRUE;
2101 }
2102
2103 #ifndef MINIZ_NO_TIME
2104 static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date)
2105 {
2106   struct tm tm;
2107   memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1;
2108   tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31;
2109   tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62;
2110   return mktime(&tm);
2111 }
2112
2113 static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
2114 {
2115 #ifdef _MSC_VER
2116   struct tm tm_struct;
2117   struct tm *tm = &tm_struct;
2118   errno_t err = localtime_s(tm, &time);
2119   if (err)
2120   {
2121     *pDOS_date = 0; *pDOS_time = 0;
2122     return;
2123   }
2124 #else
2125   struct tm *tm = localtime(&time);
2126 #endif
2127   *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
2128   *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
2129 }
2130 #endif
2131
2132 #ifndef MINIZ_NO_STDIO
2133 static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
2134 {
2135 #ifdef MINIZ_NO_TIME
2136   (void)pFilename; *pDOS_date = *pDOS_time = 0;
2137 #else
2138   struct MZ_FILE_STAT_STRUCT file_stat;
2139   // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh.
2140   if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
2141     return MZ_FALSE;
2142   mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
2143 #endif // #ifdef MINIZ_NO_TIME
2144   return MZ_TRUE;
2145 }
2146
2147 #ifndef MINIZ_NO_TIME
2148 static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time)
2149 {
2150   struct utimbuf t; t.actime = access_time; t.modtime = modified_time;
2151   return !utime(pFilename, &t);
2152 }
2153 #endif // #ifndef MINIZ_NO_TIME
2154 #endif // #ifndef MINIZ_NO_STDIO
2155
2156 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags)
2157 {
2158   (void)flags;
2159   if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
2160     return MZ_FALSE;
2161
2162   if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
2163   if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
2164   if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
2165
2166   pZip->m_zip_mode = MZ_ZIP_MODE_READING;
2167   pZip->m_archive_size = 0;
2168   pZip->m_central_directory_file_ofs = 0;
2169   pZip->m_total_files = 0;
2170
2171   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
2172     return MZ_FALSE;
2173   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
2174   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
2175   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
2176   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
2177   return MZ_TRUE;
2178 }
2179
2180 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)
2181 {
2182   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;
2183   const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
2184   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);
2185   mz_uint8 l = 0, r = 0;
2186   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
2187   pE = pL + MZ_MIN(l_len, r_len);
2188   while (pL < pE)
2189   {
2190     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
2191       break;
2192     pL++; pR++;
2193   }
2194   return (pL == pE) ? (l_len < r_len) : (l < r);
2195 }
2196
2197 #define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END
2198
2199 // Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.)
2200 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
2201 {
2202   mz_zip_internal_state *pState = pZip->m_pState;
2203   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
2204   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
2205   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
2206   const int size = pZip->m_total_files;
2207   int start = (size - 2) >> 1, end;
2208   while (start >= 0)
2209   {
2210     int child, root = start;
2211     for ( ; ; )
2212     {
2213       if ((child = (root << 1) + 1) >= size)
2214         break;
2215       child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])));
2216       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
2217         break;
2218       MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
2219     }
2220     start--;
2221   }
2222
2223   end = size - 1;
2224   while (end > 0)
2225   {
2226     int child, root = 0;
2227     MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
2228     for ( ; ; )
2229     {
2230       if ((child = (root << 1) + 1) >= end)
2231         break;
2232       child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]));
2233       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
2234         break;
2235       MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child;
2236     }
2237     end--;
2238   }
2239 }
2240
2241 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags)
2242 {
2243   mz_uint cdir_size, num_this_disk, cdir_disk_index;
2244   mz_uint64 cdir_ofs;
2245   mz_int64 cur_file_ofs;
2246   const mz_uint8 *p;
2247   mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
2248   mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
2249   // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there.
2250   if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
2251     return MZ_FALSE;
2252   // Find the end of central directory record by scanning the file from the end towards the beginning.
2253   cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
2254   for ( ; ; )
2255   {
2256     int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
2257     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
2258       return MZ_FALSE;
2259     for (i = n - 4; i >= 0; --i)
2260       if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
2261         break;
2262     if (i >= 0)
2263     {
2264       cur_file_ofs += i;
2265       break;
2266     }
2267     if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
2268       return MZ_FALSE;
2269     cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
2270   }
2271   // Read and verify the end of central directory record.
2272   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)
2273     return MZ_FALSE;
2274   if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) ||
2275       ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS)))
2276     return MZ_FALSE;
2277
2278   num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
2279   cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
2280   if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
2281     return MZ_FALSE;
2282
2283   if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
2284     return MZ_FALSE;
2285
2286   cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
2287   if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
2288     return MZ_FALSE;
2289
2290   pZip->m_central_directory_file_ofs = cdir_ofs;
2291
2292   if (pZip->m_total_files)
2293   {
2294      mz_uint i, n;
2295
2296     // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices.
2297     if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
2298         (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
2299       return MZ_FALSE;
2300
2301     if (sort_central_dir)
2302     {
2303       if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
2304         return MZ_FALSE;
2305     }
2306
2307     if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
2308       return MZ_FALSE;
2309
2310     // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported).
2311     p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
2312     for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
2313     {
2314       mz_uint total_header_size, comp_size, decomp_size, disk_index;
2315       if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
2316         return MZ_FALSE;
2317       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);
2318       if (sort_central_dir)
2319         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
2320       comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
2321       decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
2322       if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF))
2323         return MZ_FALSE;
2324       disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
2325       if ((disk_index != num_this_disk) && (disk_index != 1))
2326         return MZ_FALSE;
2327       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)
2328         return MZ_FALSE;
2329       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)
2330         return MZ_FALSE;
2331       n -= total_header_size; p += total_header_size;
2332     }
2333   }
2334
2335   if (sort_central_dir)
2336     mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
2337
2338   return MZ_TRUE;
2339 }
2340
2341 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags)
2342 {
2343   if ((!pZip) || (!pZip->m_pRead))
2344     return MZ_FALSE;
2345   if (!mz_zip_reader_init_internal(pZip, flags))
2346     return MZ_FALSE;
2347   pZip->m_archive_size = size;
2348   if (!mz_zip_reader_read_central_dir(pZip, flags))
2349   {
2350     mz_zip_reader_end(pZip);
2351     return MZ_FALSE;
2352   }
2353   return MZ_TRUE;
2354 }
2355
2356 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
2357 {
2358   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
2359   size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
2360   memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
2361   return s;
2362 }
2363
2364 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags)
2365 {
2366   if (!mz_zip_reader_init_internal(pZip, flags))
2367     return MZ_FALSE;
2368   pZip->m_archive_size = size;
2369   pZip->m_pRead = mz_zip_mem_read_func;
2370   pZip->m_pIO_opaque = pZip;
2371 #ifdef __cplusplus
2372   pZip->m_pState->m_pMem = const_cast<void *>(pMem);
2373 #else
2374   pZip->m_pState->m_pMem = (void *)pMem;
2375 #endif
2376   pZip->m_pState->m_mem_size = size;
2377   if (!mz_zip_reader_read_central_dir(pZip, flags))
2378   {
2379     mz_zip_reader_end(pZip);
2380     return MZ_FALSE;
2381   }
2382   return MZ_TRUE;
2383 }
2384
2385 #ifndef MINIZ_NO_STDIO
2386 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
2387 {
2388   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
2389   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
2390   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))))
2391     return 0;
2392   return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
2393 }
2394
2395 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
2396 {
2397   mz_uint64 file_size;
2398   MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
2399   if (!pFile)
2400     return MZ_FALSE;
2401   if (MZ_FSEEK64(pFile, 0, SEEK_END))
2402   {
2403     MZ_FCLOSE(pFile);
2404     return MZ_FALSE;
2405   }
2406   file_size = MZ_FTELL64(pFile);
2407   if (!mz_zip_reader_init_internal(pZip, flags))
2408   {
2409     MZ_FCLOSE(pFile);
2410     return MZ_FALSE;
2411   }
2412   pZip->m_pRead = mz_zip_file_read_func;
2413   pZip->m_pIO_opaque = pZip;
2414   pZip->m_pState->m_pFile = pFile;
2415   pZip->m_archive_size = file_size;
2416   if (!mz_zip_reader_read_central_dir(pZip, flags))
2417   {
2418     mz_zip_reader_end(pZip);
2419     return MZ_FALSE;
2420   }
2421   return MZ_TRUE;
2422 }
2423 #endif // #ifndef MINIZ_NO_STDIO
2424
2425 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
2426 {
2427   return pZip ? pZip->m_total_files : 0;
2428 }
2429
2430 static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
2431 {
2432   if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
2433     return NULL;
2434   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));
2435 }
2436
2437 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
2438 {
2439   mz_uint m_bit_flag;
2440   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
2441   if (!p)
2442     return MZ_FALSE;
2443   m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
2444   return (m_bit_flag & 1);
2445 }
2446
2447 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
2448 {
2449   mz_uint filename_len, external_attr;
2450   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
2451   if (!p)
2452     return MZ_FALSE;
2453
2454   // First see if the filename ends with a '/' character.
2455   filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
2456   if (filename_len)
2457   {
2458     if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
2459       return MZ_TRUE;
2460   }
2461
2462   // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct.
2463   // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field.
2464   // FIXME: Remove this check? Is it necessary - we already check the filename.
2465   external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
2466   if ((external_attr & 0x10) != 0)
2467     return MZ_TRUE;
2468
2469   return MZ_FALSE;
2470 }
2471
2472 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
2473 {
2474   mz_uint n;
2475   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
2476   if ((!p) || (!pStat))
2477     return MZ_FALSE;
2478
2479   // Unpack the central directory record.
2480   pStat->m_file_index = file_index;
2481   pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
2482   pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
2483   pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
2484   pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
2485   pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
2486 #ifndef MINIZ_NO_TIME
2487   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));
2488 #endif
2489   pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
2490   pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
2491   pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
2492   pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
2493   pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
2494   pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
2495
2496   // Copy as much of the filename and comment as possible.
2497   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
2498   memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0';
2499
2500   n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
2501   pStat->m_comment_size = n;
2502   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); pStat->m_comment[n] = '\0';
2503
2504   return MZ_TRUE;
2505 }
2506
2507 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
2508 {
2509   mz_uint n;
2510   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
2511   if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; }
2512   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
2513   if (filename_buf_size)
2514   {
2515     n = MZ_MIN(n, filename_buf_size - 1);
2516     memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
2517     pFilename[n] = '\0';
2518   }
2519   return n + 1;
2520 }
2521
2522 static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
2523 {
2524   mz_uint i;
2525   if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
2526     return 0 == memcmp(pA, pB, len);
2527   for (i = 0; i < len; ++i)
2528     if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
2529       return MZ_FALSE;
2530   return MZ_TRUE;
2531 }
2532
2533 static MZ_FORCEINLINE int mz_zip_reader_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)
2534 {
2535   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;
2536   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
2537   mz_uint8 l = 0, r = 0;
2538   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
2539   pE = pL + MZ_MIN(l_len, r_len);
2540   while (pL < pE)
2541   {
2542     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
2543       break;
2544     pL++; pR++;
2545   }
2546   return (pL == pE) ? (int)(l_len - r_len) : (l - r);
2547 }
2548
2549 static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename)
2550 {
2551   mz_zip_internal_state *pState = pZip->m_pState;
2552   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
2553   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
2554   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
2555   const int size = pZip->m_total_files;
2556   const mz_uint filename_len = (mz_uint)strlen(pFilename);
2557   int l = 0, h = size - 1;
2558   while (l <= h)
2559   {
2560     int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
2561     if (!comp)
2562       return file_index;
2563     else if (comp < 0)
2564       l = m + 1;
2565     else
2566       h = m - 1;
2567   }
2568   return -1;
2569 }
2570
2571 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
2572 {
2573   mz_uint file_index; size_t name_len, comment_len;
2574   if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
2575     return -1;
2576   if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
2577     return mz_zip_reader_locate_file_binary_search(pZip, pName);
2578   name_len = strlen(pName); if (name_len > 0xFFFF) return -1;
2579   comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1;
2580   for (file_index = 0; file_index < pZip->m_total_files; file_index++)
2581   {
2582     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));
2583     mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
2584     const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
2585     if (filename_len < name_len)
2586       continue;
2587     if (comment_len)
2588     {
2589       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);
2590       const char *pFile_comment = pFilename + filename_len + file_extra_len;
2591       if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags)))
2592         continue;
2593     }
2594     if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
2595     {
2596       int ofs = filename_len - 1;
2597       do
2598       {
2599         if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
2600           break;
2601       } while (--ofs >= 0);
2602       ofs++;
2603       pFilename += ofs; filename_len -= ofs;
2604     }
2605     if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
2606       return file_index;
2607   }
2608   return -1;
2609 }
2610
2611 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)
2612 {
2613   int status = TINFL_STATUS_DONE;
2614   mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
2615   mz_zip_archive_file_stat file_stat;
2616   void *pRead_buf;
2617   mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
2618   tinfl_decompressor inflator;
2619
2620   if ((buf_size) && (!pBuf))
2621     return MZ_FALSE;
2622
2623   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
2624     return MZ_FALSE;
2625
2626   // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
2627   if (!file_stat.m_comp_size)
2628     return MZ_TRUE;
2629
2630   // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
2631   // I'm torn how to handle this case - should it fail instead?
2632   if (mz_zip_reader_is_file_a_directory(pZip, file_index))
2633     return MZ_TRUE;
2634
2635   // Encryption and patch files are not supported.
2636   if (file_stat.m_bit_flag & (1 | 32))
2637     return MZ_FALSE;
2638
2639   // This function only supports stored and deflate.
2640   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
2641     return MZ_FALSE;
2642
2643   // Ensure supplied output buffer is large enough.
2644   needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
2645   if (buf_size < needed_size)
2646     return MZ_FALSE;
2647
2648   // Read and parse the local directory entry.
2649   cur_file_ofs = file_stat.m_local_header_ofs;
2650   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)
2651     return MZ_FALSE;
2652   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
2653     return MZ_FALSE;
2654
2655   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);
2656   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
2657     return MZ_FALSE;
2658
2659   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
2660   {
2661     // The file is stored or the caller has requested the compressed data.
2662     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
2663       return MZ_FALSE;
2664     return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
2665   }
2666
2667   // Decompress the file either directly from memory or from a file input buffer.
2668   tinfl_init(&inflator);
2669
2670   if (pZip->m_pState->m_pMem)
2671   {
2672     // Read directly from the archive in memory.
2673     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
2674     read_buf_size = read_buf_avail = file_stat.m_comp_size;
2675     comp_remaining = 0;
2676   }
2677   else if (pUser_read_buf)
2678   {
2679     // Use a user provided read buffer.
2680     if (!user_read_buf_size)
2681       return MZ_FALSE;
2682     pRead_buf = (mz_uint8 *)pUser_read_buf;
2683     read_buf_size = user_read_buf_size;
2684     read_buf_avail = 0;
2685     comp_remaining = file_stat.m_comp_size;
2686   }
2687   else
2688   {
2689     // Temporarily allocate a read buffer.
2690     read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
2691 #ifdef _MSC_VER
2692     if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
2693 #else
2694     if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
2695 #endif
2696       return MZ_FALSE;
2697     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
2698       return MZ_FALSE;
2699     read_buf_avail = 0;
2700     comp_remaining = file_stat.m_comp_size;
2701   }
2702
2703   do
2704   {
2705     size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
2706     if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
2707     {
2708       read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
2709       if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
2710       {
2711         status = TINFL_STATUS_FAILED;
2712         break;
2713       }
2714       cur_file_ofs += read_buf_avail;
2715       comp_remaining -= read_buf_avail;
2716       read_buf_ofs = 0;
2717     }
2718     in_buf_size = (size_t)read_buf_avail;
2719     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));
2720     read_buf_avail -= in_buf_size;
2721     read_buf_ofs += in_buf_size;
2722     out_buf_ofs += out_buf_size;
2723   } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
2724
2725   if (status == TINFL_STATUS_DONE)
2726   {
2727     // Make sure the entire file was decompressed, and check its CRC.
2728     if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
2729       status = TINFL_STATUS_FAILED;
2730   }
2731
2732   if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
2733     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
2734
2735   return status == TINFL_STATUS_DONE;
2736 }
2737
2738 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)
2739 {
2740   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
2741   if (file_index < 0)
2742     return MZ_FALSE;
2743   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
2744 }
2745
2746 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)
2747 {
2748   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
2749 }
2750
2751 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)
2752 {
2753   return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
2754 }
2755
2756 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
2757 {
2758   mz_uint64 comp_size, uncomp_size, alloc_size;
2759   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
2760   void *pBuf;
2761
2762   if (pSize)
2763     *pSize = 0;
2764   if (!p)
2765     return NULL;
2766
2767   comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
2768   uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
2769
2770   alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
2771 #ifdef _MSC_VER
2772   if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
2773 #else
2774   if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
2775 #endif
2776     return NULL;
2777   if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
2778     return NULL;
2779
2780   if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
2781   {
2782     pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
2783     return NULL;
2784   }
2785
2786   if (pSize) *pSize = (size_t)alloc_size;
2787   return pBuf;
2788 }
2789
2790 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
2791 {
2792   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
2793   if (file_index < 0)
2794   {
2795     if (pSize) *pSize = 0;
2796     return MZ_FALSE;
2797   }
2798   return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
2799 }
2800
2801 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)
2802 {
2803   int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT;
2804   mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
2805   mz_zip_archive_file_stat file_stat;
2806   void *pRead_buf = NULL; void *pWrite_buf = NULL;
2807   mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
2808
2809   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
2810     return MZ_FALSE;
2811
2812   // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes)
2813   if (!file_stat.m_comp_size)
2814     return MZ_TRUE;
2815
2816   // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers).
2817   // I'm torn how to handle this case - should it fail instead?
2818   if (mz_zip_reader_is_file_a_directory(pZip, file_index))
2819     return MZ_TRUE;
2820
2821   // Encryption and patch files are not supported.
2822   if (file_stat.m_bit_flag & (1 | 32))
2823     return MZ_FALSE;
2824
2825   // This function only supports stored and deflate.
2826   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
2827     return MZ_FALSE;
2828
2829   // Read and parse the local directory entry.
2830   cur_file_ofs = file_stat.m_local_header_ofs;
2831   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)
2832     return MZ_FALSE;
2833   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
2834     return MZ_FALSE;
2835
2836   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);
2837   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
2838     return MZ_FALSE;
2839
2840   // Decompress the file either directly from memory or from a file input buffer.
2841   if (pZip->m_pState->m_pMem)
2842   {
2843     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
2844     read_buf_size = read_buf_avail = file_stat.m_comp_size;
2845     comp_remaining = 0;
2846   }
2847   else
2848   {
2849     read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
2850     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
2851       return MZ_FALSE;
2852     read_buf_avail = 0;
2853     comp_remaining = file_stat.m_comp_size;
2854   }
2855
2856   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
2857   {
2858     // The file is stored or the caller has requested the compressed data.
2859     if (pZip->m_pState->m_pMem)
2860     {
2861 #ifdef _MSC_VER
2862       if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
2863 #else
2864       if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF))
2865 #endif
2866         return MZ_FALSE;
2867       if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
2868         status = TINFL_STATUS_FAILED;
2869       else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
2870         file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
2871       cur_file_ofs += file_stat.m_comp_size;
2872       out_buf_ofs += file_stat.m_comp_size;
2873       comp_remaining = 0;
2874     }
2875     else
2876     {
2877       while (comp_remaining)
2878       {
2879         read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
2880         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
2881         {
2882           status = TINFL_STATUS_FAILED;
2883           break;
2884         }
2885
2886         if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
2887           file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
2888
2889         if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
2890         {
2891           status = TINFL_STATUS_FAILED;
2892           break;
2893         }
2894         cur_file_ofs += read_buf_avail;
2895         out_buf_ofs += read_buf_avail;
2896         comp_remaining -= read_buf_avail;
2897       }
2898     }
2899   }
2900   else
2901   {
2902     tinfl_decompressor inflator;
2903     tinfl_init(&inflator);
2904
2905     if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
2906       status = TINFL_STATUS_FAILED;
2907     else
2908     {
2909       do
2910       {
2911         mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
2912         size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
2913         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
2914         {
2915           read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
2916           if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
2917           {
2918             status = TINFL_STATUS_FAILED;
2919             break;
2920           }
2921           cur_file_ofs += read_buf_avail;
2922           comp_remaining -= read_buf_avail;
2923           read_buf_ofs = 0;
2924         }
2925
2926         in_buf_size = (size_t)read_buf_avail;
2927         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);
2928         read_buf_avail -= in_buf_size;
2929         read_buf_ofs += in_buf_size;
2930
2931         if (out_buf_size)
2932         {
2933           if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
2934           {
2935             status = TINFL_STATUS_FAILED;
2936             break;
2937           }
2938           file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
2939           if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
2940           {
2941             status = TINFL_STATUS_FAILED;
2942             break;
2943           }
2944         }
2945       } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
2946     }
2947   }
2948
2949   if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
2950   {
2951     // Make sure the entire file was decompressed, and check its CRC.
2952     if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32))
2953       status = TINFL_STATUS_FAILED;
2954   }
2955
2956   if (!pZip->m_pState->m_pMem)
2957     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
2958   if (pWrite_buf)
2959     pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
2960
2961   return status == TINFL_STATUS_DONE;
2962 }
2963
2964 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)
2965 {
2966   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
2967   if (file_index < 0)
2968     return MZ_FALSE;
2969   return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
2970 }
2971
2972 #ifndef MINIZ_NO_STDIO
2973 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
2974 {
2975   (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque);
2976 }
2977
2978 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
2979 {
2980   mz_bool status;
2981   mz_zip_archive_file_stat file_stat;
2982   MZ_FILE *pFile;
2983   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
2984     return MZ_FALSE;
2985   pFile = MZ_FOPEN(pDst_filename, "wb");
2986   if (!pFile)
2987     return MZ_FALSE;
2988   status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
2989   if (MZ_FCLOSE(pFile) == EOF)
2990     return MZ_FALSE;
2991 #ifndef MINIZ_NO_TIME
2992   if (status)
2993     mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
2994 #endif
2995   return status;
2996 }
2997 #endif // #ifndef MINIZ_NO_STDIO
2998
2999 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3000 {
3001   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3002     return MZ_FALSE;
3003
3004   if (pZip->m_pState)
3005   {
3006     mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL;
3007     mz_zip_array_clear(pZip, &pState->m_central_dir);
3008     mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3009     mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3010
3011 #ifndef MINIZ_NO_STDIO
3012     if (pState->m_pFile)
3013     {
3014       MZ_FCLOSE(pState->m_pFile);
3015       pState->m_pFile = NULL;
3016     }
3017 #endif // #ifndef MINIZ_NO_STDIO
3018
3019     pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3020   }
3021   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3022
3023   return MZ_TRUE;
3024 }
3025
3026 #ifndef MINIZ_NO_STDIO
3027 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
3028 {
3029   int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
3030   if (file_index < 0)
3031     return MZ_FALSE;
3032   return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
3033 }
3034 #endif
3035
3036 // ------------------- .ZIP archive writing
3037
3038 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3039
3040 static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); }
3041 static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); }
3042 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
3043 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
3044
3045 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
3046 {
3047   if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3048     return MZ_FALSE;
3049
3050   if (pZip->m_file_offset_alignment)
3051   {
3052     // Ensure user specified file offset alignment is a power of 2.
3053     if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
3054       return MZ_FALSE;
3055   }
3056
3057   if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func;
3058   if (!pZip->m_pFree) pZip->m_pFree = def_free_func;
3059   if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func;
3060
3061   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
3062   pZip->m_archive_size = existing_size;
3063   pZip->m_central_directory_file_ofs = 0;
3064   pZip->m_total_files = 0;
3065
3066   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3067     return MZ_FALSE;
3068   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3069   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3070   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3071   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3072   return MZ_TRUE;
3073 }
3074
3075 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
3076 {
3077   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3078   mz_zip_internal_state *pState = pZip->m_pState;
3079   mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
3080 #ifdef _MSC_VER
3081   if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
3082 #else
3083   if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
3084 #endif
3085     return 0;
3086   if (new_size > pState->m_mem_capacity)
3087   {
3088     void *pNew_block;
3089     size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2;
3090     if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
3091       return 0;
3092     pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity;
3093   }
3094   memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
3095   pState->m_mem_size = (size_t)new_size;
3096   return n;
3097 }
3098
3099 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
3100 {
3101   pZip->m_pWrite = mz_zip_heap_write_func;
3102   pZip->m_pIO_opaque = pZip;
3103   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
3104     return MZ_FALSE;
3105   if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
3106   {
3107     if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
3108     {
3109       mz_zip_writer_end(pZip);
3110       return MZ_FALSE;
3111     }
3112     pZip->m_pState->m_mem_capacity = initial_allocation_size;
3113   }
3114   return MZ_TRUE;
3115 }
3116
3117 #ifndef MINIZ_NO_STDIO
3118 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
3119 {
3120   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3121   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3122   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))))
3123     return 0;
3124   return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
3125 }
3126
3127 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
3128 {
3129   MZ_FILE *pFile;
3130   pZip->m_pWrite = mz_zip_file_write_func;
3131   pZip->m_pIO_opaque = pZip;
3132   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
3133     return MZ_FALSE;
3134   if (NULL == (pFile = MZ_FOPEN(pFilename, "wb")))
3135   {
3136     mz_zip_writer_end(pZip);
3137     return MZ_FALSE;
3138   }
3139   pZip->m_pState->m_pFile = pFile;
3140   if (size_to_reserve_at_beginning)
3141   {
3142     mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf);
3143     do
3144     {
3145       size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
3146       if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
3147       {
3148         mz_zip_writer_end(pZip);
3149         return MZ_FALSE;
3150       }
3151       cur_ofs += n; size_to_reserve_at_beginning -= n;
3152     } while (size_to_reserve_at_beginning);
3153   }
3154   return MZ_TRUE;
3155 }
3156 #endif // #ifndef MINIZ_NO_STDIO
3157
3158 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
3159 {
3160   mz_zip_internal_state *pState;
3161   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3162     return MZ_FALSE;
3163   // No sense in trying to write to an archive that's already at the support max size
3164   if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
3165     return MZ_FALSE;
3166
3167   pState = pZip->m_pState;
3168
3169   if (pState->m_pFile)
3170   {
3171 #ifdef MINIZ_NO_STDIO
3172     pFilename; return MZ_FALSE;
3173 #else
3174     // Archive is being read from stdio - try to reopen as writable.
3175     if (pZip->m_pIO_opaque != pZip)
3176       return MZ_FALSE;
3177     if (!pFilename)
3178       return MZ_FALSE;
3179     pZip->m_pWrite = mz_zip_file_write_func;
3180     if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
3181     {
3182       // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it.
3183       mz_zip_reader_end(pZip);
3184       return MZ_FALSE;
3185     }
3186 #endif // #ifdef MINIZ_NO_STDIO
3187   }
3188   else if (pState->m_pMem)
3189   {
3190     // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback.
3191     if (pZip->m_pIO_opaque != pZip)
3192       return MZ_FALSE;
3193     pState->m_mem_capacity = pState->m_mem_size;
3194     pZip->m_pWrite = mz_zip_heap_write_func;
3195   }
3196   // Archive is being read via a user provided read function - make sure the user has specified a write function too.
3197   else if (!pZip->m_pWrite)
3198     return MZ_FALSE;
3199
3200   // Start writing new files at the archive's current central directory location.
3201   pZip->m_archive_size = pZip->m_central_directory_file_ofs;
3202   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
3203   pZip->m_central_directory_file_ofs = 0;
3204
3205   return MZ_TRUE;
3206 }
3207
3208 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)
3209 {
3210   return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
3211 }
3212
3213 typedef struct
3214 {
3215   mz_zip_archive *m_pZip;
3216   mz_uint64 m_cur_archive_file_ofs;
3217   mz_uint64 m_comp_size;
3218 } mz_zip_writer_add_state;
3219
3220 static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser)
3221 {
3222   mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
3223   if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
3224     return MZ_FALSE;
3225   pState->m_cur_archive_file_ofs += len;
3226   pState->m_comp_size += len;
3227   return MZ_TRUE;
3228 }
3229
3230 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)
3231 {
3232   (void)pZip;
3233   memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
3234   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
3235   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
3236   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
3237   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
3238   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
3239   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
3240   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
3241   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
3242   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
3243   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
3244   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
3245   return MZ_TRUE;
3246 }
3247
3248 static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
3249 {
3250   (void)pZip;
3251   memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
3252   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
3253   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
3254   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
3255   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
3256   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
3257   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
3258   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
3259   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
3260   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
3261   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
3262   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
3263   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
3264   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
3265   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
3266   return MZ_TRUE;
3267 }
3268
3269 static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
3270 {
3271   mz_zip_internal_state *pState = pZip->m_pState;
3272   mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
3273   size_t orig_central_dir_size = pState->m_central_dir.m_size;
3274   mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
3275
3276   // No zip64 support yet
3277   if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF))
3278     return MZ_FALSE;
3279
3280   if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
3281     return MZ_FALSE;
3282
3283   if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
3284       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
3285       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
3286       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
3287       (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
3288   {
3289     // Try to push the central directory array back into its original state.
3290     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
3291     return MZ_FALSE;
3292   }
3293
3294   return MZ_TRUE;
3295 }
3296
3297 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
3298 {
3299   // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes.
3300   if (*pArchive_name == '/')
3301     return MZ_FALSE;
3302   while (*pArchive_name)
3303   {
3304     if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
3305       return MZ_FALSE;
3306     pArchive_name++;
3307   }
3308   return MZ_TRUE;
3309 }
3310
3311 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
3312 {
3313   mz_uint32 n;
3314   if (!pZip->m_file_offset_alignment)
3315     return 0;
3316   n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
3317   return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1);
3318 }
3319
3320 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
3321 {
3322   char buf[4096];
3323   memset(buf, 0, MZ_MIN(sizeof(buf), n));
3324   while (n)
3325   {
3326     mz_uint32 s = MZ_MIN(sizeof(buf), n);
3327     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
3328       return MZ_FALSE;
3329     cur_file_ofs += s; n -= s;
3330   }
3331   return MZ_TRUE;
3332 }
3333
3334 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
3335 {
3336   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
3337   mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
3338   mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
3339   size_t archive_name_size;
3340   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
3341   tdefl_compressor *pComp = NULL;
3342   mz_bool store_data_uncompressed;
3343   mz_zip_internal_state *pState;
3344
3345   if ((int)level_and_flags < 0)
3346     level_and_flags = MZ_DEFAULT_LEVEL;
3347   level = level_and_flags & 0xF;
3348   store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
3349
3350   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
3351     return MZ_FALSE;
3352
3353   pState = pZip->m_pState;
3354
3355   if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
3356     return MZ_FALSE;
3357   // No zip64 support yet
3358   if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
3359     return MZ_FALSE;
3360   if (!mz_zip_writer_validate_archive_name(pArchive_name))
3361     return MZ_FALSE;
3362
3363 #ifndef MINIZ_NO_TIME
3364   {
3365     time_t cur_time; time(&cur_time);
3366     mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date);
3367   }
3368 #endif // #ifndef MINIZ_NO_TIME
3369
3370   archive_name_size = strlen(pArchive_name);
3371   if (archive_name_size > 0xFFFF)
3372     return MZ_FALSE;
3373
3374   num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
3375
3376   // no zip64 support yet
3377   if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
3378     return MZ_FALSE;
3379
3380   if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
3381   {
3382     // Set DOS Subdirectory attribute bit.
3383     ext_attributes |= 0x10;
3384     // Subdirectories cannot contain data.
3385     if ((buf_size) || (uncomp_size))
3386       return MZ_FALSE;
3387   }
3388
3389   // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
3390   if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
3391     return MZ_FALSE;
3392
3393   if ((!store_data_uncompressed) && (buf_size))
3394   {
3395     if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
3396       return MZ_FALSE;
3397   }
3398
3399   if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
3400   {
3401     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3402     return MZ_FALSE;
3403   }
3404   local_dir_header_ofs += num_alignment_padding_bytes;
3405   if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
3406   cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
3407
3408   MZ_CLEAR_OBJ(local_dir_header);
3409   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
3410   {
3411     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3412     return MZ_FALSE;
3413   }
3414   cur_archive_file_ofs += archive_name_size;
3415
3416   if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
3417   {
3418     uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
3419     uncomp_size = buf_size;
3420     if (uncomp_size <= 3)
3421     {
3422       level = 0;
3423       store_data_uncompressed = MZ_TRUE;
3424     }
3425   }
3426
3427   if (store_data_uncompressed)
3428   {
3429     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
3430     {
3431       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3432       return MZ_FALSE;
3433     }
3434
3435     cur_archive_file_ofs += buf_size;
3436     comp_size = buf_size;
3437
3438     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
3439       method = MZ_DEFLATED;
3440   }
3441   else if (buf_size)
3442   {
3443     mz_zip_writer_add_state state;
3444
3445     state.m_pZip = pZip;
3446     state.m_cur_archive_file_ofs = cur_archive_file_ofs;
3447     state.m_comp_size = 0;
3448
3449     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) ||
3450         (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
3451     {
3452       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3453       return MZ_FALSE;
3454     }
3455
3456     comp_size = state.m_comp_size;
3457     cur_archive_file_ofs = state.m_cur_archive_file_ofs;
3458
3459     method = MZ_DEFLATED;
3460   }
3461
3462   pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3463   pComp = NULL;
3464
3465   // no zip64 support yet
3466   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
3467     return MZ_FALSE;
3468
3469   if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
3470     return MZ_FALSE;
3471
3472   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
3473     return MZ_FALSE;
3474
3475   if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
3476     return MZ_FALSE;
3477
3478   pZip->m_total_files++;
3479   pZip->m_archive_size = cur_archive_file_ofs;
3480
3481   return MZ_TRUE;
3482 }
3483
3484 mz_bool mz_zip_writer_add_mem_ex_with_time(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, mz_uint16 dos_time, mz_uint16 dos_date)
3485 {
3486   mz_uint16 method = 0;
3487   mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
3488   mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
3489   size_t archive_name_size;
3490   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
3491   tdefl_compressor *pComp = NULL;
3492   mz_bool store_data_uncompressed;
3493   mz_zip_internal_state *pState;
3494
3495   if ((int)level_and_flags < 0)
3496     level_and_flags = MZ_DEFAULT_LEVEL;
3497   level = level_and_flags & 0xF;
3498   store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
3499
3500   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
3501     return MZ_FALSE;
3502
3503   pState = pZip->m_pState;
3504
3505   if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
3506     return MZ_FALSE;
3507   // No zip64 support yet
3508   if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
3509     return MZ_FALSE;
3510   if (!mz_zip_writer_validate_archive_name(pArchive_name))
3511     return MZ_FALSE;
3512
3513   archive_name_size = strlen(pArchive_name);
3514   if (archive_name_size > 0xFFFF)
3515     return MZ_FALSE;
3516
3517   num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
3518
3519   // no zip64 support yet
3520   if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
3521     return MZ_FALSE;
3522
3523   if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
3524   {
3525     // Set DOS Subdirectory attribute bit.
3526     ext_attributes |= 0x10;
3527     // Subdirectories cannot contain data.
3528     if ((buf_size) || (uncomp_size))
3529       return MZ_FALSE;
3530   }
3531
3532   // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.)
3533   if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
3534     return MZ_FALSE;
3535
3536   if ((!store_data_uncompressed) && (buf_size))
3537   {
3538     if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
3539       return MZ_FALSE;
3540   }
3541
3542   if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
3543   {
3544     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3545     return MZ_FALSE;
3546   }
3547   local_dir_header_ofs += num_alignment_padding_bytes;
3548   if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
3549   cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
3550
3551   MZ_CLEAR_OBJ(local_dir_header);
3552   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
3553   {
3554     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3555     return MZ_FALSE;
3556   }
3557   cur_archive_file_ofs += archive_name_size;
3558
3559   if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
3560   {
3561     uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size);
3562     uncomp_size = buf_size;
3563     if (uncomp_size <= 3)
3564     {
3565       level = 0;
3566       store_data_uncompressed = MZ_TRUE;
3567     }
3568   }
3569
3570   if (store_data_uncompressed)
3571   {
3572     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
3573     {
3574       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3575       return MZ_FALSE;
3576     }
3577
3578     cur_archive_file_ofs += buf_size;
3579     comp_size = buf_size;
3580
3581     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
3582       method = MZ_DEFLATED;
3583   }
3584   else if (buf_size)
3585   {
3586     mz_zip_writer_add_state state;
3587
3588     state.m_pZip = pZip;
3589     state.m_cur_archive_file_ofs = cur_archive_file_ofs;
3590     state.m_comp_size = 0;
3591
3592     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) ||
3593         (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
3594     {
3595       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3596       return MZ_FALSE;
3597     }
3598
3599     comp_size = state.m_comp_size;
3600     cur_archive_file_ofs = state.m_cur_archive_file_ofs;
3601
3602     method = MZ_DEFLATED;
3603   }
3604
3605   pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3606   pComp = NULL;
3607
3608   // no zip64 support yet
3609   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
3610     return MZ_FALSE;
3611
3612   if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
3613     return MZ_FALSE;
3614
3615   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
3616     return MZ_FALSE;
3617
3618   if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
3619     return MZ_FALSE;
3620
3621   pZip->m_total_files++;
3622   pZip->m_archive_size = cur_archive_file_ofs;
3623
3624   return MZ_TRUE;
3625 }
3626
3627 #ifndef MINIZ_NO_STDIO
3628 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)
3629 {
3630   mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
3631   mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
3632   mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
3633   size_t archive_name_size;
3634   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
3635   MZ_FILE *pSrc_file = NULL;
3636
3637   if ((int)level_and_flags < 0)
3638     level_and_flags = MZ_DEFAULT_LEVEL;
3639   level = level_and_flags & 0xF;
3640
3641   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
3642     return MZ_FALSE;
3643   if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
3644     return MZ_FALSE;
3645   if (!mz_zip_writer_validate_archive_name(pArchive_name))
3646     return MZ_FALSE;
3647
3648   archive_name_size = strlen(pArchive_name);
3649   if (archive_name_size > 0xFFFF)
3650     return MZ_FALSE;
3651
3652   num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
3653
3654   // no zip64 support yet
3655   if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF))
3656     return MZ_FALSE;
3657
3658   if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date))
3659     return MZ_FALSE;
3660
3661   pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
3662   if (!pSrc_file)
3663     return MZ_FALSE;
3664   MZ_FSEEK64(pSrc_file, 0, SEEK_END);
3665   uncomp_size = MZ_FTELL64(pSrc_file);
3666   MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
3667
3668   if (uncomp_size > 0xFFFFFFFF)
3669   {
3670     // No zip64 support yet
3671     MZ_FCLOSE(pSrc_file);
3672     return MZ_FALSE;
3673   }
3674   if (uncomp_size <= 3)
3675     level = 0;
3676
3677   if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header)))
3678   {
3679     MZ_FCLOSE(pSrc_file);
3680     return MZ_FALSE;
3681   }
3682   local_dir_header_ofs += num_alignment_padding_bytes;
3683   if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
3684   cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header);
3685
3686   MZ_CLEAR_OBJ(local_dir_header);
3687   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
3688   {
3689     MZ_FCLOSE(pSrc_file);
3690     return MZ_FALSE;
3691   }
3692   cur_archive_file_ofs += archive_name_size;
3693
3694   if (uncomp_size)
3695   {
3696     mz_uint64 uncomp_remaining = uncomp_size;
3697     void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
3698     if (!pRead_buf)
3699     {
3700       MZ_FCLOSE(pSrc_file);
3701       return MZ_FALSE;
3702     }
3703
3704     if (!level)
3705     {
3706       while (uncomp_remaining)
3707       {
3708         mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
3709         if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
3710         {
3711           pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3712           MZ_FCLOSE(pSrc_file);
3713           return MZ_FALSE;
3714         }
3715         uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
3716         uncomp_remaining -= n;
3717         cur_archive_file_ofs += n;
3718       }
3719       comp_size = uncomp_size;
3720     }
3721     else
3722     {
3723       mz_bool result = MZ_FALSE;
3724       mz_zip_writer_add_state state;
3725       tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
3726       if (!pComp)
3727       {
3728         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3729         MZ_FCLOSE(pSrc_file);
3730         return MZ_FALSE;
3731       }
3732
3733       state.m_pZip = pZip;
3734       state.m_cur_archive_file_ofs = cur_archive_file_ofs;
3735       state.m_comp_size = 0;
3736
3737       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)
3738       {
3739         pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3740         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3741         MZ_FCLOSE(pSrc_file);
3742         return MZ_FALSE;
3743       }
3744
3745       for ( ; ; )
3746       {
3747         size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
3748         tdefl_status status;
3749
3750         if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
3751           break;
3752
3753         uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
3754         uncomp_remaining -= in_buf_size;
3755
3756         status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
3757         if (status == TDEFL_STATUS_DONE)
3758         {
3759           result = MZ_TRUE;
3760           break;
3761         }
3762         else if (status != TDEFL_STATUS_OKAY)
3763           break;
3764       }
3765
3766       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
3767
3768       if (!result)
3769       {
3770         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3771         MZ_FCLOSE(pSrc_file);
3772         return MZ_FALSE;
3773       }
3774
3775       comp_size = state.m_comp_size;
3776       cur_archive_file_ofs = state.m_cur_archive_file_ofs;
3777
3778       method = MZ_DEFLATED;
3779     }
3780
3781     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
3782   }
3783
3784   MZ_FCLOSE(pSrc_file); pSrc_file = NULL;
3785
3786   // no zip64 support yet
3787   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
3788     return MZ_FALSE;
3789
3790   if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
3791     return MZ_FALSE;
3792
3793   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
3794     return MZ_FALSE;
3795
3796   if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes))
3797     return MZ_FALSE;
3798
3799   pZip->m_total_files++;
3800   pZip->m_archive_size = cur_archive_file_ofs;
3801
3802   return MZ_TRUE;
3803 }
3804 #endif // #ifndef MINIZ_NO_STDIO
3805
3806 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index)
3807 {
3808   mz_uint n, bit_flags, num_alignment_padding_bytes;
3809   mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
3810   mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
3811   mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
3812   mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
3813   size_t orig_central_dir_size;
3814   mz_zip_internal_state *pState;
3815   void *pBuf; const mz_uint8 *pSrc_central_header;
3816
3817   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
3818     return MZ_FALSE;
3819   if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
3820     return MZ_FALSE;
3821   pState = pZip->m_pState;
3822
3823   num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
3824
3825   // no zip64 support yet
3826   if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
3827     return MZ_FALSE;
3828
3829   cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3830   cur_dst_file_ofs = pZip->m_archive_size;
3831
3832   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)
3833     return MZ_FALSE;
3834   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
3835     return MZ_FALSE;
3836   cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
3837
3838   if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
3839     return MZ_FALSE;
3840   cur_dst_file_ofs += num_alignment_padding_bytes;
3841   local_dir_header_ofs = cur_dst_file_ofs;
3842   if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); }
3843
3844   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)
3845     return MZ_FALSE;
3846   cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
3847
3848   n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
3849   comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3850
3851   if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining)))))
3852     return MZ_FALSE;
3853
3854   while (comp_bytes_remaining)
3855   {
3856     n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
3857     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
3858     {
3859       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3860       return MZ_FALSE;
3861     }
3862     cur_src_file_ofs += n;
3863
3864     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
3865     {
3866       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3867       return MZ_FALSE;
3868     }
3869     cur_dst_file_ofs += n;
3870
3871     comp_bytes_remaining -= n;
3872   }
3873
3874   bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
3875   if (bit_flags & 8)
3876   {
3877     // Copy data descriptor
3878     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
3879     {
3880       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3881       return MZ_FALSE;
3882     }
3883
3884     n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
3885     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
3886     {
3887       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3888       return MZ_FALSE;
3889     }
3890
3891     cur_src_file_ofs += n;
3892     cur_dst_file_ofs += n;
3893   }
3894   pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
3895
3896   // no zip64 support yet
3897   if (cur_dst_file_ofs > 0xFFFFFFFF)
3898     return MZ_FALSE;
3899
3900   orig_central_dir_size = pState->m_central_dir.m_size;
3901
3902   memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
3903   MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
3904   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
3905     return MZ_FALSE;
3906
3907   n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
3908   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n))
3909   {
3910     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
3911     return MZ_FALSE;
3912   }
3913
3914   if (pState->m_central_dir.m_size > 0xFFFFFFFF)
3915     return MZ_FALSE;
3916   n = (mz_uint32)orig_central_dir_size;
3917   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
3918   {
3919     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
3920     return MZ_FALSE;
3921   }
3922
3923   pZip->m_total_files++;
3924   pZip->m_archive_size = cur_dst_file_ofs;
3925
3926   return MZ_TRUE;
3927 }
3928
3929 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
3930 {
3931   mz_zip_internal_state *pState;
3932   mz_uint64 central_dir_ofs, central_dir_size;
3933   mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
3934
3935   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
3936     return MZ_FALSE;
3937
3938   pState = pZip->m_pState;
3939
3940   // no zip64 support yet
3941   if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
3942     return MZ_FALSE;
3943
3944   central_dir_ofs = 0;
3945   central_dir_size = 0;
3946   if (pZip->m_total_files)
3947   {
3948     // Write central directory
3949     central_dir_ofs = pZip->m_archive_size;
3950     central_dir_size = pState->m_central_dir.m_size;
3951     pZip->m_central_directory_file_ofs = central_dir_ofs;
3952     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)
3953       return MZ_FALSE;
3954     pZip->m_archive_size += central_dir_size;
3955   }
3956
3957   // Write end of central directory record
3958   MZ_CLEAR_OBJ(hdr);
3959   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
3960   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
3961   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
3962   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
3963   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
3964
3965   if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr))
3966     return MZ_FALSE;
3967 #ifndef MINIZ_NO_STDIO
3968   if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
3969     return MZ_FALSE;
3970 #endif // #ifndef MINIZ_NO_STDIO
3971
3972   pZip->m_archive_size += sizeof(hdr);
3973
3974   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
3975   return MZ_TRUE;
3976 }
3977
3978 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize)
3979 {
3980   if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
3981     return MZ_FALSE;
3982   if (pZip->m_pWrite != mz_zip_heap_write_func)
3983     return MZ_FALSE;
3984   if (!mz_zip_writer_finalize_archive(pZip))
3985     return MZ_FALSE;
3986
3987   *pBuf = pZip->m_pState->m_pMem;
3988   *pSize = pZip->m_pState->m_mem_size;
3989   pZip->m_pState->m_pMem = NULL;
3990   pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
3991   return MZ_TRUE;
3992 }
3993
3994 mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
3995 {
3996   mz_zip_internal_state *pState;
3997   mz_bool status = MZ_TRUE;
3998   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)))
3999     return MZ_FALSE;
4000
4001   pState = pZip->m_pState;
4002   pZip->m_pState = NULL;
4003   mz_zip_array_clear(pZip, &pState->m_central_dir);
4004   mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
4005   mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
4006
4007 #ifndef MINIZ_NO_STDIO
4008   if (pState->m_pFile)
4009   {
4010     MZ_FCLOSE(pState->m_pFile);
4011     pState->m_pFile = NULL;
4012   }
4013 #endif // #ifndef MINIZ_NO_STDIO
4014
4015   if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
4016   {
4017     pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
4018     pState->m_pMem = NULL;
4019   }
4020
4021   pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4022   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
4023   return status;
4024 }
4025
4026 #ifndef MINIZ_NO_STDIO
4027 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)
4028 {
4029   mz_bool status, created_new_archive = MZ_FALSE;
4030   mz_zip_archive zip_archive;
4031   struct MZ_FILE_STAT_STRUCT file_stat;
4032   MZ_CLEAR_OBJ(zip_archive);
4033   if ((int)level_and_flags < 0)
4034      level_and_flags = MZ_DEFAULT_LEVEL;
4035   if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
4036     return MZ_FALSE;
4037   if (!mz_zip_writer_validate_archive_name(pArchive_name))
4038     return MZ_FALSE;
4039   if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
4040   {
4041     // Create a new archive.
4042     if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
4043       return MZ_FALSE;
4044     created_new_archive = MZ_TRUE;
4045   }
4046   else
4047   {
4048     // Append to an existing archive.
4049     if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4050       return MZ_FALSE;
4051     if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
4052     {
4053       mz_zip_reader_end(&zip_archive);
4054       return MZ_FALSE;
4055     }
4056   }
4057   status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
4058   // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
4059   if (!mz_zip_writer_finalize_archive(&zip_archive))
4060     status = MZ_FALSE;
4061   if (!mz_zip_writer_end(&zip_archive))
4062     status = MZ_FALSE;
4063   if ((!status) && (created_new_archive))
4064   {
4065     // It's a new archive and something went wrong, so just delete it.
4066     int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
4067     (void)ignoredStatus;
4068   }
4069   return status;
4070 }
4071
4072 mz_bool mz_zip_add_mem_to_archive_file_in_place_with_time(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_uint16 dos_time, mz_uint16 dos_date)
4073 {
4074   mz_bool status, created_new_archive = MZ_FALSE;
4075   mz_zip_archive zip_archive;
4076   struct MZ_FILE_STAT_STRUCT file_stat;
4077   MZ_CLEAR_OBJ(zip_archive);
4078   if ((int)level_and_flags < 0)
4079      level_and_flags = MZ_DEFAULT_LEVEL;
4080   if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
4081     return MZ_FALSE;
4082   if (!mz_zip_writer_validate_archive_name(pArchive_name))
4083     return MZ_FALSE;
4084   if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
4085   {
4086     // Create a new archive.
4087     if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
4088       return MZ_FALSE;
4089     created_new_archive = MZ_TRUE;
4090   }
4091   else
4092   {
4093     // Append to an existing archive.
4094     if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4095       return MZ_FALSE;
4096     if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename))
4097     {
4098       mz_zip_reader_end(&zip_archive);
4099       return MZ_FALSE;
4100     }
4101   }
4102   status = mz_zip_writer_add_mem_ex_with_time(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0, dos_time, dos_date);
4103   // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.)
4104   if (!mz_zip_writer_finalize_archive(&zip_archive))
4105     status = MZ_FALSE;
4106   if (!mz_zip_writer_end(&zip_archive))
4107     status = MZ_FALSE;
4108   if ((!status) && (created_new_archive))
4109   {
4110     // It's a new archive and something went wrong, so just delete it.
4111     int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
4112     (void)ignoredStatus;
4113   }
4114   return status;
4115 }
4116
4117
4118 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
4119 {
4120   int file_index;
4121   mz_zip_archive zip_archive;
4122   void *p = NULL;
4123
4124   if (pSize)
4125     *pSize = 0;
4126
4127   if ((!pZip_filename) || (!pArchive_name))
4128     return NULL;
4129
4130   MZ_CLEAR_OBJ(zip_archive);
4131   if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
4132     return NULL;
4133
4134   if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0)
4135     p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
4136
4137   mz_zip_reader_end(&zip_archive);
4138   return p;
4139 }
4140
4141 #endif // #ifndef MINIZ_NO_STDIO
4142
4143 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4144
4145 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
4146
4147 #ifdef __cplusplus
4148 }
4149 #endif
4150
4151 #endif // MINIZ_HEADER_FILE_ONLY
4152
4153 /*
4154   This is free and unencumbered software released into the public domain.
4155
4156   Anyone is free to copy, modify, publish, use, compile, sell, or
4157   distribute this software, either in source code form or as a compiled
4158   binary, for any purpose, commercial or non-commercial, and by any
4159   means.
4160
4161   In jurisdictions that recognize copyright laws, the author or authors
4162   of this software dedicate any and all copyright interest in the
4163   software to the public domain. We make this dedication for the benefit
4164   of the public at large and to the detriment of our heirs and
4165   successors. We intend this dedication to be an overt act of
4166   relinquishment in perpetuity of all present and future rights to this
4167   software under copyright law.
4168
4169   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
4170   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4171   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
4172   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
4173   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4174   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4175   OTHER DEALINGS IN THE SOFTWARE.
4176
4177   For more information, please refer to <http://unlicense.org/>
4178 */