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