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