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