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