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