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