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