1 /*
2    miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
3    reading/writing/appending, PNG writing See "unlicense" statement at the end
4    of this file. Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13,
5    2013 Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951:
6    http://www.ietf.org/rfc/rfc1951.txt
7 
8    Most API's defined in miniz.c are optional. For example, to disable the
9    archive related functions just define MINIZ_NO_ARCHIVE_APIS, or to get rid of
10    all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
11 
12    * Change History
13      10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major
14    release with Zip64 support (almost there!):
15        - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug
16    (thanks kahmyong.moon@hp.com) which could cause locate files to not find
17    files. This bug would only have occured in earlier versions if you explicitly
18    used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or
19    mz_zip_add_mem_to_archive_file_in_place() (which used this flag). If you
20    can't switch to v1.15 but want to fix this bug, just remove the uses of this
21    flag from both helper funcs (and of course don't use the flag).
22        - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when
23    pUser_read_buf is not NULL and compressed size is > uncompressed size
24        - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract
25    compressed data from directory entries, to account for weird zipfiles which
26    contain zero-size compressed data on dir entries. Hopefully this fix won't
27    cause any issues on weird zip archives, because it assumes the low 16-bits of
28    zip external attributes are DOS attributes (which I believe they always are
29    in practice).
30        - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the
31    internal attributes, just the filename and external attributes
32        - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
33        - Added cmake support for Linux builds which builds all the examples,
34    tested with clang v3.3 and gcc v4.6.
35        - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
36        - Merged MZ_FORCEINLINE fix from hdeanclark
37        - Fix <time.h> include before config #ifdef, thanks emil.brink
38        - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping
39    (super useful for OpenGL apps), and explicit control over the compression
40    level (so you can set it to 1 for real-time compression).
41        - Merged in some compiler fixes from paulharris's github repro.
42        - Retested this build under Windows (VS 2010, including static analysis),
43    tcc  0.9.26, gcc v4.6 and clang v3.3.
44        - Added example6.c, which dumps an image of the mandelbrot set to a PNG
45    file.
46        - Modified example2 to help test the
47    MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
48        - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix
49    possible src file fclose() leak if alignment bytes+local header file write
50    faiiled
51    - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the
52    wrong central dir header offset, appears harmless in this release, but it
53    became a problem in the zip64 branch 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1
54    compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
55      5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix
56    mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
57        - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and
58    re-ran a randomized regression test on ~500k files.
59        - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
60        - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze
61    (static analysis) option and fixed all warnings (except for the silly "Use of
62    the comma-operator in a tested expression.." analysis warning, which I
63    purposely use to work around a MSVC compiler warning).
64        - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and
65    tested Linux executables. The codeblocks workspace is compatible with
66    Linux+Win32/x64.
67        - Added miniz_tester solution/project, which is a useful little app
68    derived from LZHAM's tester app that I use as part of the regression test.
69        - Ran miniz.c and tinfl.c through another series of regression testing on
70    ~500,000 files and archives.
71        - Modified example5.c so it purposely disables a bunch of high-level
72    functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the
73    MINIZ_NO_STDIO bug report.)
74        - Fix ftell() usage in examples so they exit with an error on files which
75    are too large (a limitation of the examples, not miniz itself). 4/12/12 v1.12
76    - More comments, added low-level example5.c, fixed a couple minor
77    level_and_flags issues in the archive API's. level_and_flags can now be set
78    to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com>
79    for the feedback/bug report. 5/28/11 v1.11 - Added statement from
80    unlicense.org 5/27/11 v1.10 - Substantial compressor optimizations:
81       - Level 1 is now ~4x faster than before. The L1 compressor's throughput
82    now varies between 70-110MB/sec. on a
83       - Core i7 (actual throughput varies depending on the type of data, and x64
84    vs. x86).
85       - Improved baseline L2-L9 compression perf. Also, greatly improved
86    compression perf. issues on some file types.
87       - Refactored the compression code for better readability and
88    maintainability.
89       - Added level 10 compression level (L10 has slightly better ratio than
90    level 9, but could have a potentially large drop in throughput on some
91    files). 5/15/11 v1.09 - Initial stable release.
92 
93    * Low-level Deflate/Inflate implementation notes:
94 
95      Compression: Use the "tdefl" API's. The compressor supports raw, static,
96    and dynamic blocks, lazy or greedy parsing, match length filtering, RLE-only,
97    and Huffman-only streams. It performs and compresses approximately as well as
98    zlib.
99 
100      Decompression: Use the "tinfl" API's. The entire decompressor is
101    implemented as a single function coroutine: see tinfl_decompress(). It
102    supports decompression into a 32KB (or larger power of 2) wrapping buffer, or
103    into a memory block large enough to hold the entire file.
104 
105      The low-level tdefl/tinfl API's do not make any use of dynamic memory
106    allocation.
107 
108    * zlib-style API notes:
109 
110      miniz.c implements a fairly large subset of zlib. There's enough
111    functionality present for it to be a drop-in zlib replacement in many apps:
112         The z_stream struct, optional memory allocation callbacks
113         deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
114         inflateInit/inflateInit2/inflate/inflateEnd
115         compress, compress2, compressBound, uncompress
116         CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly
117    routines. Supports raw deflate streams or standard zlib streams with adler-32
118    checking.
119 
120      Limitations:
121       The callback API's are not implemented yet. No support for gzip headers or
122    zlib static dictionaries. I've tried to closely emulate zlib's various
123    flavors of stream flushing and return status codes, but there are no
124    guarantees that miniz.c pulls this off perfectly.
125 
126    * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function,
127    originally written by Alex Evans. Supports 1-4 bytes/pixel images.
128 
129    * ZIP archive API notes:
130 
131      The ZIP archive API's where designed with simplicity and efficiency in
132    mind, with just enough abstraction to get the job done with minimal fuss.
133    There are simple API's to retrieve file information, read files from existing
134    archives, create new archives, append new files to existing archives, or
135    clone archive data from one archive to another. It supports archives located
136    in memory or the heap, on disk (using stdio.h), or you can specify custom
137    file read/write callbacks.
138 
139      - Archive reading: Just call this function to read a single file from a
140    disk archive:
141 
142       void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const
143    char *pArchive_name, size_t *pSize, mz_uint zip_flags);
144 
145      For more complex cases, use the "mz_zip_reader" functions. Upon opening an
146    archive, the entire central directory is located and read as-is into memory,
147    and subsequent file access only occurs when reading individual files.
148 
149      - Archives file scanning: The simple way is to use this function to scan a
150    loaded archive for a specific file:
151 
152      int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
153    const char *pComment, mz_uint flags);
154 
155      The locate operation can optionally check file comments too, which (as one
156    example) can be used to identify multiple versions of the same file in an
157    archive. This function uses a simple linear search through the central
158      directory, so it's not very fast.
159 
160      Alternately, you can iterate through all the files in an archive (using
161    mz_zip_reader_get_num_files()) and retrieve detailed info on each file by
162    calling mz_zip_reader_file_stat().
163 
164      - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer
165    immediately writes compressed file data to disk and builds an exact image of
166    the central directory in memory. The central directory image is written all
167    at once at the end of the archive file when the archive is finalized.
168 
169      The archive writer can optionally align each file's local header and file
170    data to any power of 2 alignment, which can be useful when the archive will
171    be read from optical media. Also, the writer supports placing arbitrary data
172    blobs at the very beginning of ZIP archives. Archives written using either
173    feature are still readable by any ZIP tool.
174 
175      - Archive appending: The simple way to add a single file to an archive is
176    to call this function:
177 
178       mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename,
179    const char *pArchive_name, const void *pBuf, size_t buf_size, const void
180    *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
181 
182      The archive will be created if it doesn't already exist, otherwise it'll be
183    appended to. Note the appending is done in-place and is not an atomic
184    operation, so if something goes wrong during the operation it's possible the
185    archive could be left without a central directory (although the local file
186    headers and file data will be fine, so the archive will be recoverable).
187 
188      For more complex archive modification scenarios:
189      1. The safest way is to use a mz_zip_reader to read the existing archive,
190    cloning only those bits you want to preserve into a new archive using using
191    the mz_zip_writer_add_from_zip_reader() function (which compiles the
192      compressed file data as-is). When you're done, delete the old archive and
193    rename the newly written archive, and you're done. This is safe but requires
194    a bunch of temporary disk space or heap memory.
195 
196      2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using
197    mz_zip_writer_init_from_reader(), append new files as needed, then finalize
198    the archive which will write an updated central directory to the original
199    archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place()
200    does.) There's a possibility that the archive's central directory could be
201    lost with this method if anything goes wrong, though.
202 
203      - ZIP archive support limitations:
204      No zip64 or spanning support. Extraction functions can only handle
205    unencrypted, stored or deflated files. Requires streams capable of seeking.
206 
207    * This is a header file library, like stb_image.c. To get only a header file,
208    either cut and paste the below header, or create miniz.h, #define
209    MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
210 
211    * Important: For best perf. be sure to customize the below macros for your
212    target platform: #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define
213    MINIZ_LITTLE_ENDIAN 1 #define MINIZ_HAS_64BIT_REGISTERS 1
214 
215    * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before
216    including miniz.c to ensure miniz uses the 64-bit variants: fopen64(),
217    stat64(), etc. Otherwise you won't be able to process large files (i.e.
218    32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
219 */
220 
221 #ifndef MINIZ_HEADER_INCLUDED
222 #define MINIZ_HEADER_INCLUDED
223 
224 #include <stdint.h>
225 #include <stdlib.h>
226 
227 // Defines to completely disable specific portions of miniz.c:
228 // If all macros here are defined the only functionality remaining will be
229 // CRC-32, adler-32, tinfl, and tdefl.
230 
231 // Define MINIZ_NO_STDIO to disable all usage and any functions which rely on
232 // stdio for file I/O.
233 //#define MINIZ_NO_STDIO
234 
235 // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able
236 // to get the current time, or get/set file times, and the C run-time funcs that
237 // get/set times won't be called. The current downside is the times written to
238 // your archives will be from 1979.
239 //#define MINIZ_NO_TIME
240 
241 // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
242 //#define MINIZ_NO_ARCHIVE_APIS
243 
244 // Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive
245 // API's.
246 //#define MINIZ_NO_ARCHIVE_WRITING_APIS
247 
248 // Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression
249 // API's.
250 //#define MINIZ_NO_ZLIB_APIS
251 
252 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent
253 // conflicts against stock zlib.
254 //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
255 
256 // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
257 // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom
258 // user alloc/free/realloc callbacks to the zlib and archive API's, and a few
259 // stand-alone helper API's which don't provide custom user functions (such as
260 // tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
261 //#define MINIZ_NO_MALLOC
262 
263 #if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
264 // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc
265 // on Linux
266 #define MINIZ_NO_TIME
267 #endif
268 
269 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
270 #include <time.h>
271 #endif
272 
273 #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) ||                \
274     defined(__i386) || defined(__i486__) || defined(__i486) ||                 \
275     defined(i386) || defined(__ia64__) || defined(__x86_64__)
276 // MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
277 #define MINIZ_X86_OR_X64_CPU 1
278 #endif
279 
280 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
281 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
282 #define MINIZ_LITTLE_ENDIAN 1
283 #endif
284 
285 /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */
286 #if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES)
287 #if MINIZ_X86_OR_X64_CPU
288 /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
289  * integer loads and stores from unaligned addresses. */
290 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
291 #define MINIZ_UNALIGNED_USE_MEMCPY
292 #else
293 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
294 #endif
295 #endif
296 
297 #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) ||              \
298     defined(_LP64) || defined(__LP64__) || defined(__ia64__) ||                \
299     defined(__x86_64__)
300 // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are
301 // reasonably fast (and don't involve compiler generated calls to helper
302 // functions).
303 #define MINIZ_HAS_64BIT_REGISTERS 1
304 #endif
305 
306 #ifdef __APPLE__
307 #define ftello64 ftello
308 #define fseeko64 fseeko
309 #define fopen64 fopen
310 #define freopen64 freopen
311 
312 // Darwin OSX
313 #define MZ_PLATFORM 19
314 #endif
315 
316 #ifndef MZ_PLATFORM
317 #if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
318 #define MZ_PLATFORM 0
319 #else
320 // UNIX
321 #define MZ_PLATFORM 3
322 #endif
323 #endif
324 
325 #ifdef __cplusplus
326 extern "C" {
327 #endif
328 
329 // ------------------- zlib-style API Definitions.
330 
331 // For more compatibility with zlib, miniz.c uses unsigned long for some
332 // parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
333 typedef unsigned long mz_ulong;
334 
335 // mz_free() internally uses the MZ_FREE() macro (which by default calls free()
336 // unless you've modified the MZ_MALLOC macro) to release a block allocated from
337 // the heap.
338 void mz_free(void *p);
339 
340 #define MZ_ADLER32_INIT (1)
341 // mz_adler32() returns the initial adler-32 value to use when called with
342 // ptr==NULL.
343 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
344 
345 #define MZ_CRC32_INIT (0)
346 // mz_crc32() returns the initial CRC-32 value to use when called with
347 // ptr==NULL.
348 mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
349 
350 // Compression strategies.
351 enum {
352   MZ_DEFAULT_STRATEGY = 0,
353   MZ_FILTERED = 1,
354   MZ_HUFFMAN_ONLY = 2,
355   MZ_RLE = 3,
356   MZ_FIXED = 4
357 };
358 
359 /* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or
360  * modify this enum. */
361 typedef enum {
362   MZ_ZIP_NO_ERROR = 0,
363   MZ_ZIP_UNDEFINED_ERROR,
364   MZ_ZIP_TOO_MANY_FILES,
365   MZ_ZIP_FILE_TOO_LARGE,
366   MZ_ZIP_UNSUPPORTED_METHOD,
367   MZ_ZIP_UNSUPPORTED_ENCRYPTION,
368   MZ_ZIP_UNSUPPORTED_FEATURE,
369   MZ_ZIP_FAILED_FINDING_CENTRAL_DIR,
370   MZ_ZIP_NOT_AN_ARCHIVE,
371   MZ_ZIP_INVALID_HEADER_OR_CORRUPTED,
372   MZ_ZIP_UNSUPPORTED_MULTIDISK,
373   MZ_ZIP_DECOMPRESSION_FAILED,
374   MZ_ZIP_COMPRESSION_FAILED,
375   MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE,
376   MZ_ZIP_CRC_CHECK_FAILED,
377   MZ_ZIP_UNSUPPORTED_CDIR_SIZE,
378   MZ_ZIP_ALLOC_FAILED,
379   MZ_ZIP_FILE_OPEN_FAILED,
380   MZ_ZIP_FILE_CREATE_FAILED,
381   MZ_ZIP_FILE_WRITE_FAILED,
382   MZ_ZIP_FILE_READ_FAILED,
383   MZ_ZIP_FILE_CLOSE_FAILED,
384   MZ_ZIP_FILE_SEEK_FAILED,
385   MZ_ZIP_FILE_STAT_FAILED,
386   MZ_ZIP_INVALID_PARAMETER,
387   MZ_ZIP_INVALID_FILENAME,
388   MZ_ZIP_BUF_TOO_SMALL,
389   MZ_ZIP_INTERNAL_ERROR,
390   MZ_ZIP_FILE_NOT_FOUND,
391   MZ_ZIP_ARCHIVE_TOO_LARGE,
392   MZ_ZIP_VALIDATION_FAILED,
393   MZ_ZIP_WRITE_CALLBACK_FAILED,
394   MZ_ZIP_TOTAL_ERRORS
395 } mz_zip_error;
396 
397 // Method
398 #define MZ_DEFLATED 8
399 
400 #ifndef MINIZ_NO_ZLIB_APIS
401 
402 // Heap allocation callbacks.
403 // Note that mz_alloc_func parameter types purposely differ from zlib's:
404 // items/size is size_t, not unsigned long.
405 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
406 typedef void (*mz_free_func)(void *opaque, void *address);
407 typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items,
408                                  size_t size);
409 
410 #define MZ_VERSION "9.1.15"
411 #define MZ_VERNUM 0x91F0
412 #define MZ_VER_MAJOR 9
413 #define MZ_VER_MINOR 1
414 #define MZ_VER_REVISION 15
415 #define MZ_VER_SUBREVISION 0
416 
417 // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The
418 // other values are for advanced use (refer to the zlib docs).
419 enum {
420   MZ_NO_FLUSH = 0,
421   MZ_PARTIAL_FLUSH = 1,
422   MZ_SYNC_FLUSH = 2,
423   MZ_FULL_FLUSH = 3,
424   MZ_FINISH = 4,
425   MZ_BLOCK = 5
426 };
427 
428 // Return status codes. MZ_PARAM_ERROR is non-standard.
429 enum {
430   MZ_OK = 0,
431   MZ_STREAM_END = 1,
432   MZ_NEED_DICT = 2,
433   MZ_ERRNO = -1,
434   MZ_STREAM_ERROR = -2,
435   MZ_DATA_ERROR = -3,
436   MZ_MEM_ERROR = -4,
437   MZ_BUF_ERROR = -5,
438   MZ_VERSION_ERROR = -6,
439   MZ_PARAM_ERROR = -10000
440 };
441 
442 // Compression levels: 0-9 are the standard zlib-style levels, 10 is best
443 // possible compression (not zlib compatible, and may be very slow),
444 // MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
445 enum {
446   MZ_NO_COMPRESSION = 0,
447   MZ_BEST_SPEED = 1,
448   MZ_BEST_COMPRESSION = 9,
449   MZ_UBER_COMPRESSION = 10,
450   MZ_DEFAULT_LEVEL = 6,
451   MZ_DEFAULT_COMPRESSION = -1
452 };
453 
454 // Window bits
455 #define MZ_DEFAULT_WINDOW_BITS 15
456 
457 struct mz_internal_state;
458 
459 // Compression/decompression stream struct.
460 typedef struct mz_stream_s {
461   const unsigned char *next_in; // pointer to next byte to read
462   unsigned int avail_in;        // number of bytes available at next_in
463   mz_ulong total_in;            // total number of bytes consumed so far
464 
465   unsigned char *next_out; // pointer to next byte to write
466   unsigned int avail_out;  // number of bytes that can be written to next_out
467   mz_ulong total_out;      // total number of bytes produced so far
468 
469   char *msg;                       // error msg (unused)
470   struct mz_internal_state *state; // internal state, allocated by zalloc/zfree
471 
472   mz_alloc_func
473       zalloc;         // optional heap allocation function (defaults to malloc)
474   mz_free_func zfree; // optional heap free function (defaults to free)
475   void *opaque;       // heap alloc function user pointer
476 
477   int data_type;     // data_type (unused)
478   mz_ulong adler;    // adler32 of the source or uncompressed data
479   mz_ulong reserved; // not used
480 } mz_stream;
481 
482 typedef mz_stream *mz_streamp;
483 
484 // Returns the version string of miniz.c.
485 const char *mz_version(void);
486 
487 // mz_deflateInit() initializes a compressor with default options:
488 // Parameters:
489 //  pStream must point to an initialized mz_stream struct.
490 //  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
491 //  level 1 enables a specially optimized compression function that's been
492 //  optimized purely for performance, not ratio. (This special func. is
493 //  currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and
494 //  MINIZ_LITTLE_ENDIAN are defined.)
495 // Return values:
496 //  MZ_OK on success.
497 //  MZ_STREAM_ERROR if the stream is bogus.
498 //  MZ_PARAM_ERROR if the input parameters are bogus.
499 //  MZ_MEM_ERROR on out of memory.
500 int mz_deflateInit(mz_streamp pStream, int level);
501 
502 // mz_deflateInit2() is like mz_deflate(), except with more control:
503 // Additional parameters:
504 //   method must be MZ_DEFLATED
505 //   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with
506 //   zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no
507 //   header or footer) mem_level must be between [1, 9] (it's checked but
508 //   ignored by miniz.c)
509 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
510                     int mem_level, int strategy);
511 
512 // Quickly resets a compressor without having to reallocate anything. Same as
513 // calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
514 int mz_deflateReset(mz_streamp pStream);
515 
516 // mz_deflate() compresses the input to output, consuming as much of the input
517 // and producing as much output as possible. Parameters:
518 //   pStream is the stream to read from and write to. You must initialize/update
519 //   the next_in, avail_in, next_out, and avail_out members. flush may be
520 //   MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
521 // Return values:
522 //   MZ_OK on success (when flushing, or if more input is needed but not
523 //   available, and/or there's more output to be written but the output buffer
524 //   is full). MZ_STREAM_END if all input has been consumed and all output bytes
525 //   have been written. Don't call mz_deflate() on the stream anymore.
526 //   MZ_STREAM_ERROR if the stream is bogus.
527 //   MZ_PARAM_ERROR if one of the parameters is invalid.
528 //   MZ_BUF_ERROR if no forward progress is possible because the input and/or
529 //   output buffers are empty. (Fill up the input buffer or free up some output
530 //   space and try again.)
531 int mz_deflate(mz_streamp pStream, int flush);
532 
533 // mz_deflateEnd() deinitializes a compressor:
534 // Return values:
535 //  MZ_OK on success.
536 //  MZ_STREAM_ERROR if the stream is bogus.
537 int mz_deflateEnd(mz_streamp pStream);
538 
539 // mz_deflateBound() returns a (very) conservative upper bound on the amount of
540 // data that could be generated by deflate(), assuming flush is set to only
541 // MZ_NO_FLUSH or MZ_FINISH.
542 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
543 
544 // Single-call compression functions mz_compress() and mz_compress2():
545 // Returns MZ_OK on success, or one of the error codes from mz_deflate() on
546 // failure.
547 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
548                 const unsigned char *pSource, mz_ulong source_len);
549 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
550                  const unsigned char *pSource, mz_ulong source_len, int level);
551 
552 // mz_compressBound() returns a (very) conservative upper bound on the amount of
553 // data that could be generated by calling mz_compress().
554 mz_ulong mz_compressBound(mz_ulong source_len);
555 
556 // Initializes a decompressor.
557 int mz_inflateInit(mz_streamp pStream);
558 
559 // mz_inflateInit2() is like mz_inflateInit() with an additional option that
560 // controls the window size and whether or not the stream has been wrapped with
561 // a zlib header/footer: window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse
562 // zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
563 int mz_inflateInit2(mz_streamp pStream, int window_bits);
564 
565 // Decompresses the input stream to the output, consuming only as much of the
566 // input as needed, and writing as much to the output as possible. Parameters:
567 //   pStream is the stream to read from and write to. You must initialize/update
568 //   the next_in, avail_in, next_out, and avail_out members. flush may be
569 //   MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. On the first call, if flush is
570 //   MZ_FINISH it's assumed the input and output buffers are both sized large
571 //   enough to decompress the entire stream in a single call (this is slightly
572 //   faster). MZ_FINISH implies that there are no more source bytes available
573 //   beside what's already in the input buffer, and that the output buffer is
574 //   large enough to hold the rest of the decompressed data.
575 // Return values:
576 //   MZ_OK on success. Either more input is needed but not available, and/or
577 //   there's more output to be written but the output buffer is full.
578 //   MZ_STREAM_END if all needed input has been consumed and all output bytes
579 //   have been written. For zlib streams, the adler-32 of the decompressed data
580 //   has also been verified. MZ_STREAM_ERROR if the stream is bogus.
581 //   MZ_DATA_ERROR if the deflate stream is invalid.
582 //   MZ_PARAM_ERROR if one of the parameters is invalid.
583 //   MZ_BUF_ERROR if no forward progress is possible because the input buffer is
584 //   empty but the inflater needs more input to continue, or if the output
585 //   buffer is not large enough. Call mz_inflate() again with more input data,
586 //   or with more room in the output buffer (except when using single call
587 //   decompression, described above).
588 int mz_inflate(mz_streamp pStream, int flush);
589 
590 // Deinitializes a decompressor.
591 int mz_inflateEnd(mz_streamp pStream);
592 
593 // Single-call decompression.
594 // Returns MZ_OK on success, or one of the error codes from mz_inflate() on
595 // failure.
596 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
597                   const unsigned char *pSource, mz_ulong source_len);
598 
599 // Returns a string description of the specified error code, or NULL if the
600 // error code is invalid.
601 const char *mz_error(int err);
602 
603 // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used
604 // as a drop-in replacement for the subset of zlib that miniz.c supports. Define
605 // MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib
606 // in the same project.
607 #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
608 typedef unsigned char Byte;
609 typedef unsigned int uInt;
610 typedef mz_ulong uLong;
611 typedef Byte Bytef;
612 typedef uInt uIntf;
613 typedef char charf;
614 typedef int intf;
615 typedef void *voidpf;
616 typedef uLong uLongf;
617 typedef void *voidp;
618 typedef void *const voidpc;
619 #define Z_NULL 0
620 #define Z_NO_FLUSH MZ_NO_FLUSH
621 #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
622 #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
623 #define Z_FULL_FLUSH MZ_FULL_FLUSH
624 #define Z_FINISH MZ_FINISH
625 #define Z_BLOCK MZ_BLOCK
626 #define Z_OK MZ_OK
627 #define Z_STREAM_END MZ_STREAM_END
628 #define Z_NEED_DICT MZ_NEED_DICT
629 #define Z_ERRNO MZ_ERRNO
630 #define Z_STREAM_ERROR MZ_STREAM_ERROR
631 #define Z_DATA_ERROR MZ_DATA_ERROR
632 #define Z_MEM_ERROR MZ_MEM_ERROR
633 #define Z_BUF_ERROR MZ_BUF_ERROR
634 #define Z_VERSION_ERROR MZ_VERSION_ERROR
635 #define Z_PARAM_ERROR MZ_PARAM_ERROR
636 #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
637 #define Z_BEST_SPEED MZ_BEST_SPEED
638 #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
639 #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
640 #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
641 #define Z_FILTERED MZ_FILTERED
642 #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
643 #define Z_RLE MZ_RLE
644 #define Z_FIXED MZ_FIXED
645 #define Z_DEFLATED MZ_DEFLATED
646 #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
647 #define alloc_func mz_alloc_func
648 #define free_func mz_free_func
649 #define internal_state mz_internal_state
650 #define z_stream mz_stream
651 #define deflateInit mz_deflateInit
652 #define deflateInit2 mz_deflateInit2
653 #define deflateReset mz_deflateReset
654 #define deflate mz_deflate
655 #define deflateEnd mz_deflateEnd
656 #define deflateBound mz_deflateBound
657 #define compress mz_compress
658 #define compress2 mz_compress2
659 #define compressBound mz_compressBound
660 #define inflateInit mz_inflateInit
661 #define inflateInit2 mz_inflateInit2
662 #define inflate mz_inflate
663 #define inflateEnd mz_inflateEnd
664 #define uncompress mz_uncompress
665 #define crc32 mz_crc32
666 #define adler32 mz_adler32
667 #define MAX_WBITS 15
668 #define MAX_MEM_LEVEL 9
669 #define zError mz_error
670 #define ZLIB_VERSION MZ_VERSION
671 #define ZLIB_VERNUM MZ_VERNUM
672 #define ZLIB_VER_MAJOR MZ_VER_MAJOR
673 #define ZLIB_VER_MINOR MZ_VER_MINOR
674 #define ZLIB_VER_REVISION MZ_VER_REVISION
675 #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
676 #define zlibVersion mz_version
677 #define zlib_version mz_version()
678 #endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
679 
680 #endif // MINIZ_NO_ZLIB_APIS
681 
682 // ------------------- Types and macros
683 
684 typedef unsigned char mz_uint8;
685 typedef signed short mz_int16;
686 typedef unsigned short mz_uint16;
687 typedef unsigned int mz_uint32;
688 typedef unsigned int mz_uint;
689 typedef long long mz_int64;
690 typedef unsigned long long mz_uint64;
691 typedef int mz_bool;
692 
693 #define MZ_FALSE (0)
694 #define MZ_TRUE (1)
695 
696 // An attempt to work around MSVC's spammy "warning C4127: conditional
697 // expression is constant" message.
698 #ifdef _MSC_VER
699 #define MZ_MACRO_END while (0, 0)
700 #else
701 #define MZ_MACRO_END while (0)
702 #endif
703 
704 // ------------------- ZIP archive reading/writing
705 
706 #ifndef MINIZ_NO_ARCHIVE_APIS
707 
708 enum {
709   MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,
710   MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
711   MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
712 };
713 
714 typedef struct {
715   mz_uint32 m_file_index;
716   mz_uint32 m_central_dir_ofs;
717   mz_uint16 m_version_made_by;
718   mz_uint16 m_version_needed;
719   mz_uint16 m_bit_flag;
720   mz_uint16 m_method;
721 #ifndef MINIZ_NO_TIME
722   time_t m_time;
723 #endif
724   mz_uint32 m_crc32;
725   mz_uint64 m_comp_size;
726   mz_uint64 m_uncomp_size;
727   mz_uint16 m_internal_attr;
728   mz_uint32 m_external_attr;
729   mz_uint64 m_local_header_ofs;
730   mz_uint32 m_comment_size;
731   char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
732   char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
733 } mz_zip_archive_file_stat;
734 
735 typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
736                                     void *pBuf, size_t n);
737 typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
738                                      const void *pBuf, size_t n);
739 typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
740 
741 struct mz_zip_internal_state_tag;
742 typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
743 
744 typedef enum {
745   MZ_ZIP_MODE_INVALID = 0,
746   MZ_ZIP_MODE_READING = 1,
747   MZ_ZIP_MODE_WRITING = 2,
748   MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
749 } mz_zip_mode;
750 
751 typedef enum {
752   MZ_ZIP_TYPE_INVALID = 0,
753   MZ_ZIP_TYPE_USER,
754   MZ_ZIP_TYPE_MEMORY,
755   MZ_ZIP_TYPE_HEAP,
756   MZ_ZIP_TYPE_FILE,
757   MZ_ZIP_TYPE_CFILE,
758   MZ_ZIP_TOTAL_TYPES
759 } mz_zip_type;
760 
761 typedef struct {
762   mz_uint64 m_archive_size;
763   mz_uint64 m_central_directory_file_ofs;
764 
765   /* We only support up to UINT32_MAX files in zip64 mode. */
766   mz_uint32 m_total_files;
767   mz_zip_mode m_zip_mode;
768   mz_zip_type m_zip_type;
769   mz_zip_error m_last_error;
770 
771   mz_uint64 m_file_offset_alignment;
772 
773   mz_alloc_func m_pAlloc;
774   mz_free_func m_pFree;
775   mz_realloc_func m_pRealloc;
776   void *m_pAlloc_opaque;
777 
778   mz_file_read_func m_pRead;
779   mz_file_write_func m_pWrite;
780   mz_file_needs_keepalive m_pNeeds_keepalive;
781   void *m_pIO_opaque;
782 
783   mz_zip_internal_state *m_pState;
784 
785 } mz_zip_archive;
786 
787 typedef enum {
788   MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
789   MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
790   MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
791   MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
792 } mz_zip_flags;
793 
794 // ZIP archive reading
795 
796 // Inits a ZIP archive reader.
797 // These functions read and validate the archive's central directory.
798 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
799                            mz_uint32 flags);
800 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
801                                size_t size, mz_uint32 flags);
802 
803 #ifndef MINIZ_NO_STDIO
804 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
805                                 mz_uint32 flags);
806 #endif
807 
808 // Returns the total number of files in the archive.
809 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
810 
811 // Returns detailed information about an archive file entry.
812 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
813                                 mz_zip_archive_file_stat *pStat);
814 
815 // Determines if an archive file entry is a directory entry.
816 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
817                                           mz_uint file_index);
818 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
819                                         mz_uint file_index);
820 
821 // Retrieves the filename of an archive file entry.
822 // Returns the number of bytes written to pFilename, or if filename_buf_size is
823 // 0 this function returns the number of bytes needed to fully store the
824 // filename.
825 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
826                                    char *pFilename, mz_uint filename_buf_size);
827 
828 // Attempts to locates a file in the archive's central directory.
829 // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
830 // Returns -1 if the file cannot be found.
831 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
832                               const char *pComment, mz_uint flags);
833 
834 // Extracts a archive file to a memory buffer using no memory allocation.
835 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
836                                               mz_uint file_index, void *pBuf,
837                                               size_t buf_size, mz_uint flags,
838                                               void *pUser_read_buf,
839                                               size_t user_read_buf_size);
840 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
841     mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
842     mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
843 
844 // Extracts a archive file to a memory buffer.
845 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
846                                      void *pBuf, size_t buf_size,
847                                      mz_uint flags);
848 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
849                                           const char *pFilename, void *pBuf,
850                                           size_t buf_size, mz_uint flags);
851 
852 // Extracts a archive file to a dynamically allocated heap buffer.
853 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
854                                     size_t *pSize, mz_uint flags);
855 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
856                                          const char *pFilename, size_t *pSize,
857                                          mz_uint flags);
858 
859 // Extracts a archive file using a callback function to output the file's data.
860 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
861                                           mz_uint file_index,
862                                           mz_file_write_func pCallback,
863                                           void *pOpaque, mz_uint flags);
864 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
865                                                const char *pFilename,
866                                                mz_file_write_func pCallback,
867                                                void *pOpaque, mz_uint flags);
868 
869 #ifndef MINIZ_NO_STDIO
870 // Extracts a archive file to a disk file and sets its last accessed and
871 // modified times. This function only extracts files, not archive directory
872 // records.
873 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
874                                       const char *pDst_filename, mz_uint flags);
875 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
876                                            const char *pArchive_filename,
877                                            const char *pDst_filename,
878                                            mz_uint flags);
879 #endif
880 
881 // Ends archive reading, freeing all allocations, and closing the input archive
882 // file if mz_zip_reader_init_file() was used.
883 mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
884 
885 // ZIP archive writing
886 
887 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
888 
889 // Inits a ZIP archive writer.
890 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
891 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
892                                 size_t size_to_reserve_at_beginning,
893                                 size_t initial_allocation_size);
894 
895 #ifndef MINIZ_NO_STDIO
896 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
897                                 mz_uint64 size_to_reserve_at_beginning);
898 #endif
899 
900 // Converts a ZIP archive reader object into a writer object, to allow efficient
901 // in-place file appends to occur on an existing archive. For archives opened
902 // using mz_zip_reader_init_file, pFilename must be the archive's filename so it
903 // can be reopened for writing. If the file can't be reopened,
904 // mz_zip_reader_end() will be called. For archives opened using
905 // mz_zip_reader_init_mem, the memory block must be growable using the realloc
906 // callback (which defaults to realloc unless you've overridden it). Finally,
907 // for archives opened using mz_zip_reader_init, the mz_zip_archive's user
908 // provided m_pWrite function cannot be NULL. Note: In-place archive
909 // modification is not recommended unless you know what you're doing, because if
910 // execution stops or something goes wrong before the archive is finalized the
911 // file's central directory will be hosed.
912 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
913                                        const char *pFilename);
914 
915 // Adds the contents of a memory buffer to an archive. These functions record
916 // the current local time into the archive. To add a directory entry, call this
917 // method with an archive name ending in a forwardslash with empty buffer.
918 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
919 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
920 // just set to MZ_DEFAULT_COMPRESSION.
921 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
922                               const void *pBuf, size_t buf_size,
923                               mz_uint level_and_flags);
924 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
925                                  const char *pArchive_name, const void *pBuf,
926                                  size_t buf_size, const void *pComment,
927                                  mz_uint16 comment_size,
928                                  mz_uint level_and_flags, mz_uint64 uncomp_size,
929                                  mz_uint32 uncomp_crc32);
930 
931 #ifndef MINIZ_NO_STDIO
932 // Adds the contents of a disk file to an archive. This function also records
933 // the disk file's modified time into the archive. level_and_flags - compression
934 // level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd
935 // with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
936 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
937                                const char *pSrc_filename, const void *pComment,
938                                mz_uint16 comment_size, mz_uint level_and_flags,
939                                mz_uint32 ext_attributes);
940 #endif
941 
942 // Adds a file to an archive by fully cloning the data from another archive.
943 // This function fully clones the source file's compressed data (no
944 // recompression), along with its full filename, extra data, and comment fields.
945 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
946                                           mz_zip_archive *pSource_zip,
947                                           mz_uint file_index);
948 
949 // Finalizes the archive by writing the central directory records followed by
950 // the end of central directory record. After an archive is finalized, the only
951 // valid call on the mz_zip_archive struct is mz_zip_writer_end(). An archive
952 // must be manually finalized by calling this function for it to be valid.
953 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
954 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
955                                             size_t *pSize);
956 
957 // Ends archive writing, freeing all allocations, and closing the output file if
958 // mz_zip_writer_init_file() was used. Note for the archive to be valid, it must
959 // have been finalized before ending.
960 mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
961 
962 // Misc. high-level helper functions:
963 
964 // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically)
965 // appends a memory blob to a ZIP archive. level_and_flags - compression level
966 // (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero
967 // or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
968 mz_bool mz_zip_add_mem_to_archive_file_in_place(
969     const char *pZip_filename, const char *pArchive_name, const void *pBuf,
970     size_t buf_size, const void *pComment, mz_uint16 comment_size,
971     mz_uint level_and_flags);
972 
973 // Reads a single file from an archive into a heap block.
974 // Returns NULL on failure.
975 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
976                                           const char *pArchive_name,
977                                           size_t *pSize, mz_uint zip_flags);
978 
979 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
980 
981 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
982 
983 // ------------------- Low-level Decompression API Definitions
984 
985 // Decompression flags used by tinfl_decompress().
986 // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and
987 // ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the
988 // input is a raw deflate stream. TINFL_FLAG_HAS_MORE_INPUT: If set, there are
989 // more input bytes available beyond the end of the supplied input buffer. If
990 // clear, the input buffer contains all remaining input.
991 // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large
992 // enough to hold the entire decompressed stream. If clear, the output buffer is
993 // at least the size of the dictionary (typically 32KB).
994 // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the
995 // decompressed bytes.
996 enum {
997   TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
998   TINFL_FLAG_HAS_MORE_INPUT = 2,
999   TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
1000   TINFL_FLAG_COMPUTE_ADLER32 = 8
1001 };
1002 
1003 // High level decompression functions:
1004 // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block
1005 // allocated via malloc(). On entry:
1006 //  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data
1007 //  to decompress.
1008 // On return:
1009 //  Function returns a pointer to the decompressed data, or NULL on failure.
1010 //  *pOut_len will be set to the decompressed data's size, which could be larger
1011 //  than src_buf_len on uncompressible data. The caller must call mz_free() on
1012 //  the returned block when it's no longer needed.
1013 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1014                                    size_t *pOut_len, int flags);
1015 
1016 // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block
1017 // in memory. Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the
1018 // number of bytes written on success.
1019 #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
1020 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1021                                    const void *pSrc_buf, size_t src_buf_len,
1022                                    int flags);
1023 
1024 // tinfl_decompress_mem_to_callback() decompresses a block in memory to an
1025 // internal 32KB buffer, and a user provided callback function will be called to
1026 // flush the buffer. Returns 1 on success or 0 on failure.
1027 typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1028 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
1029                                      tinfl_put_buf_func_ptr pPut_buf_func,
1030                                      void *pPut_buf_user, int flags);
1031 
1032 struct tinfl_decompressor_tag;
1033 typedef struct tinfl_decompressor_tag tinfl_decompressor;
1034 
1035 // Max size of LZ dictionary.
1036 #define TINFL_LZ_DICT_SIZE 32768
1037 
1038 // Return status.
1039 typedef enum {
1040   TINFL_STATUS_BAD_PARAM = -3,
1041   TINFL_STATUS_ADLER32_MISMATCH = -2,
1042   TINFL_STATUS_FAILED = -1,
1043   TINFL_STATUS_DONE = 0,
1044   TINFL_STATUS_NEEDS_MORE_INPUT = 1,
1045   TINFL_STATUS_HAS_MORE_OUTPUT = 2
1046 } tinfl_status;
1047 
1048 // Initializes the decompressor to its initial state.
1049 #define tinfl_init(r)                                                          \
1050   do {                                                                         \
1051     (r)->m_state = 0;                                                          \
1052   }                                                                            \
1053   MZ_MACRO_END
1054 #define tinfl_get_adler32(r) (r)->m_check_adler32
1055 
1056 // Main low-level decompressor coroutine function. This is the only function
1057 // actually needed for decompression. All the other functions are just
1058 // high-level helpers for improved usability. This is a universal API, i.e. it
1059 // can be used as a building block to build any desired higher level
1060 // decompression API. In the limit case, it can be called once per every byte
1061 // input or output.
1062 tinfl_status tinfl_decompress(tinfl_decompressor *r,
1063                               const mz_uint8 *pIn_buf_next,
1064                               size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
1065                               mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
1066                               const mz_uint32 decomp_flags);
1067 
1068 // Internal/private bits follow.
1069 enum {
1070   TINFL_MAX_HUFF_TABLES = 3,
1071   TINFL_MAX_HUFF_SYMBOLS_0 = 288,
1072   TINFL_MAX_HUFF_SYMBOLS_1 = 32,
1073   TINFL_MAX_HUFF_SYMBOLS_2 = 19,
1074   TINFL_FAST_LOOKUP_BITS = 10,
1075   TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
1076 };
1077 
1078 typedef struct {
1079   mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
1080   mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE],
1081       m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
1082 } tinfl_huff_table;
1083 
1084 #if MINIZ_HAS_64BIT_REGISTERS
1085 #define TINFL_USE_64BIT_BITBUF 1
1086 #endif
1087 
1088 #if TINFL_USE_64BIT_BITBUF
1089 typedef mz_uint64 tinfl_bit_buf_t;
1090 #define TINFL_BITBUF_SIZE (64)
1091 #else
1092 typedef mz_uint32 tinfl_bit_buf_t;
1093 #define TINFL_BITBUF_SIZE (32)
1094 #endif
1095 
1096 struct tinfl_decompressor_tag {
1097   mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type,
1098       m_check_adler32, m_dist, m_counter, m_num_extra,
1099       m_table_sizes[TINFL_MAX_HUFF_TABLES];
1100   tinfl_bit_buf_t m_bit_buf;
1101   size_t m_dist_from_out_buf_start;
1102   tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
1103   mz_uint8 m_raw_header[4],
1104       m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
1105 };
1106 
1107 // ------------------- Low-level Compression API Definitions
1108 
1109 // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly
1110 // slower, and raw/dynamic blocks will be output more frequently).
1111 #define TDEFL_LESS_MEMORY 0
1112 
1113 // tdefl_init() compression flags logically OR'd together (low 12 bits contain
1114 // the max. number of probes per dictionary search): TDEFL_DEFAULT_MAX_PROBES:
1115 // The compressor defaults to 128 dictionary probes per dictionary search.
1116 // 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ
1117 // (slowest/best compression).
1118 enum {
1119   TDEFL_HUFFMAN_ONLY = 0,
1120   TDEFL_DEFAULT_MAX_PROBES = 128,
1121   TDEFL_MAX_PROBES_MASK = 0xFFF
1122 };
1123 
1124 // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before
1125 // the deflate data, and the Adler-32 of the source data at the end. Otherwise,
1126 // you'll get raw deflate data. TDEFL_COMPUTE_ADLER32: Always compute the
1127 // adler-32 of the input data (even when not writing zlib headers).
1128 // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more
1129 // efficient lazy parsing. TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to
1130 // decrease the compressor's initialization time to the minimum, but the output
1131 // may vary from run to run given the same input (depending on the contents of
1132 // memory). TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a
1133 // distance of 1) TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
1134 // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
1135 // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
1136 // The low 12 bits are reserved to control the max # of hash probes per
1137 // dictionary lookup (see TDEFL_MAX_PROBES_MASK).
1138 enum {
1139   TDEFL_WRITE_ZLIB_HEADER = 0x01000,
1140   TDEFL_COMPUTE_ADLER32 = 0x02000,
1141   TDEFL_GREEDY_PARSING_FLAG = 0x04000,
1142   TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
1143   TDEFL_RLE_MATCHES = 0x10000,
1144   TDEFL_FILTER_MATCHES = 0x20000,
1145   TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
1146   TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
1147 };
1148 
1149 // High level compression functions:
1150 // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block
1151 // allocated via malloc(). On entry:
1152 //  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
1153 //  flags: The max match finder probes (default is 128) logically OR'd against
1154 //  the above flags. Higher probes are slower but improve compression.
1155 // On return:
1156 //  Function returns a pointer to the compressed data, or NULL on failure.
1157 //  *pOut_len will be set to the compressed data's size, which could be larger
1158 //  than src_buf_len on uncompressible data. The caller must free() the returned
1159 //  block when it's no longer needed.
1160 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1161                                  size_t *pOut_len, int flags);
1162 
1163 // tdefl_compress_mem_to_mem() compresses a block in memory to another block in
1164 // memory. Returns 0 on failure.
1165 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1166                                  const void *pSrc_buf, size_t src_buf_len,
1167                                  int flags);
1168 
1169 // Compresses an image to a compressed PNG file in memory.
1170 // On entry:
1171 //  pImage, w, h, and num_chans describe the image to compress. num_chans may be
1172 //  1, 2, 3, or 4. The image pitch in bytes per scanline will be w*num_chans.
1173 //  The leftmost pixel on the top scanline is stored first in memory. level may
1174 //  range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED,
1175 //  MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL If flip is
1176 //  true, the image will be flipped on the Y axis (useful for OpenGL apps).
1177 // On return:
1178 //  Function returns a pointer to the compressed data, or NULL on failure.
1179 //  *pLen_out will be set to the size of the PNG image file.
1180 //  The caller must mz_free() the returned heap block (which will typically be
1181 //  larger than *pLen_out) when it's no longer needed.
1182 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
1183                                                  int h, int num_chans,
1184                                                  size_t *pLen_out,
1185                                                  mz_uint level, mz_bool flip);
1186 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
1187                                               int num_chans, size_t *pLen_out);
1188 
1189 // Output stream interface. The compressor uses this interface to write
1190 // compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
1191 typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len,
1192                                           void *pUser);
1193 
1194 // tdefl_compress_mem_to_output() compresses a block to an output stream. The
1195 // above helpers use this function internally.
1196 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
1197                                      tdefl_put_buf_func_ptr pPut_buf_func,
1198                                      void *pPut_buf_user, int flags);
1199 
1200 enum {
1201   TDEFL_MAX_HUFF_TABLES = 3,
1202   TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
1203   TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
1204   TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
1205   TDEFL_LZ_DICT_SIZE = 32768,
1206   TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,
1207   TDEFL_MIN_MATCH_LEN = 3,
1208   TDEFL_MAX_MATCH_LEN = 258
1209 };
1210 
1211 // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed
1212 // output block (using static/fixed Huffman codes).
1213 #if TDEFL_LESS_MEMORY
1214 enum {
1215   TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,
1216   TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1217   TDEFL_MAX_HUFF_SYMBOLS = 288,
1218   TDEFL_LZ_HASH_BITS = 12,
1219   TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1220   TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1221   TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1222 };
1223 #else
1224 enum {
1225   TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,
1226   TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1227   TDEFL_MAX_HUFF_SYMBOLS = 288,
1228   TDEFL_LZ_HASH_BITS = 15,
1229   TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1230   TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1231   TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1232 };
1233 #endif
1234 
1235 // The low-level tdefl functions below may be used directly if the above helper
1236 // functions aren't flexible enough. The low-level functions don't make any heap
1237 // allocations, unlike the above helper functions.
1238 typedef enum {
1239   TDEFL_STATUS_BAD_PARAM = -2,
1240   TDEFL_STATUS_PUT_BUF_FAILED = -1,
1241   TDEFL_STATUS_OKAY = 0,
1242   TDEFL_STATUS_DONE = 1,
1243 } tdefl_status;
1244 
1245 // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
1246 typedef enum {
1247   TDEFL_NO_FLUSH = 0,
1248   TDEFL_SYNC_FLUSH = 2,
1249   TDEFL_FULL_FLUSH = 3,
1250   TDEFL_FINISH = 4
1251 } tdefl_flush;
1252 
1253 // tdefl's compression state structure.
1254 typedef struct {
1255   tdefl_put_buf_func_ptr m_pPut_buf_func;
1256   void *m_pPut_buf_user;
1257   mz_uint m_flags, m_max_probes[2];
1258   int m_greedy_parsing;
1259   mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
1260   mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
1261   mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in,
1262       m_bit_buffer;
1263   mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit,
1264       m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index,
1265       m_wants_to_finish;
1266   tdefl_status m_prev_return_status;
1267   const void *m_pIn_buf;
1268   void *m_pOut_buf;
1269   size_t *m_pIn_buf_size, *m_pOut_buf_size;
1270   tdefl_flush m_flush;
1271   const mz_uint8 *m_pSrc;
1272   size_t m_src_buf_left, m_out_buf_ofs;
1273   mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
1274   mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1275   mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1276   mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1277   mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
1278   mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
1279   mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
1280   mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
1281 } tdefl_compressor;
1282 
1283 // Initializes the compressor.
1284 // There is no corresponding deinit() function because the tdefl API's do not
1285 // dynamically allocate memory. pBut_buf_func: If NULL, output data will be
1286 // supplied to the specified callback. In this case, the user should call the
1287 // tdefl_compress_buffer() API for compression. If pBut_buf_func is NULL the
1288 // user should always call the tdefl_compress() API. flags: See the above enums
1289 // (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
1290 tdefl_status tdefl_init(tdefl_compressor *d,
1291                         tdefl_put_buf_func_ptr pPut_buf_func,
1292                         void *pPut_buf_user, int flags);
1293 
1294 // Compresses a block of data, consuming as much of the specified input buffer
1295 // as possible, and writing as much compressed data to the specified output
1296 // buffer as possible.
1297 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
1298                             size_t *pIn_buf_size, void *pOut_buf,
1299                             size_t *pOut_buf_size, tdefl_flush flush);
1300 
1301 // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a
1302 // non-NULL tdefl_put_buf_func_ptr. tdefl_compress_buffer() always consumes the
1303 // entire input buffer.
1304 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1305                                    size_t in_buf_size, tdefl_flush flush);
1306 
1307 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1308 mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
1309 
1310 // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't
1311 // defined, because it uses some of its macros.
1312 #ifndef MINIZ_NO_ZLIB_APIS
1313 // Create tdefl_compress() flags given zlib-style compression parameters.
1314 // level may range from [0,10] (where 10 is absolute max compression, but may be
1315 // much slower on some files) window_bits may be -15 (raw deflate) or 15 (zlib)
1316 // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY,
1317 // MZ_RLE, or MZ_FIXED
1318 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
1319                                                 int strategy);
1320 #endif // #ifndef MINIZ_NO_ZLIB_APIS
1321 
1322 #define MZ_UINT16_MAX (0xFFFFU)
1323 #define MZ_UINT32_MAX (0xFFFFFFFFU)
1324 
1325 #ifdef __cplusplus
1326 }
1327 #endif
1328 
1329 #endif // MINIZ_HEADER_INCLUDED
1330 
1331 // ------------------- End of Header: Implementation follows. (If you only want
1332 // the header, define MINIZ_HEADER_FILE_ONLY.)
1333 
1334 #ifndef MINIZ_HEADER_FILE_ONLY
1335 
1336 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1337 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1338 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
1339 
1340 #include <assert.h>
1341 #include <string.h>
1342 
1343 #define MZ_ASSERT(x) assert(x)
1344 
1345 #ifdef MINIZ_NO_MALLOC
1346 #define MZ_MALLOC(x) NULL
1347 #define MZ_FREE(x) (void)x, ((void)0)
1348 #define MZ_REALLOC(p, x) NULL
1349 #else
1350 #define MZ_MALLOC(x) malloc(x)
1351 #define MZ_FREE(x) free(x)
1352 #define MZ_REALLOC(p, x) realloc(p, x)
1353 #endif
1354 
1355 #define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
1356 #define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))
1357 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
1358 
1359 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1360 #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
1361 #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
1362 #else
1363 #define MZ_READ_LE16(p)                                                        \
1364   ((mz_uint32)(((const mz_uint8 *)(p))[0]) |                                   \
1365    ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
1366 #define MZ_READ_LE32(p)                                                        \
1367   ((mz_uint32)(((const mz_uint8 *)(p))[0]) |                                   \
1368    ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) |                           \
1369    ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) |                          \
1370    ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
1371 #endif
1372 
1373 #define MZ_READ_LE64(p)                                                        \
1374   (((mz_uint64)MZ_READ_LE32(p)) |                                              \
1375    (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32)))       \
1376     << 32U))
1377 
1378 #ifdef _MSC_VER
1379 #define MZ_FORCEINLINE __forceinline
1380 #elif defined(__GNUC__)
1381 #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
1382 #else
1383 #define MZ_FORCEINLINE inline
1384 #endif
1385 
1386 #ifdef __cplusplus
1387 extern "C" {
1388 #endif
1389 
1390 // ------------------- zlib-style API's
1391 
mz_adler32(mz_ulong adler,const unsigned char * ptr,size_t buf_len)1392 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) {
1393   mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
1394   size_t block_len = buf_len % 5552;
1395   if (!ptr)
1396     return MZ_ADLER32_INIT;
1397   while (buf_len) {
1398     for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
1399       s1 += ptr[0], s2 += s1;
1400       s1 += ptr[1], s2 += s1;
1401       s1 += ptr[2], s2 += s1;
1402       s1 += ptr[3], s2 += s1;
1403       s1 += ptr[4], s2 += s1;
1404       s1 += ptr[5], s2 += s1;
1405       s1 += ptr[6], s2 += s1;
1406       s1 += ptr[7], s2 += s1;
1407     }
1408     for (; i < block_len; ++i)
1409       s1 += *ptr++, s2 += s1;
1410     s1 %= 65521U, s2 %= 65521U;
1411     buf_len -= block_len;
1412     block_len = 5552;
1413   }
1414   return (s2 << 16) + s1;
1415 }
1416 
1417 // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C
1418 // implementation that balances processor cache usage against speed":
1419 // http://www.geocities.com/malbrain/
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)1420 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) {
1421   static const mz_uint32 s_crc32[16] = {
1422       0,          0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
1423       0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1424       0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
1425   mz_uint32 crcu32 = (mz_uint32)crc;
1426   if (!ptr)
1427     return MZ_CRC32_INIT;
1428   crcu32 = ~crcu32;
1429   while (buf_len--) {
1430     mz_uint8 b = *ptr++;
1431     crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
1432     crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
1433   }
1434   return ~crcu32;
1435 }
1436 
mz_free(void * p)1437 void mz_free(void *p) { MZ_FREE(p); }
1438 
1439 #ifndef MINIZ_NO_ZLIB_APIS
1440 
def_alloc_func(void * opaque,size_t items,size_t size)1441 static void *def_alloc_func(void *opaque, size_t items, size_t size) {
1442   (void)opaque, (void)items, (void)size;
1443   return MZ_MALLOC(items * size);
1444 }
def_free_func(void * opaque,void * address)1445 static void def_free_func(void *opaque, void *address) {
1446   (void)opaque, (void)address;
1447   MZ_FREE(address);
1448 }
def_realloc_func(void * opaque,void * address,size_t items,size_t size)1449 static void *def_realloc_func(void *opaque, void *address, size_t items,
1450                               size_t size) {
1451   (void)opaque, (void)address, (void)items, (void)size;
1452   return MZ_REALLOC(address, items * size);
1453 }
1454 
mz_version(void)1455 const char *mz_version(void) { return MZ_VERSION; }
1456 
mz_deflateInit(mz_streamp pStream,int level)1457 int mz_deflateInit(mz_streamp pStream, int level) {
1458   return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9,
1459                          MZ_DEFAULT_STRATEGY);
1460 }
1461 
mz_deflateInit2(mz_streamp pStream,int level,int method,int window_bits,int mem_level,int strategy)1462 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
1463                     int mem_level, int strategy) {
1464   tdefl_compressor *pComp;
1465   mz_uint comp_flags =
1466       TDEFL_COMPUTE_ADLER32 |
1467       tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
1468 
1469   if (!pStream)
1470     return MZ_STREAM_ERROR;
1471   if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) ||
1472       ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
1473        (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
1474     return MZ_PARAM_ERROR;
1475 
1476   pStream->data_type = 0;
1477   pStream->adler = MZ_ADLER32_INIT;
1478   pStream->msg = NULL;
1479   pStream->reserved = 0;
1480   pStream->total_in = 0;
1481   pStream->total_out = 0;
1482   if (!pStream->zalloc)
1483     pStream->zalloc = def_alloc_func;
1484   if (!pStream->zfree)
1485     pStream->zfree = def_free_func;
1486 
1487   pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1,
1488                                               sizeof(tdefl_compressor));
1489   if (!pComp)
1490     return MZ_MEM_ERROR;
1491 
1492   pStream->state = (struct mz_internal_state *)pComp;
1493 
1494   if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) {
1495     mz_deflateEnd(pStream);
1496     return MZ_PARAM_ERROR;
1497   }
1498 
1499   return MZ_OK;
1500 }
1501 
mz_deflateReset(mz_streamp pStream)1502 int mz_deflateReset(mz_streamp pStream) {
1503   if ((!pStream) || (!pStream->state) || (!pStream->zalloc) ||
1504       (!pStream->zfree))
1505     return MZ_STREAM_ERROR;
1506   pStream->total_in = pStream->total_out = 0;
1507   tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL,
1508              ((tdefl_compressor *)pStream->state)->m_flags);
1509   return MZ_OK;
1510 }
1511 
mz_deflate(mz_streamp pStream,int flush)1512 int mz_deflate(mz_streamp pStream, int flush) {
1513   size_t in_bytes, out_bytes;
1514   mz_ulong orig_total_in, orig_total_out;
1515   int mz_status = MZ_OK;
1516 
1517   if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) ||
1518       (!pStream->next_out))
1519     return MZ_STREAM_ERROR;
1520   if (!pStream->avail_out)
1521     return MZ_BUF_ERROR;
1522 
1523   if (flush == MZ_PARTIAL_FLUSH)
1524     flush = MZ_SYNC_FLUSH;
1525 
1526   if (((tdefl_compressor *)pStream->state)->m_prev_return_status ==
1527       TDEFL_STATUS_DONE)
1528     return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
1529 
1530   orig_total_in = pStream->total_in;
1531   orig_total_out = pStream->total_out;
1532   for (;;) {
1533     tdefl_status defl_status;
1534     in_bytes = pStream->avail_in;
1535     out_bytes = pStream->avail_out;
1536 
1537     defl_status = tdefl_compress((tdefl_compressor *)pStream->state,
1538                                  pStream->next_in, &in_bytes, pStream->next_out,
1539                                  &out_bytes, (tdefl_flush)flush);
1540     pStream->next_in += (mz_uint)in_bytes;
1541     pStream->avail_in -= (mz_uint)in_bytes;
1542     pStream->total_in += (mz_uint)in_bytes;
1543     pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
1544 
1545     pStream->next_out += (mz_uint)out_bytes;
1546     pStream->avail_out -= (mz_uint)out_bytes;
1547     pStream->total_out += (mz_uint)out_bytes;
1548 
1549     if (defl_status < 0) {
1550       mz_status = MZ_STREAM_ERROR;
1551       break;
1552     } else if (defl_status == TDEFL_STATUS_DONE) {
1553       mz_status = MZ_STREAM_END;
1554       break;
1555     } else if (!pStream->avail_out)
1556       break;
1557     else if ((!pStream->avail_in) && (flush != MZ_FINISH)) {
1558       if ((flush) || (pStream->total_in != orig_total_in) ||
1559           (pStream->total_out != orig_total_out))
1560         break;
1561       return MZ_BUF_ERROR; // Can't make forward progress without some input.
1562     }
1563   }
1564   return mz_status;
1565 }
1566 
mz_deflateEnd(mz_streamp pStream)1567 int mz_deflateEnd(mz_streamp pStream) {
1568   if (!pStream)
1569     return MZ_STREAM_ERROR;
1570   if (pStream->state) {
1571     pStream->zfree(pStream->opaque, pStream->state);
1572     pStream->state = NULL;
1573   }
1574   return MZ_OK;
1575 }
1576 
mz_deflateBound(mz_streamp pStream,mz_ulong source_len)1577 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) {
1578   (void)pStream;
1579   // This is really over conservative. (And lame, but it's actually pretty
1580   // tricky to compute a true upper bound given the way tdefl's blocking works.)
1581   return MZ_MAX(128 + (source_len * 110) / 100,
1582                 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
1583 }
1584 
mz_compress2(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len,int level)1585 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
1586                  const unsigned char *pSource, mz_ulong source_len, int level) {
1587   int status;
1588   mz_stream stream;
1589   memset(&stream, 0, sizeof(stream));
1590 
1591   // In case mz_ulong is 64-bits (argh I hate longs).
1592   if ((source_len | *pDest_len) > 0xFFFFFFFFU)
1593     return MZ_PARAM_ERROR;
1594 
1595   stream.next_in = pSource;
1596   stream.avail_in = (mz_uint32)source_len;
1597   stream.next_out = pDest;
1598   stream.avail_out = (mz_uint32)*pDest_len;
1599 
1600   status = mz_deflateInit(&stream, level);
1601   if (status != MZ_OK)
1602     return status;
1603 
1604   status = mz_deflate(&stream, MZ_FINISH);
1605   if (status != MZ_STREAM_END) {
1606     mz_deflateEnd(&stream);
1607     return (status == MZ_OK) ? MZ_BUF_ERROR : status;
1608   }
1609 
1610   *pDest_len = stream.total_out;
1611   return mz_deflateEnd(&stream);
1612 }
1613 
mz_compress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)1614 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
1615                 const unsigned char *pSource, mz_ulong source_len) {
1616   return mz_compress2(pDest, pDest_len, pSource, source_len,
1617                       MZ_DEFAULT_COMPRESSION);
1618 }
1619 
mz_compressBound(mz_ulong source_len)1620 mz_ulong mz_compressBound(mz_ulong source_len) {
1621   return mz_deflateBound(NULL, source_len);
1622 }
1623 
1624 typedef struct {
1625   tinfl_decompressor m_decomp;
1626   mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
1627   int m_window_bits;
1628   mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
1629   tinfl_status m_last_status;
1630 } inflate_state;
1631 
mz_inflateInit2(mz_streamp pStream,int window_bits)1632 int mz_inflateInit2(mz_streamp pStream, int window_bits) {
1633   inflate_state *pDecomp;
1634   if (!pStream)
1635     return MZ_STREAM_ERROR;
1636   if ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
1637       (-window_bits != MZ_DEFAULT_WINDOW_BITS))
1638     return MZ_PARAM_ERROR;
1639 
1640   pStream->data_type = 0;
1641   pStream->adler = 0;
1642   pStream->msg = NULL;
1643   pStream->total_in = 0;
1644   pStream->total_out = 0;
1645   pStream->reserved = 0;
1646   if (!pStream->zalloc)
1647     pStream->zalloc = def_alloc_func;
1648   if (!pStream->zfree)
1649     pStream->zfree = def_free_func;
1650 
1651   pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1,
1652                                              sizeof(inflate_state));
1653   if (!pDecomp)
1654     return MZ_MEM_ERROR;
1655 
1656   pStream->state = (struct mz_internal_state *)pDecomp;
1657 
1658   tinfl_init(&pDecomp->m_decomp);
1659   pDecomp->m_dict_ofs = 0;
1660   pDecomp->m_dict_avail = 0;
1661   pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
1662   pDecomp->m_first_call = 1;
1663   pDecomp->m_has_flushed = 0;
1664   pDecomp->m_window_bits = window_bits;
1665 
1666   return MZ_OK;
1667 }
1668 
mz_inflateInit(mz_streamp pStream)1669 int mz_inflateInit(mz_streamp pStream) {
1670   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
1671 }
1672 
mz_inflate(mz_streamp pStream,int flush)1673 int mz_inflate(mz_streamp pStream, int flush) {
1674   inflate_state *pState;
1675   mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
1676   size_t in_bytes, out_bytes, orig_avail_in;
1677   tinfl_status status;
1678 
1679   if ((!pStream) || (!pStream->state))
1680     return MZ_STREAM_ERROR;
1681   if (flush == MZ_PARTIAL_FLUSH)
1682     flush = MZ_SYNC_FLUSH;
1683   if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
1684     return MZ_STREAM_ERROR;
1685 
1686   pState = (inflate_state *)pStream->state;
1687   if (pState->m_window_bits > 0)
1688     decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
1689   orig_avail_in = pStream->avail_in;
1690 
1691   first_call = pState->m_first_call;
1692   pState->m_first_call = 0;
1693   if (pState->m_last_status < 0)
1694     return MZ_DATA_ERROR;
1695 
1696   if (pState->m_has_flushed && (flush != MZ_FINISH))
1697     return MZ_STREAM_ERROR;
1698   pState->m_has_flushed |= (flush == MZ_FINISH);
1699 
1700   if ((flush == MZ_FINISH) && (first_call)) {
1701     // MZ_FINISH on the first call implies that the input and output buffers are
1702     // large enough to hold the entire compressed/decompressed file.
1703     decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1704     in_bytes = pStream->avail_in;
1705     out_bytes = pStream->avail_out;
1706     status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes,
1707                               pStream->next_out, pStream->next_out, &out_bytes,
1708                               decomp_flags);
1709     pState->m_last_status = status;
1710     pStream->next_in += (mz_uint)in_bytes;
1711     pStream->avail_in -= (mz_uint)in_bytes;
1712     pStream->total_in += (mz_uint)in_bytes;
1713     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1714     pStream->next_out += (mz_uint)out_bytes;
1715     pStream->avail_out -= (mz_uint)out_bytes;
1716     pStream->total_out += (mz_uint)out_bytes;
1717 
1718     if (status < 0)
1719       return MZ_DATA_ERROR;
1720     else if (status != TINFL_STATUS_DONE) {
1721       pState->m_last_status = TINFL_STATUS_FAILED;
1722       return MZ_BUF_ERROR;
1723     }
1724     return MZ_STREAM_END;
1725   }
1726   // flush != MZ_FINISH then we must assume there's more input.
1727   if (flush != MZ_FINISH)
1728     decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
1729 
1730   if (pState->m_dict_avail) {
1731     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1732     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1733     pStream->next_out += n;
1734     pStream->avail_out -= n;
1735     pStream->total_out += n;
1736     pState->m_dict_avail -= n;
1737     pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1738     return ((pState->m_last_status == TINFL_STATUS_DONE) &&
1739             (!pState->m_dict_avail))
1740                ? MZ_STREAM_END
1741                : MZ_OK;
1742   }
1743 
1744   for (;;) {
1745     in_bytes = pStream->avail_in;
1746     out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
1747 
1748     status = tinfl_decompress(
1749         &pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict,
1750         pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
1751     pState->m_last_status = status;
1752 
1753     pStream->next_in += (mz_uint)in_bytes;
1754     pStream->avail_in -= (mz_uint)in_bytes;
1755     pStream->total_in += (mz_uint)in_bytes;
1756     pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1757 
1758     pState->m_dict_avail = (mz_uint)out_bytes;
1759 
1760     n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1761     memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1762     pStream->next_out += n;
1763     pStream->avail_out -= n;
1764     pStream->total_out += n;
1765     pState->m_dict_avail -= n;
1766     pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1767 
1768     if (status < 0)
1769       return MZ_DATA_ERROR; // Stream is corrupted (there could be some
1770                             // uncompressed data left in the output dictionary -
1771                             // oh well).
1772     else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
1773       return MZ_BUF_ERROR; // Signal caller that we can't make forward progress
1774                            // without supplying more input or by setting flush
1775                            // to MZ_FINISH.
1776     else if (flush == MZ_FINISH) {
1777       // The output buffer MUST be large to hold the remaining uncompressed data
1778       // when flush==MZ_FINISH.
1779       if (status == TINFL_STATUS_DONE)
1780         return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
1781       // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's
1782       // at least 1 more byte on the way. If there's no more room left in the
1783       // output buffer then something is wrong.
1784       else if (!pStream->avail_out)
1785         return MZ_BUF_ERROR;
1786     } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) ||
1787                (!pStream->avail_out) || (pState->m_dict_avail))
1788       break;
1789   }
1790 
1791   return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail))
1792              ? MZ_STREAM_END
1793              : MZ_OK;
1794 }
1795 
mz_inflateEnd(mz_streamp pStream)1796 int mz_inflateEnd(mz_streamp pStream) {
1797   if (!pStream)
1798     return MZ_STREAM_ERROR;
1799   if (pStream->state) {
1800     pStream->zfree(pStream->opaque, pStream->state);
1801     pStream->state = NULL;
1802   }
1803   return MZ_OK;
1804 }
1805 
mz_uncompress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)1806 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
1807                   const unsigned char *pSource, mz_ulong source_len) {
1808   mz_stream stream;
1809   int status;
1810   memset(&stream, 0, sizeof(stream));
1811 
1812   // In case mz_ulong is 64-bits (argh I hate longs).
1813   if ((source_len | *pDest_len) > 0xFFFFFFFFU)
1814     return MZ_PARAM_ERROR;
1815 
1816   stream.next_in = pSource;
1817   stream.avail_in = (mz_uint32)source_len;
1818   stream.next_out = pDest;
1819   stream.avail_out = (mz_uint32)*pDest_len;
1820 
1821   status = mz_inflateInit(&stream);
1822   if (status != MZ_OK)
1823     return status;
1824 
1825   status = mz_inflate(&stream, MZ_FINISH);
1826   if (status != MZ_STREAM_END) {
1827     mz_inflateEnd(&stream);
1828     return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR
1829                                                             : status;
1830   }
1831   *pDest_len = stream.total_out;
1832 
1833   return mz_inflateEnd(&stream);
1834 }
1835 
mz_error(int err)1836 const char *mz_error(int err) {
1837   static struct {
1838     int m_err;
1839     const char *m_pDesc;
1840   } s_error_descs[] = {{MZ_OK, ""},
1841                        {MZ_STREAM_END, "stream end"},
1842                        {MZ_NEED_DICT, "need dictionary"},
1843                        {MZ_ERRNO, "file error"},
1844                        {MZ_STREAM_ERROR, "stream error"},
1845                        {MZ_DATA_ERROR, "data error"},
1846                        {MZ_MEM_ERROR, "out of memory"},
1847                        {MZ_BUF_ERROR, "buf error"},
1848                        {MZ_VERSION_ERROR, "version error"},
1849                        {MZ_PARAM_ERROR, "parameter error"}};
1850   mz_uint i;
1851   for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
1852     if (s_error_descs[i].m_err == err)
1853       return s_error_descs[i].m_pDesc;
1854   return NULL;
1855 }
1856 
1857 #endif // MINIZ_NO_ZLIB_APIS
1858 
1859 // ------------------- Low-level Decompression (completely independent from all
1860 // compression API's)
1861 
1862 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
1863 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
1864 
1865 #define TINFL_CR_BEGIN                                                         \
1866   switch (r->m_state) {                                                        \
1867   case 0:
1868 #define TINFL_CR_RETURN(state_index, result)                                   \
1869   do {                                                                         \
1870     status = result;                                                           \
1871     r->m_state = state_index;                                                  \
1872     goto common_exit;                                                          \
1873   case state_index:;                                                           \
1874   }                                                                            \
1875   MZ_MACRO_END
1876 #define TINFL_CR_RETURN_FOREVER(state_index, result)                           \
1877   do {                                                                         \
1878     for (;;) {                                                                 \
1879       TINFL_CR_RETURN(state_index, result);                                    \
1880     }                                                                          \
1881   }                                                                            \
1882   MZ_MACRO_END
1883 #define TINFL_CR_FINISH }
1884 
1885 // TODO: If the caller has indicated that there's no more input, and we attempt
1886 // to read beyond the input buf, then something is wrong with the input because
1887 // the inflator never reads ahead more than it needs to. Currently
1888 // TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
1889 #define TINFL_GET_BYTE(state_index, c)                                         \
1890   do {                                                                         \
1891     if (pIn_buf_cur >= pIn_buf_end) {                                          \
1892       for (;;) {                                                               \
1893         if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {                        \
1894           TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT);         \
1895           if (pIn_buf_cur < pIn_buf_end) {                                     \
1896             c = *pIn_buf_cur++;                                                \
1897             break;                                                             \
1898           }                                                                    \
1899         } else {                                                               \
1900           c = 0;                                                               \
1901           break;                                                               \
1902         }                                                                      \
1903       }                                                                        \
1904     } else                                                                     \
1905       c = *pIn_buf_cur++;                                                      \
1906   }                                                                            \
1907   MZ_MACRO_END
1908 
1909 #define TINFL_NEED_BITS(state_index, n)                                        \
1910   do {                                                                         \
1911     mz_uint c;                                                                 \
1912     TINFL_GET_BYTE(state_index, c);                                            \
1913     bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                             \
1914     num_bits += 8;                                                             \
1915   } while (num_bits < (mz_uint)(n))
1916 #define TINFL_SKIP_BITS(state_index, n)                                        \
1917   do {                                                                         \
1918     if (num_bits < (mz_uint)(n)) {                                             \
1919       TINFL_NEED_BITS(state_index, n);                                         \
1920     }                                                                          \
1921     bit_buf >>= (n);                                                           \
1922     num_bits -= (n);                                                           \
1923   }                                                                            \
1924   MZ_MACRO_END
1925 #define TINFL_GET_BITS(state_index, b, n)                                      \
1926   do {                                                                         \
1927     if (num_bits < (mz_uint)(n)) {                                             \
1928       TINFL_NEED_BITS(state_index, n);                                         \
1929     }                                                                          \
1930     b = bit_buf & ((1 << (n)) - 1);                                            \
1931     bit_buf >>= (n);                                                           \
1932     num_bits -= (n);                                                           \
1933   }                                                                            \
1934   MZ_MACRO_END
1935 
1936 // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
1937 // remaining in the input buffer falls below 2. It reads just enough bytes from
1938 // the input stream that are needed to decode the next Huffman code (and
1939 // absolutely no more). It works by trying to fully decode a Huffman code by
1940 // using whatever bits are currently present in the bit buffer. If this fails,
1941 // it reads another byte, and tries again until it succeeds or until the bit
1942 // buffer contains >=15 bits (deflate's max. Huffman code size).
1943 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
1944   do {                                                                         \
1945     temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];         \
1946     if (temp >= 0) {                                                           \
1947       code_len = temp >> 9;                                                    \
1948       if ((code_len) && (num_bits >= code_len))                                \
1949         break;                                                                 \
1950     } else if (num_bits > TINFL_FAST_LOOKUP_BITS) {                            \
1951       code_len = TINFL_FAST_LOOKUP_BITS;                                       \
1952       do {                                                                     \
1953         temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];         \
1954       } while ((temp < 0) && (num_bits >= (code_len + 1)));                    \
1955       if (temp >= 0)                                                           \
1956         break;                                                                 \
1957     }                                                                          \
1958     TINFL_GET_BYTE(state_index, c);                                            \
1959     bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                             \
1960     num_bits += 8;                                                             \
1961   } while (num_bits < 15);
1962 
1963 // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex
1964 // than you would initially expect because the zlib API expects the decompressor
1965 // to never read beyond the final byte of the deflate stream. (In other words,
1966 // when this macro wants to read another byte from the input, it REALLY needs
1967 // another byte in order to fully decode the next Huffman code.) Handling this
1968 // properly is particularly important on raw deflate (non-zlib) streams, which
1969 // aren't followed by a byte aligned adler-32. The slow path is only executed at
1970 // the very end of the input buffer.
1971 #define TINFL_HUFF_DECODE(state_index, sym, pHuff)                             \
1972   do {                                                                         \
1973     int temp;                                                                  \
1974     mz_uint code_len, c;                                                       \
1975     if (num_bits < 15) {                                                       \
1976       if ((pIn_buf_end - pIn_buf_cur) < 2) {                                   \
1977         TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                            \
1978       } else {                                                                 \
1979         bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) |           \
1980                    (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8));      \
1981         pIn_buf_cur += 2;                                                      \
1982         num_bits += 16;                                                        \
1983       }                                                                        \
1984     }                                                                          \
1985     if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \
1986         0)                                                                     \
1987       code_len = temp >> 9, temp &= 511;                                       \
1988     else {                                                                     \
1989       code_len = TINFL_FAST_LOOKUP_BITS;                                       \
1990       do {                                                                     \
1991         temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];         \
1992       } while (temp < 0);                                                      \
1993     }                                                                          \
1994     sym = temp;                                                                \
1995     bit_buf >>= code_len;                                                      \
1996     num_bits -= code_len;                                                      \
1997   }                                                                            \
1998   MZ_MACRO_END
1999 
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)2000 tinfl_status tinfl_decompress(tinfl_decompressor *r,
2001                               const mz_uint8 *pIn_buf_next,
2002                               size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
2003                               mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
2004                               const mz_uint32 decomp_flags) {
2005   static const int s_length_base[31] = {
2006       3,  4,  5,  6,  7,  8,  9,  10,  11,  13,  15,  17,  19,  23, 27, 31,
2007       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0,  0};
2008   static const int s_length_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
2009                                          1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
2010                                          4, 4, 5, 5, 5, 5, 0, 0, 0};
2011   static const int s_dist_base[32] = {
2012       1,    2,    3,    4,    5,    7,     9,     13,    17,  25,   33,
2013       49,   65,   97,   129,  193,  257,   385,   513,   769, 1025, 1537,
2014       2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0,   0};
2015   static const int s_dist_extra[32] = {0, 0, 0,  0,  1,  1,  2,  2,  3,  3,
2016                                        4, 4, 5,  5,  6,  6,  7,  7,  8,  8,
2017                                        9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
2018   static const mz_uint8 s_length_dezigzag[19] = {
2019       16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2020   static const int s_min_table_sizes[3] = {257, 1, 4};
2021 
2022   tinfl_status status = TINFL_STATUS_FAILED;
2023   mz_uint32 num_bits, dist, counter, num_extra;
2024   tinfl_bit_buf_t bit_buf;
2025   const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
2026                                                   pIn_buf_next + *pIn_buf_size;
2027   mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
2028                                               pOut_buf_next + *pOut_buf_size;
2029   size_t out_buf_size_mask =
2030              (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
2031                  ? (size_t)-1
2032                  : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1,
2033          dist_from_out_buf_start;
2034 
2035   // Ensure the output buffer's size is a power of 2, unless the output buffer
2036   // is large enough to hold the entire output file (in which case it doesn't
2037   // matter).
2038   if (((out_buf_size_mask + 1) & out_buf_size_mask) ||
2039       (pOut_buf_next < pOut_buf_start)) {
2040     *pIn_buf_size = *pOut_buf_size = 0;
2041     return TINFL_STATUS_BAD_PARAM;
2042   }
2043 
2044   num_bits = r->m_num_bits;
2045   bit_buf = r->m_bit_buf;
2046   dist = r->m_dist;
2047   counter = r->m_counter;
2048   num_extra = r->m_num_extra;
2049   dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2050   TINFL_CR_BEGIN
2051 
2052   bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2053   r->m_z_adler32 = r->m_check_adler32 = 1;
2054   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2055     TINFL_GET_BYTE(1, r->m_zhdr0);
2056     TINFL_GET_BYTE(2, r->m_zhdr1);
2057     counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) ||
2058                (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2059     if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2060       counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) ||
2061                   ((out_buf_size_mask + 1) <
2062                    (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2063     if (counter) {
2064       TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2065     }
2066   }
2067 
2068   do {
2069     TINFL_GET_BITS(3, r->m_final, 3);
2070     r->m_type = r->m_final >> 1;
2071     if (r->m_type == 0) {
2072       TINFL_SKIP_BITS(5, num_bits & 7);
2073       for (counter = 0; counter < 4; ++counter) {
2074         if (num_bits)
2075           TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2076         else
2077           TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2078       }
2079       if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) !=
2080           (mz_uint)(0xFFFF ^
2081                     (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) {
2082         TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2083       }
2084       while ((counter) && (num_bits)) {
2085         TINFL_GET_BITS(51, dist, 8);
2086         while (pOut_buf_cur >= pOut_buf_end) {
2087           TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2088         }
2089         *pOut_buf_cur++ = (mz_uint8)dist;
2090         counter--;
2091       }
2092       while (counter) {
2093         size_t n;
2094         while (pOut_buf_cur >= pOut_buf_end) {
2095           TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2096         }
2097         while (pIn_buf_cur >= pIn_buf_end) {
2098           if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {
2099             TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
2100           } else {
2101             TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
2102           }
2103         }
2104         n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur),
2105                           (size_t)(pIn_buf_end - pIn_buf_cur)),
2106                    counter);
2107         TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2108         pIn_buf_cur += n;
2109         pOut_buf_cur += n;
2110         counter -= (mz_uint)n;
2111       }
2112     } else if (r->m_type == 3) {
2113       TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2114     } else {
2115       if (r->m_type == 1) {
2116         mz_uint8 *p = r->m_tables[0].m_code_size;
2117         mz_uint i;
2118         r->m_table_sizes[0] = 288;
2119         r->m_table_sizes[1] = 32;
2120         TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2121         for (i = 0; i <= 143; ++i)
2122           *p++ = 8;
2123         for (; i <= 255; ++i)
2124           *p++ = 9;
2125         for (; i <= 279; ++i)
2126           *p++ = 7;
2127         for (; i <= 287; ++i)
2128           *p++ = 8;
2129       } else {
2130         for (counter = 0; counter < 3; counter++) {
2131           TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2132           r->m_table_sizes[counter] += s_min_table_sizes[counter];
2133         }
2134         MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2135         for (counter = 0; counter < r->m_table_sizes[2]; counter++) {
2136           mz_uint s;
2137           TINFL_GET_BITS(14, s, 3);
2138           r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2139         }
2140         r->m_table_sizes[2] = 19;
2141       }
2142       for (; (int)r->m_type >= 0; r->m_type--) {
2143         int tree_next, tree_cur;
2144         tinfl_huff_table *pTable;
2145         mz_uint i, j, used_syms, total, sym_index, next_code[17],
2146             total_syms[16];
2147         pTable = &r->m_tables[r->m_type];
2148         MZ_CLEAR_OBJ(total_syms);
2149         MZ_CLEAR_OBJ(pTable->m_look_up);
2150         MZ_CLEAR_OBJ(pTable->m_tree);
2151         for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2152           total_syms[pTable->m_code_size[i]]++;
2153         used_syms = 0, total = 0;
2154         next_code[0] = next_code[1] = 0;
2155         for (i = 1; i <= 15; ++i) {
2156           used_syms += total_syms[i];
2157           next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2158         }
2159         if ((65536 != total) && (used_syms > 1)) {
2160           TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2161         }
2162         for (tree_next = -1, sym_index = 0;
2163              sym_index < r->m_table_sizes[r->m_type]; ++sym_index) {
2164           mz_uint rev_code = 0, l, cur_code,
2165                   code_size = pTable->m_code_size[sym_index];
2166           if (!code_size)
2167             continue;
2168           cur_code = next_code[code_size]++;
2169           for (l = code_size; l > 0; l--, cur_code >>= 1)
2170             rev_code = (rev_code << 1) | (cur_code & 1);
2171           if (code_size <= TINFL_FAST_LOOKUP_BITS) {
2172             mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2173             while (rev_code < TINFL_FAST_LOOKUP_SIZE) {
2174               pTable->m_look_up[rev_code] = k;
2175               rev_code += (1 << code_size);
2176             }
2177             continue;
2178           }
2179           if (0 ==
2180               (tree_cur = pTable->m_look_up[rev_code &
2181                                             (TINFL_FAST_LOOKUP_SIZE - 1)])) {
2182             pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] =
2183                 (mz_int16)tree_next;
2184             tree_cur = tree_next;
2185             tree_next -= 2;
2186           }
2187           rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2188           for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) {
2189             tree_cur -= ((rev_code >>= 1) & 1);
2190             if (!pTable->m_tree[-tree_cur - 1]) {
2191               pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2192               tree_cur = tree_next;
2193               tree_next -= 2;
2194             } else
2195               tree_cur = pTable->m_tree[-tree_cur - 1];
2196           }
2197           rev_code >>= 1;
2198           tree_cur -= (rev_code & 1);
2199           pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2200         }
2201         if (r->m_type == 2) {
2202           for (counter = 0;
2203                counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) {
2204             mz_uint s;
2205             TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2206             if (dist < 16) {
2207               r->m_len_codes[counter++] = (mz_uint8)dist;
2208               continue;
2209             }
2210             if ((dist == 16) && (!counter)) {
2211               TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2212             }
2213             num_extra = "\02\03\07"[dist - 16];
2214             TINFL_GET_BITS(18, s, num_extra);
2215             s += "\03\03\013"[dist - 16];
2216             TINFL_MEMSET(r->m_len_codes + counter,
2217                          (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2218             counter += s;
2219           }
2220           if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) {
2221             TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2222           }
2223           TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes,
2224                        r->m_table_sizes[0]);
2225           TINFL_MEMCPY(r->m_tables[1].m_code_size,
2226                        r->m_len_codes + r->m_table_sizes[0],
2227                        r->m_table_sizes[1]);
2228         }
2229       }
2230       for (;;) {
2231         mz_uint8 *pSrc;
2232         for (;;) {
2233           if (((pIn_buf_end - pIn_buf_cur) < 4) ||
2234               ((pOut_buf_end - pOut_buf_cur) < 2)) {
2235             TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2236             if (counter >= 256)
2237               break;
2238             while (pOut_buf_cur >= pOut_buf_end) {
2239               TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2240             }
2241             *pOut_buf_cur++ = (mz_uint8)counter;
2242           } else {
2243             int sym2;
2244             mz_uint code_len;
2245 #if TINFL_USE_64BIT_BITBUF
2246             if (num_bits < 30) {
2247               bit_buf |=
2248                   (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2249               pIn_buf_cur += 4;
2250               num_bits += 32;
2251             }
2252 #else
2253             if (num_bits < 15) {
2254               bit_buf |=
2255                   (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2256               pIn_buf_cur += 2;
2257               num_bits += 16;
2258             }
2259 #endif
2260             if ((sym2 =
2261                      r->m_tables[0]
2262                          .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2263                 0)
2264               code_len = sym2 >> 9;
2265             else {
2266               code_len = TINFL_FAST_LOOKUP_BITS;
2267               do {
2268                 sym2 = r->m_tables[0]
2269                            .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2270               } while (sym2 < 0);
2271             }
2272             counter = sym2;
2273             bit_buf >>= code_len;
2274             num_bits -= code_len;
2275             if (counter & 256)
2276               break;
2277 
2278 #if !TINFL_USE_64BIT_BITBUF
2279             if (num_bits < 15) {
2280               bit_buf |=
2281                   (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2282               pIn_buf_cur += 2;
2283               num_bits += 16;
2284             }
2285 #endif
2286             if ((sym2 =
2287                      r->m_tables[0]
2288                          .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2289                 0)
2290               code_len = sym2 >> 9;
2291             else {
2292               code_len = TINFL_FAST_LOOKUP_BITS;
2293               do {
2294                 sym2 = r->m_tables[0]
2295                            .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2296               } while (sym2 < 0);
2297             }
2298             bit_buf >>= code_len;
2299             num_bits -= code_len;
2300 
2301             pOut_buf_cur[0] = (mz_uint8)counter;
2302             if (sym2 & 256) {
2303               pOut_buf_cur++;
2304               counter = sym2;
2305               break;
2306             }
2307             pOut_buf_cur[1] = (mz_uint8)sym2;
2308             pOut_buf_cur += 2;
2309           }
2310         }
2311         if ((counter &= 511) == 256)
2312           break;
2313 
2314         num_extra = s_length_extra[counter - 257];
2315         counter = s_length_base[counter - 257];
2316         if (num_extra) {
2317           mz_uint extra_bits;
2318           TINFL_GET_BITS(25, extra_bits, num_extra);
2319           counter += extra_bits;
2320         }
2321 
2322         TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2323         num_extra = s_dist_extra[dist];
2324         dist = s_dist_base[dist];
2325         if (num_extra) {
2326           mz_uint extra_bits;
2327           TINFL_GET_BITS(27, extra_bits, num_extra);
2328           dist += extra_bits;
2329         }
2330 
2331         dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2332         if ((dist > dist_from_out_buf_start) &&
2333             (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) {
2334           TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2335         }
2336 
2337         pSrc = pOut_buf_start +
2338                ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2339 
2340         if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
2341           while (counter--) {
2342             while (pOut_buf_cur >= pOut_buf_end) {
2343               TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2344             }
2345             *pOut_buf_cur++ =
2346                 pOut_buf_start[(dist_from_out_buf_start++ - dist) &
2347                                out_buf_size_mask];
2348           }
2349           continue;
2350         }
2351 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2352         else if ((counter >= 9) && (counter <= dist)) {
2353           const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2354           do {
2355             ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2356             ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2357             pOut_buf_cur += 8;
2358           } while ((pSrc += 8) < pSrc_end);
2359           if ((counter &= 7) < 3) {
2360             if (counter) {
2361               pOut_buf_cur[0] = pSrc[0];
2362               if (counter > 1)
2363                 pOut_buf_cur[1] = pSrc[1];
2364               pOut_buf_cur += counter;
2365             }
2366             continue;
2367           }
2368         }
2369 #endif
2370         do {
2371           pOut_buf_cur[0] = pSrc[0];
2372           pOut_buf_cur[1] = pSrc[1];
2373           pOut_buf_cur[2] = pSrc[2];
2374           pOut_buf_cur += 3;
2375           pSrc += 3;
2376         } while ((int)(counter -= 3) > 2);
2377         if ((int)counter > 0) {
2378           pOut_buf_cur[0] = pSrc[0];
2379           if ((int)counter > 1)
2380             pOut_buf_cur[1] = pSrc[1];
2381           pOut_buf_cur += counter;
2382         }
2383       }
2384     }
2385   } while (!(r->m_final & 1));
2386   if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2387     TINFL_SKIP_BITS(32, num_bits & 7);
2388     for (counter = 0; counter < 4; ++counter) {
2389       mz_uint s;
2390       if (num_bits)
2391         TINFL_GET_BITS(41, s, 8);
2392       else
2393         TINFL_GET_BYTE(42, s);
2394       r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2395     }
2396   }
2397   TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2398   TINFL_CR_FINISH
2399 
2400 common_exit:
2401   r->m_num_bits = num_bits;
2402   r->m_bit_buf = bit_buf;
2403   r->m_dist = dist;
2404   r->m_counter = counter;
2405   r->m_num_extra = num_extra;
2406   r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2407   *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2408   *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2409   if ((decomp_flags &
2410        (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) &&
2411       (status >= 0)) {
2412     const mz_uint8 *ptr = pOut_buf_next;
2413     size_t buf_len = *pOut_buf_size;
2414     mz_uint32 i, s1 = r->m_check_adler32 & 0xffff,
2415                  s2 = r->m_check_adler32 >> 16;
2416     size_t block_len = buf_len % 5552;
2417     while (buf_len) {
2418       for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
2419         s1 += ptr[0], s2 += s1;
2420         s1 += ptr[1], s2 += s1;
2421         s1 += ptr[2], s2 += s1;
2422         s1 += ptr[3], s2 += s1;
2423         s1 += ptr[4], s2 += s1;
2424         s1 += ptr[5], s2 += s1;
2425         s1 += ptr[6], s2 += s1;
2426         s1 += ptr[7], s2 += s1;
2427       }
2428       for (; i < block_len; ++i)
2429         s1 += *ptr++, s2 += s1;
2430       s1 %= 65521U, s2 %= 65521U;
2431       buf_len -= block_len;
2432       block_len = 5552;
2433     }
2434     r->m_check_adler32 = (s2 << 16) + s1;
2435     if ((status == TINFL_STATUS_DONE) &&
2436         (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) &&
2437         (r->m_check_adler32 != r->m_z_adler32))
2438       status = TINFL_STATUS_ADLER32_MISMATCH;
2439   }
2440   return status;
2441 }
2442 
2443 // Higher level helper functions.
tinfl_decompress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2444 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
2445                                    size_t *pOut_len, int flags) {
2446   tinfl_decompressor decomp;
2447   void *pBuf = NULL, *pNew_buf;
2448   size_t src_buf_ofs = 0, out_buf_capacity = 0;
2449   *pOut_len = 0;
2450   tinfl_init(&decomp);
2451   for (;;) {
2452     size_t src_buf_size = src_buf_len - src_buf_ofs,
2453            dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2454     tinfl_status status = tinfl_decompress(
2455         &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
2456         (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
2457         &dst_buf_size,
2458         (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2459             TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2460     if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
2461       MZ_FREE(pBuf);
2462       *pOut_len = 0;
2463       return NULL;
2464     }
2465     src_buf_ofs += src_buf_size;
2466     *pOut_len += dst_buf_size;
2467     if (status == TINFL_STATUS_DONE)
2468       break;
2469     new_out_buf_capacity = out_buf_capacity * 2;
2470     if (new_out_buf_capacity < 128)
2471       new_out_buf_capacity = 128;
2472     pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2473     if (!pNew_buf) {
2474       MZ_FREE(pBuf);
2475       *pOut_len = 0;
2476       return NULL;
2477     }
2478     pBuf = pNew_buf;
2479     out_buf_capacity = new_out_buf_capacity;
2480   }
2481   return pBuf;
2482 }
2483 
tinfl_decompress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2484 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
2485                                    const void *pSrc_buf, size_t src_buf_len,
2486                                    int flags) {
2487   tinfl_decompressor decomp;
2488   tinfl_status status;
2489   tinfl_init(&decomp);
2490   status =
2491       tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len,
2492                        (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
2493                        (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2494                            TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2495   return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
2496                                        : out_buf_len;
2497 }
2498 
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)2499 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
2500                                      tinfl_put_buf_func_ptr pPut_buf_func,
2501                                      void *pPut_buf_user, int flags) {
2502   int result = 0;
2503   tinfl_decompressor decomp;
2504   mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2505   size_t in_buf_ofs = 0, dict_ofs = 0;
2506   if (!pDict)
2507     return TINFL_STATUS_FAILED;
2508   tinfl_init(&decomp);
2509   for (;;) {
2510     size_t in_buf_size = *pIn_buf_size - in_buf_ofs,
2511            dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2512     tinfl_status status =
2513         tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
2514                          &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2515                          (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
2516                                     TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2517     in_buf_ofs += in_buf_size;
2518     if ((dst_buf_size) &&
2519         (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2520       break;
2521     if (status != TINFL_STATUS_HAS_MORE_OUTPUT) {
2522       result = (status == TINFL_STATUS_DONE);
2523       break;
2524     }
2525     dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2526   }
2527   MZ_FREE(pDict);
2528   *pIn_buf_size = in_buf_ofs;
2529   return result;
2530 }
2531 
2532 // ------------------- Low-level Compression (independent from all decompression
2533 // API's)
2534 
2535 // Purposely making these tables static for faster init and thread safety.
2536 static const mz_uint16 s_tdefl_len_sym[256] = {
2537     257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268,
2538     268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272,
2539     272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274,
2540     274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276,
2541     276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
2542     277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
2543     278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279,
2544     279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
2545     280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281,
2546     281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
2547     281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282,
2548     282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
2549     282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283,
2550     283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
2551     283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
2552     284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2553     284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2554     285};
2555 
2556 static const mz_uint8 s_tdefl_len_extra[256] = {
2557     0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2558     2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2559     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
2560     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2561     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2562     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2563     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2564     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2565     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2566     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2567     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0};
2568 
2569 static const mz_uint8 s_tdefl_small_dist_sym[512] = {
2570     0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,
2571     8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10,
2572     10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
2573     11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2574     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2575     12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2576     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
2577     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2578     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2579     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2580     14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2581     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2582     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2583     15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2584     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2585     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2586     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2587     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2588     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2589     16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2590     16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2591     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2592     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2593     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2594     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2595     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2596     17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17};
2597 
2598 static const mz_uint8 s_tdefl_small_dist_extra[512] = {
2599     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,
2600     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,
2601     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2602     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2603     5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2604     5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2605     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2606     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2607     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2608     6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2609     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,
2610     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2611     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2612     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2613     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2614     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2615     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2616     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2617     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2618     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2619     7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
2620 
2621 static const mz_uint8 s_tdefl_large_dist_sym[128] = {
2622     0,  0,  18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24,
2623     24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
2624     26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
2625     27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2626     28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2627     28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2628     29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
2629 
2630 static const mz_uint8 s_tdefl_large_dist_extra[128] = {
2631     0,  0,  8,  8,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
2632     11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
2633     12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2634     12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2635     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2636     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2637     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
2638 
2639 // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
2640 // values.
2641 typedef struct {
2642   mz_uint16 m_key, m_sym_index;
2643 } tdefl_sym_freq;
tdefl_radix_sort_syms(mz_uint num_syms,tdefl_sym_freq * pSyms0,tdefl_sym_freq * pSyms1)2644 static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
2645                                              tdefl_sym_freq *pSyms0,
2646                                              tdefl_sym_freq *pSyms1) {
2647   mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
2648   tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
2649   MZ_CLEAR_OBJ(hist);
2650   for (i = 0; i < num_syms; i++) {
2651     mz_uint freq = pSyms0[i].m_key;
2652     hist[freq & 0xFF]++;
2653     hist[256 + ((freq >> 8) & 0xFF)]++;
2654   }
2655   while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
2656     total_passes--;
2657   for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
2658     const mz_uint32 *pHist = &hist[pass << 8];
2659     mz_uint offsets[256], cur_ofs = 0;
2660     for (i = 0; i < 256; i++) {
2661       offsets[i] = cur_ofs;
2662       cur_ofs += pHist[i];
2663     }
2664     for (i = 0; i < num_syms; i++)
2665       pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] =
2666           pCur_syms[i];
2667     {
2668       tdefl_sym_freq *t = pCur_syms;
2669       pCur_syms = pNew_syms;
2670       pNew_syms = t;
2671     }
2672   }
2673   return pCur_syms;
2674 }
2675 
2676 // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat,
2677 // alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
tdefl_calculate_minimum_redundancy(tdefl_sym_freq * A,int n)2678 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
2679   int root, leaf, next, avbl, used, dpth;
2680   if (n == 0)
2681     return;
2682   else if (n == 1) {
2683     A[0].m_key = 1;
2684     return;
2685   }
2686   A[0].m_key += A[1].m_key;
2687   root = 0;
2688   leaf = 2;
2689   for (next = 1; next < n - 1; next++) {
2690     if (leaf >= n || A[root].m_key < A[leaf].m_key) {
2691       A[next].m_key = A[root].m_key;
2692       A[root++].m_key = (mz_uint16)next;
2693     } else
2694       A[next].m_key = A[leaf++].m_key;
2695     if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) {
2696       A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
2697       A[root++].m_key = (mz_uint16)next;
2698     } else
2699       A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
2700   }
2701   A[n - 2].m_key = 0;
2702   for (next = n - 3; next >= 0; next--)
2703     A[next].m_key = A[A[next].m_key].m_key + 1;
2704   avbl = 1;
2705   used = dpth = 0;
2706   root = n - 2;
2707   next = n - 1;
2708   while (avbl > 0) {
2709     while (root >= 0 && (int)A[root].m_key == dpth) {
2710       used++;
2711       root--;
2712     }
2713     while (avbl > used) {
2714       A[next--].m_key = (mz_uint16)(dpth);
2715       avbl--;
2716     }
2717     avbl = 2 * used;
2718     dpth++;
2719     used = 0;
2720   }
2721 }
2722 
2723 // Limits canonical Huffman code table's max code size.
2724 enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
tdefl_huffman_enforce_max_code_size(int * pNum_codes,int code_list_len,int max_code_size)2725 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes,
2726                                                 int code_list_len,
2727                                                 int max_code_size) {
2728   int i;
2729   mz_uint32 total = 0;
2730   if (code_list_len <= 1)
2731     return;
2732   for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
2733     pNum_codes[max_code_size] += pNum_codes[i];
2734   for (i = max_code_size; i > 0; i--)
2735     total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
2736   while (total != (1UL << max_code_size)) {
2737     pNum_codes[max_code_size]--;
2738     for (i = max_code_size - 1; i > 0; i--)
2739       if (pNum_codes[i]) {
2740         pNum_codes[i]--;
2741         pNum_codes[i + 1] += 2;
2742         break;
2743       }
2744     total--;
2745   }
2746 }
2747 
tdefl_optimize_huffman_table(tdefl_compressor * d,int table_num,int table_len,int code_size_limit,int static_table)2748 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num,
2749                                          int table_len, int code_size_limit,
2750                                          int static_table) {
2751   int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
2752   mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
2753   MZ_CLEAR_OBJ(num_codes);
2754   if (static_table) {
2755     for (i = 0; i < table_len; i++)
2756       num_codes[d->m_huff_code_sizes[table_num][i]]++;
2757   } else {
2758     tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS],
2759         *pSyms;
2760     int num_used_syms = 0;
2761     const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
2762     for (i = 0; i < table_len; i++)
2763       if (pSym_count[i]) {
2764         syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
2765         syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
2766       }
2767 
2768     pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
2769     tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
2770 
2771     for (i = 0; i < num_used_syms; i++)
2772       num_codes[pSyms[i].m_key]++;
2773 
2774     tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms,
2775                                         code_size_limit);
2776 
2777     MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
2778     MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
2779     for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
2780       for (l = num_codes[i]; l > 0; l--)
2781         d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
2782   }
2783 
2784   next_code[1] = 0;
2785   for (j = 0, i = 2; i <= code_size_limit; i++)
2786     next_code[i] = j = ((j + num_codes[i - 1]) << 1);
2787 
2788   for (i = 0; i < table_len; i++) {
2789     mz_uint rev_code = 0, code, code_size;
2790     if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
2791       continue;
2792     code = next_code[code_size]++;
2793     for (l = code_size; l > 0; l--, code >>= 1)
2794       rev_code = (rev_code << 1) | (code & 1);
2795     d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
2796   }
2797 }
2798 
2799 #define TDEFL_PUT_BITS(b, l)                                                   \
2800   do {                                                                         \
2801     mz_uint bits = b;                                                          \
2802     mz_uint len = l;                                                           \
2803     MZ_ASSERT(bits <= ((1U << len) - 1U));                                     \
2804     d->m_bit_buffer |= (bits << d->m_bits_in);                                 \
2805     d->m_bits_in += len;                                                       \
2806     while (d->m_bits_in >= 8) {                                                \
2807       if (d->m_pOutput_buf < d->m_pOutput_buf_end)                             \
2808         *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer);                     \
2809       d->m_bit_buffer >>= 8;                                                   \
2810       d->m_bits_in -= 8;                                                       \
2811     }                                                                          \
2812   }                                                                            \
2813   MZ_MACRO_END
2814 
2815 #define TDEFL_RLE_PREV_CODE_SIZE()                                             \
2816   {                                                                            \
2817     if (rle_repeat_count) {                                                    \
2818       if (rle_repeat_count < 3) {                                              \
2819         d->m_huff_count[2][prev_code_size] = (mz_uint16)(                      \
2820             d->m_huff_count[2][prev_code_size] + rle_repeat_count);            \
2821         while (rle_repeat_count--)                                             \
2822           packed_code_sizes[num_packed_code_sizes++] = prev_code_size;         \
2823       } else {                                                                 \
2824         d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);      \
2825         packed_code_sizes[num_packed_code_sizes++] = 16;                       \
2826         packed_code_sizes[num_packed_code_sizes++] =                           \
2827             (mz_uint8)(rle_repeat_count - 3);                                  \
2828       }                                                                        \
2829       rle_repeat_count = 0;                                                    \
2830     }                                                                          \
2831   }
2832 
2833 #define TDEFL_RLE_ZERO_CODE_SIZE()                                             \
2834   {                                                                            \
2835     if (rle_z_count) {                                                         \
2836       if (rle_z_count < 3) {                                                   \
2837         d->m_huff_count[2][0] =                                                \
2838             (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);                  \
2839         while (rle_z_count--)                                                  \
2840           packed_code_sizes[num_packed_code_sizes++] = 0;                      \
2841       } else if (rle_z_count <= 10) {                                          \
2842         d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);      \
2843         packed_code_sizes[num_packed_code_sizes++] = 17;                       \
2844         packed_code_sizes[num_packed_code_sizes++] =                           \
2845             (mz_uint8)(rle_z_count - 3);                                       \
2846       } else {                                                                 \
2847         d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);      \
2848         packed_code_sizes[num_packed_code_sizes++] = 18;                       \
2849         packed_code_sizes[num_packed_code_sizes++] =                           \
2850             (mz_uint8)(rle_z_count - 11);                                      \
2851       }                                                                        \
2852       rle_z_count = 0;                                                         \
2853     }                                                                          \
2854   }
2855 
2856 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {
2857     16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2858 
tdefl_start_dynamic_block(tdefl_compressor * d)2859 static void tdefl_start_dynamic_block(tdefl_compressor *d) {
2860   int num_lit_codes, num_dist_codes, num_bit_lengths;
2861   mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count,
2862       rle_repeat_count, packed_code_sizes_index;
2863   mz_uint8
2864       code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2865       packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2866       prev_code_size = 0xFF;
2867 
2868   d->m_huff_count[0][256] = 1;
2869 
2870   tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
2871   tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
2872 
2873   for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
2874     if (d->m_huff_code_sizes[0][num_lit_codes - 1])
2875       break;
2876   for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
2877     if (d->m_huff_code_sizes[1][num_dist_codes - 1])
2878       break;
2879 
2880   memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0],
2881          sizeof(mz_uint8) * num_lit_codes);
2882   memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0],
2883          sizeof(mz_uint8) * num_dist_codes);
2884   total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
2885   num_packed_code_sizes = 0;
2886   rle_z_count = 0;
2887   rle_repeat_count = 0;
2888 
2889   memset(&d->m_huff_count[2][0], 0,
2890          sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
2891   for (i = 0; i < total_code_sizes_to_pack; i++) {
2892     mz_uint8 code_size = code_sizes_to_pack[i];
2893     if (!code_size) {
2894       TDEFL_RLE_PREV_CODE_SIZE();
2895       if (++rle_z_count == 138) {
2896         TDEFL_RLE_ZERO_CODE_SIZE();
2897       }
2898     } else {
2899       TDEFL_RLE_ZERO_CODE_SIZE();
2900       if (code_size != prev_code_size) {
2901         TDEFL_RLE_PREV_CODE_SIZE();
2902         d->m_huff_count[2][code_size] =
2903             (mz_uint16)(d->m_huff_count[2][code_size] + 1);
2904         packed_code_sizes[num_packed_code_sizes++] = code_size;
2905       } else if (++rle_repeat_count == 6) {
2906         TDEFL_RLE_PREV_CODE_SIZE();
2907       }
2908     }
2909     prev_code_size = code_size;
2910   }
2911   if (rle_repeat_count) {
2912     TDEFL_RLE_PREV_CODE_SIZE();
2913   } else {
2914     TDEFL_RLE_ZERO_CODE_SIZE();
2915   }
2916 
2917   tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
2918 
2919   TDEFL_PUT_BITS(2, 2);
2920 
2921   TDEFL_PUT_BITS(num_lit_codes - 257, 5);
2922   TDEFL_PUT_BITS(num_dist_codes - 1, 5);
2923 
2924   for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
2925     if (d->m_huff_code_sizes
2926             [2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
2927       break;
2928   num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
2929   TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
2930   for (i = 0; (int)i < num_bit_lengths; i++)
2931     TDEFL_PUT_BITS(
2932         d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
2933 
2934   for (packed_code_sizes_index = 0;
2935        packed_code_sizes_index < num_packed_code_sizes;) {
2936     mz_uint code = packed_code_sizes[packed_code_sizes_index++];
2937     MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
2938     TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
2939     if (code >= 16)
2940       TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
2941                      "\02\03\07"[code - 16]);
2942   }
2943 }
2944 
tdefl_start_static_block(tdefl_compressor * d)2945 static void tdefl_start_static_block(tdefl_compressor *d) {
2946   mz_uint i;
2947   mz_uint8 *p = &d->m_huff_code_sizes[0][0];
2948 
2949   for (i = 0; i <= 143; ++i)
2950     *p++ = 8;
2951   for (; i <= 255; ++i)
2952     *p++ = 9;
2953   for (; i <= 279; ++i)
2954     *p++ = 7;
2955   for (; i <= 287; ++i)
2956     *p++ = 8;
2957 
2958   memset(d->m_huff_code_sizes[1], 5, 32);
2959 
2960   tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
2961   tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
2962 
2963   TDEFL_PUT_BITS(1, 2);
2964 }
2965 
2966 static const mz_uint mz_bitmasks[17] = {
2967     0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
2968     0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
2969 
2970 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&             \
2971     MINIZ_HAS_64BIT_REGISTERS
tdefl_compress_lz_codes(tdefl_compressor * d)2972 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
2973   mz_uint flags;
2974   mz_uint8 *pLZ_codes;
2975   mz_uint8 *pOutput_buf = d->m_pOutput_buf;
2976   mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
2977   mz_uint64 bit_buffer = d->m_bit_buffer;
2978   mz_uint bits_in = d->m_bits_in;
2979 
2980 #define TDEFL_PUT_BITS_FAST(b, l)                                              \
2981   {                                                                            \
2982     bit_buffer |= (((mz_uint64)(b)) << bits_in);                               \
2983     bits_in += (l);                                                            \
2984   }
2985 
2986   flags = 1;
2987   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end;
2988        flags >>= 1) {
2989     if (flags == 1)
2990       flags = *pLZ_codes++ | 0x100;
2991 
2992     if (flags & 1) {
2993       mz_uint s0, s1, n0, n1, sym, num_extra_bits;
2994       mz_uint match_len = pLZ_codes[0],
2995               match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
2996       pLZ_codes += 3;
2997 
2998       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2999       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3000                           d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3001       TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3002                           s_tdefl_len_extra[match_len]);
3003 
3004       // This sequence coaxes MSVC into using cmov's vs. jmp's.
3005       s0 = s_tdefl_small_dist_sym[match_dist & 511];
3006       n0 = s_tdefl_small_dist_extra[match_dist & 511];
3007       s1 = s_tdefl_large_dist_sym[match_dist >> 8];
3008       n1 = s_tdefl_large_dist_extra[match_dist >> 8];
3009       sym = (match_dist < 512) ? s0 : s1;
3010       num_extra_bits = (match_dist < 512) ? n0 : n1;
3011 
3012       MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3013       TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym],
3014                           d->m_huff_code_sizes[1][sym]);
3015       TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits],
3016                           num_extra_bits);
3017     } else {
3018       mz_uint lit = *pLZ_codes++;
3019       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3020       TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3021                           d->m_huff_code_sizes[0][lit]);
3022 
3023       if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3024         flags >>= 1;
3025         lit = *pLZ_codes++;
3026         MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3027         TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3028                             d->m_huff_code_sizes[0][lit]);
3029 
3030         if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3031           flags >>= 1;
3032           lit = *pLZ_codes++;
3033           MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3034           TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3035                               d->m_huff_code_sizes[0][lit]);
3036         }
3037       }
3038     }
3039 
3040     if (pOutput_buf >= d->m_pOutput_buf_end)
3041       return MZ_FALSE;
3042 
3043     *(mz_uint64 *)pOutput_buf = bit_buffer;
3044     pOutput_buf += (bits_in >> 3);
3045     bit_buffer >>= (bits_in & ~7);
3046     bits_in &= 7;
3047   }
3048 
3049 #undef TDEFL_PUT_BITS_FAST
3050 
3051   d->m_pOutput_buf = pOutput_buf;
3052   d->m_bits_in = 0;
3053   d->m_bit_buffer = 0;
3054 
3055   while (bits_in) {
3056     mz_uint32 n = MZ_MIN(bits_in, 16);
3057     TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
3058     bit_buffer >>= n;
3059     bits_in -= n;
3060   }
3061 
3062   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3063 
3064   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3065 }
3066 #else
tdefl_compress_lz_codes(tdefl_compressor * d)3067 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3068   mz_uint flags;
3069   mz_uint8 *pLZ_codes;
3070 
3071   flags = 1;
3072   for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf;
3073        flags >>= 1) {
3074     if (flags == 1)
3075       flags = *pLZ_codes++ | 0x100;
3076     if (flags & 1) {
3077       mz_uint sym, num_extra_bits;
3078       mz_uint match_len = pLZ_codes[0],
3079               match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
3080       pLZ_codes += 3;
3081 
3082       MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3083       TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3084                      d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3085       TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3086                      s_tdefl_len_extra[match_len]);
3087 
3088       if (match_dist < 512) {
3089         sym = s_tdefl_small_dist_sym[match_dist];
3090         num_extra_bits = s_tdefl_small_dist_extra[match_dist];
3091       } else {
3092         sym = s_tdefl_large_dist_sym[match_dist >> 8];
3093         num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
3094       }
3095       TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
3096       TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
3097     } else {
3098       mz_uint lit = *pLZ_codes++;
3099       MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3100       TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
3101     }
3102   }
3103 
3104   TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3105 
3106   return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3107 }
3108 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&
3109        // MINIZ_HAS_64BIT_REGISTERS
3110 
tdefl_compress_block(tdefl_compressor * d,mz_bool static_block)3111 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) {
3112   if (static_block)
3113     tdefl_start_static_block(d);
3114   else
3115     tdefl_start_dynamic_block(d);
3116   return tdefl_compress_lz_codes(d);
3117 }
3118 
tdefl_flush_block(tdefl_compressor * d,int flush)3119 static int tdefl_flush_block(tdefl_compressor *d, int flush) {
3120   mz_uint saved_bit_buf, saved_bits_in;
3121   mz_uint8 *pSaved_output_buf;
3122   mz_bool comp_block_succeeded = MZ_FALSE;
3123   int n, use_raw_block =
3124              ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
3125              (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
3126   mz_uint8 *pOutput_buf_start =
3127       ((d->m_pPut_buf_func == NULL) &&
3128        ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
3129           ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs)
3130           : d->m_output_buf;
3131 
3132   d->m_pOutput_buf = pOutput_buf_start;
3133   d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
3134 
3135   MZ_ASSERT(!d->m_output_flush_remaining);
3136   d->m_output_flush_ofs = 0;
3137   d->m_output_flush_remaining = 0;
3138 
3139   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
3140   d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
3141 
3142   if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) {
3143     TDEFL_PUT_BITS(0x78, 8);
3144     TDEFL_PUT_BITS(0x01, 8);
3145   }
3146 
3147   TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
3148 
3149   pSaved_output_buf = d->m_pOutput_buf;
3150   saved_bit_buf = d->m_bit_buffer;
3151   saved_bits_in = d->m_bits_in;
3152 
3153   if (!use_raw_block)
3154     comp_block_succeeded =
3155         tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
3156                                     (d->m_total_lz_bytes < 48));
3157 
3158   // If the block gets expanded, forget the current contents of the output
3159   // buffer and send a raw block instead.
3160   if (((use_raw_block) ||
3161        ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >=
3162                                   d->m_total_lz_bytes))) &&
3163       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) {
3164     mz_uint i;
3165     d->m_pOutput_buf = pSaved_output_buf;
3166     d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3167     TDEFL_PUT_BITS(0, 2);
3168     if (d->m_bits_in) {
3169       TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3170     }
3171     for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) {
3172       TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
3173     }
3174     for (i = 0; i < d->m_total_lz_bytes; ++i) {
3175       TDEFL_PUT_BITS(
3176           d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK],
3177           8);
3178     }
3179   }
3180   // Check for the extremely unlikely (if not impossible) case of the compressed
3181   // block not fitting into the output buffer when using dynamic codes.
3182   else if (!comp_block_succeeded) {
3183     d->m_pOutput_buf = pSaved_output_buf;
3184     d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3185     tdefl_compress_block(d, MZ_TRUE);
3186   }
3187 
3188   if (flush) {
3189     if (flush == TDEFL_FINISH) {
3190       if (d->m_bits_in) {
3191         TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3192       }
3193       if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) {
3194         mz_uint i, a = d->m_adler32;
3195         for (i = 0; i < 4; i++) {
3196           TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
3197           a <<= 8;
3198         }
3199       }
3200     } else {
3201       mz_uint i, z = 0;
3202       TDEFL_PUT_BITS(0, 3);
3203       if (d->m_bits_in) {
3204         TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3205       }
3206       for (i = 2; i; --i, z ^= 0xFFFF) {
3207         TDEFL_PUT_BITS(z & 0xFFFF, 16);
3208       }
3209     }
3210   }
3211 
3212   MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
3213 
3214   memset(&d->m_huff_count[0][0], 0,
3215          sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3216   memset(&d->m_huff_count[1][0], 0,
3217          sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3218 
3219   d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3220   d->m_pLZ_flags = d->m_lz_code_buf;
3221   d->m_num_flags_left = 8;
3222   d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
3223   d->m_total_lz_bytes = 0;
3224   d->m_block_index++;
3225 
3226   if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) {
3227     if (d->m_pPut_buf_func) {
3228       *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3229       if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
3230         return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
3231     } else if (pOutput_buf_start == d->m_output_buf) {
3232       int bytes_to_copy = (int)MZ_MIN(
3233           (size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
3234       memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf,
3235              bytes_to_copy);
3236       d->m_out_buf_ofs += bytes_to_copy;
3237       if ((n -= bytes_to_copy) != 0) {
3238         d->m_output_flush_ofs = bytes_to_copy;
3239         d->m_output_flush_remaining = n;
3240       }
3241     } else {
3242       d->m_out_buf_ofs += n;
3243     }
3244   }
3245 
3246   return d->m_output_flush_remaining;
3247 }
3248 
3249 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3250 #define TDEFL_READ_UNALIGNED_WORD(p) ((p)[0] | (p)[1] << 8)
3251 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)3252 tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3253                  mz_uint max_match_len, mz_uint *pMatch_dist,
3254                  mz_uint *pMatch_len) {
3255   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3256                 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3257                 probe_len;
3258   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3259   const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
3260   mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]),
3261             s01 = *s;
3262   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3263   if (max_match_len <= match_len)
3264     return;
3265   for (;;) {
3266     for (;;) {
3267       if (--num_probes_left == 0)
3268         return;
3269 #define TDEFL_PROBE                                                            \
3270   next_probe_pos = d->m_next[probe_pos];                                       \
3271   if ((!next_probe_pos) ||                                                     \
3272       ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))       \
3273     return;                                                                    \
3274   probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                        \
3275   if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
3276     break;
3277       TDEFL_PROBE;
3278       TDEFL_PROBE;
3279       TDEFL_PROBE;
3280     }
3281     if (!dist)
3282       break;
3283     q = (const mz_uint16 *)(d->m_dict + probe_pos);
3284     if (*q != s01)
3285       continue;
3286     p = s;
3287     probe_len = 32;
3288     do {
3289     } while ((*(++p) == *(++q)) && (*(++p) == *(++q)) && (*(++p) == *(++q)) &&
3290              (*(++p) == *(++q)) && (--probe_len > 0));
3291     if (!probe_len) {
3292       *pMatch_dist = dist;
3293       *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN);
3294       break;
3295     } else if ((probe_len = ((mz_uint)(p - s) * 2) +
3296                             (mz_uint)(*(const mz_uint8 *)p ==
3297                                       *(const mz_uint8 *)q)) > match_len) {
3298       *pMatch_dist = dist;
3299       if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) ==
3300           max_match_len)
3301         break;
3302       c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
3303     }
3304   }
3305 }
3306 #else
3307 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)3308 tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3309                  mz_uint max_match_len, mz_uint *pMatch_dist,
3310                  mz_uint *pMatch_len) {
3311   mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3312                 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3313                 probe_len;
3314   mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3315   const mz_uint8 *s = d->m_dict + pos, *p, *q;
3316   mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
3317   MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3318   if (max_match_len <= match_len)
3319     return;
3320   for (;;) {
3321     for (;;) {
3322       if (--num_probes_left == 0)
3323         return;
3324 #define TDEFL_PROBE                                                            \
3325   next_probe_pos = d->m_next[probe_pos];                                       \
3326   if ((!next_probe_pos) ||                                                     \
3327       ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))       \
3328     return;                                                                    \
3329   probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                        \
3330   if ((d->m_dict[probe_pos + match_len] == c0) &&                              \
3331       (d->m_dict[probe_pos + match_len - 1] == c1))                            \
3332     break;
3333       TDEFL_PROBE;
3334       TDEFL_PROBE;
3335       TDEFL_PROBE;
3336     }
3337     if (!dist)
3338       break;
3339     p = s;
3340     q = d->m_dict + probe_pos;
3341     for (probe_len = 0; probe_len < max_match_len; probe_len++)
3342       if (*p++ != *q++)
3343         break;
3344     if (probe_len > match_len) {
3345       *pMatch_dist = dist;
3346       if ((*pMatch_len = match_len = probe_len) == max_match_len)
3347         return;
3348       c0 = d->m_dict[pos + match_len];
3349       c1 = d->m_dict[pos + match_len - 1];
3350     }
3351   }
3352 }
3353 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3354 
3355 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
tdefl_compress_fast(tdefl_compressor * d)3356 static mz_bool tdefl_compress_fast(tdefl_compressor *d) {
3357   // Faster, minimally featured LZRW1-style match+parse loop with better
3358   // register utilization. Intended for applications where raw throughput is
3359   // valued more highly than ratio.
3360   mz_uint lookahead_pos = d->m_lookahead_pos,
3361           lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size,
3362           total_lz_bytes = d->m_total_lz_bytes,
3363           num_flags_left = d->m_num_flags_left;
3364   mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
3365   mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3366 
3367   while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
3368     const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
3369     mz_uint dst_pos =
3370         (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
3371     mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3372         d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
3373     d->m_src_buf_left -= num_bytes_to_process;
3374     lookahead_size += num_bytes_to_process;
3375 
3376     while (num_bytes_to_process) {
3377       mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
3378       memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
3379       if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3380         memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc,
3381                MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
3382       d->m_pSrc += n;
3383       dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
3384       num_bytes_to_process -= n;
3385     }
3386 
3387     dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
3388     if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
3389       break;
3390 
3391     while (lookahead_size >= 4) {
3392       mz_uint cur_match_dist, cur_match_len = 1;
3393       mz_uint8 *pCur_dict = d->m_dict + cur_pos;
3394       mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
3395       mz_uint hash =
3396           (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) &
3397           TDEFL_LEVEL1_HASH_SIZE_MASK;
3398       mz_uint probe_pos = d->m_hash[hash];
3399       d->m_hash[hash] = (mz_uint16)lookahead_pos;
3400 
3401       if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <=
3402            dict_size) &&
3403           ((mz_uint32)(
3404                *(d->m_dict + (probe_pos & TDEFL_LZ_DICT_SIZE_MASK)) |
3405                (*(d->m_dict + ((probe_pos & TDEFL_LZ_DICT_SIZE_MASK) + 1))
3406                 << 8) |
3407                (*(d->m_dict + ((probe_pos & TDEFL_LZ_DICT_SIZE_MASK) + 2))
3408                 << 16)) == first_trigram)) {
3409         const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
3410         const mz_uint16 *q =
3411             (const mz_uint16 *)(d->m_dict +
3412                                 (probe_pos & TDEFL_LZ_DICT_SIZE_MASK));
3413         mz_uint32 probe_len = 32;
3414         do {
3415         } while ((*(++p) == *(++q)) && (*(++p) == *(++q)) &&
3416                  (*(++p) == *(++q)) && (*(++p) == *(++q)) && (--probe_len > 0));
3417         cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) +
3418                         (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
3419         if (!probe_len)
3420           cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
3421 
3422         if ((cur_match_len < TDEFL_MIN_MATCH_LEN) ||
3423             ((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3424              (cur_match_dist >= 8U * 1024U))) {
3425           cur_match_len = 1;
3426           *pLZ_code_buf++ = (mz_uint8)first_trigram;
3427           *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3428           d->m_huff_count[0][(mz_uint8)first_trigram]++;
3429         } else {
3430           mz_uint32 s0, s1;
3431           cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
3432 
3433           MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) &&
3434                     (cur_match_dist >= 1) &&
3435                     (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
3436 
3437           cur_match_dist--;
3438 
3439           pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
3440           *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
3441           pLZ_code_buf += 3;
3442           *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
3443 
3444           s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
3445           s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
3446           d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
3447 
3448           d->m_huff_count[0][s_tdefl_len_sym[cur_match_len -
3449                                              TDEFL_MIN_MATCH_LEN]]++;
3450         }
3451       } else {
3452         *pLZ_code_buf++ = (mz_uint8)first_trigram;
3453         *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3454         d->m_huff_count[0][(mz_uint8)first_trigram]++;
3455       }
3456 
3457       if (--num_flags_left == 0) {
3458         num_flags_left = 8;
3459         pLZ_flags = pLZ_code_buf++;
3460       }
3461 
3462       total_lz_bytes += cur_match_len;
3463       lookahead_pos += cur_match_len;
3464       dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
3465       cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
3466       MZ_ASSERT(lookahead_size >= cur_match_len);
3467       lookahead_size -= cur_match_len;
3468 
3469       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3470         int n;
3471         d->m_lookahead_pos = lookahead_pos;
3472         d->m_lookahead_size = lookahead_size;
3473         d->m_dict_size = dict_size;
3474         d->m_total_lz_bytes = total_lz_bytes;
3475         d->m_pLZ_code_buf = pLZ_code_buf;
3476         d->m_pLZ_flags = pLZ_flags;
3477         d->m_num_flags_left = num_flags_left;
3478         if ((n = tdefl_flush_block(d, 0)) != 0)
3479           return (n < 0) ? MZ_FALSE : MZ_TRUE;
3480         total_lz_bytes = d->m_total_lz_bytes;
3481         pLZ_code_buf = d->m_pLZ_code_buf;
3482         pLZ_flags = d->m_pLZ_flags;
3483         num_flags_left = d->m_num_flags_left;
3484       }
3485     }
3486 
3487     while (lookahead_size) {
3488       mz_uint8 lit = d->m_dict[cur_pos];
3489 
3490       total_lz_bytes++;
3491       *pLZ_code_buf++ = lit;
3492       *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3493       if (--num_flags_left == 0) {
3494         num_flags_left = 8;
3495         pLZ_flags = pLZ_code_buf++;
3496       }
3497 
3498       d->m_huff_count[0][lit]++;
3499 
3500       lookahead_pos++;
3501       dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
3502       cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3503       lookahead_size--;
3504 
3505       if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3506         int n;
3507         d->m_lookahead_pos = lookahead_pos;
3508         d->m_lookahead_size = lookahead_size;
3509         d->m_dict_size = dict_size;
3510         d->m_total_lz_bytes = total_lz_bytes;
3511         d->m_pLZ_code_buf = pLZ_code_buf;
3512         d->m_pLZ_flags = pLZ_flags;
3513         d->m_num_flags_left = num_flags_left;
3514         if ((n = tdefl_flush_block(d, 0)) != 0)
3515           return (n < 0) ? MZ_FALSE : MZ_TRUE;
3516         total_lz_bytes = d->m_total_lz_bytes;
3517         pLZ_code_buf = d->m_pLZ_code_buf;
3518         pLZ_flags = d->m_pLZ_flags;
3519         num_flags_left = d->m_num_flags_left;
3520       }
3521     }
3522   }
3523 
3524   d->m_lookahead_pos = lookahead_pos;
3525   d->m_lookahead_size = lookahead_size;
3526   d->m_dict_size = dict_size;
3527   d->m_total_lz_bytes = total_lz_bytes;
3528   d->m_pLZ_code_buf = pLZ_code_buf;
3529   d->m_pLZ_flags = pLZ_flags;
3530   d->m_num_flags_left = num_flags_left;
3531   return MZ_TRUE;
3532 }
3533 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3534 
tdefl_record_literal(tdefl_compressor * d,mz_uint8 lit)3535 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d,
3536                                                 mz_uint8 lit) {
3537   d->m_total_lz_bytes++;
3538   *d->m_pLZ_code_buf++ = lit;
3539   *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
3540   if (--d->m_num_flags_left == 0) {
3541     d->m_num_flags_left = 8;
3542     d->m_pLZ_flags = d->m_pLZ_code_buf++;
3543   }
3544   d->m_huff_count[0][lit]++;
3545 }
3546 
3547 static MZ_FORCEINLINE void
tdefl_record_match(tdefl_compressor * d,mz_uint match_len,mz_uint match_dist)3548 tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) {
3549   mz_uint32 s0, s1;
3550 
3551   MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) &&
3552             (match_dist <= TDEFL_LZ_DICT_SIZE));
3553 
3554   d->m_total_lz_bytes += match_len;
3555 
3556   d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
3557 
3558   match_dist -= 1;
3559   d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
3560   d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
3561   d->m_pLZ_code_buf += 3;
3562 
3563   *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
3564   if (--d->m_num_flags_left == 0) {
3565     d->m_num_flags_left = 8;
3566     d->m_pLZ_flags = d->m_pLZ_code_buf++;
3567   }
3568 
3569   s0 = s_tdefl_small_dist_sym[match_dist & 511];
3570   s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
3571   d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
3572 
3573   if (match_len >= TDEFL_MIN_MATCH_LEN)
3574     d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
3575 }
3576 
tdefl_compress_normal(tdefl_compressor * d)3577 static mz_bool tdefl_compress_normal(tdefl_compressor *d) {
3578   const mz_uint8 *pSrc = d->m_pSrc;
3579   size_t src_buf_left = d->m_src_buf_left;
3580   tdefl_flush flush = d->m_flush;
3581 
3582   while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) {
3583     mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
3584     // Update dictionary and hash chains. Keeps the lookahead size equal to
3585     // TDEFL_MAX_MATCH_LEN.
3586     if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) {
3587       mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3588                         TDEFL_LZ_DICT_SIZE_MASK,
3589               ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
3590       mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3591                       << TDEFL_LZ_HASH_SHIFT) ^
3592                      d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
3593       mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3594           src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
3595       const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
3596       src_buf_left -= num_bytes_to_process;
3597       d->m_lookahead_size += num_bytes_to_process;
3598       while (pSrc != pSrc_end) {
3599         mz_uint8 c = *pSrc++;
3600         d->m_dict[dst_pos] = c;
3601         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3602           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3603         hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
3604         d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3605         d->m_hash[hash] = (mz_uint16)(ins_pos);
3606         dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3607         ins_pos++;
3608       }
3609     } else {
3610       while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) {
3611         mz_uint8 c = *pSrc++;
3612         mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3613                           TDEFL_LZ_DICT_SIZE_MASK;
3614         src_buf_left--;
3615         d->m_dict[dst_pos] = c;
3616         if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3617           d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3618         if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) {
3619           mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
3620           mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3621                            << (TDEFL_LZ_HASH_SHIFT * 2)) ^
3622                           (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]
3623                            << TDEFL_LZ_HASH_SHIFT) ^
3624                           c) &
3625                          (TDEFL_LZ_HASH_SIZE - 1);
3626           d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3627           d->m_hash[hash] = (mz_uint16)(ins_pos);
3628         }
3629       }
3630     }
3631     d->m_dict_size =
3632         MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
3633     if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
3634       break;
3635 
3636     // Simple lazy/greedy parsing state machine.
3637     len_to_move = 1;
3638     cur_match_dist = 0;
3639     cur_match_len =
3640         d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
3641     cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3642     if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) {
3643       if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) {
3644         mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
3645         cur_match_len = 0;
3646         while (cur_match_len < d->m_lookahead_size) {
3647           if (d->m_dict[cur_pos + cur_match_len] != c)
3648             break;
3649           cur_match_len++;
3650         }
3651         if (cur_match_len < TDEFL_MIN_MATCH_LEN)
3652           cur_match_len = 0;
3653         else
3654           cur_match_dist = 1;
3655       }
3656     } else {
3657       tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size,
3658                        d->m_lookahead_size, &cur_match_dist, &cur_match_len);
3659     }
3660     if (((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3661          (cur_match_dist >= 8U * 1024U)) ||
3662         (cur_pos == cur_match_dist) ||
3663         ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) {
3664       cur_match_dist = cur_match_len = 0;
3665     }
3666     if (d->m_saved_match_len) {
3667       if (cur_match_len > d->m_saved_match_len) {
3668         tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
3669         if (cur_match_len >= 128) {
3670           tdefl_record_match(d, cur_match_len, cur_match_dist);
3671           d->m_saved_match_len = 0;
3672           len_to_move = cur_match_len;
3673         } else {
3674           d->m_saved_lit = d->m_dict[cur_pos];
3675           d->m_saved_match_dist = cur_match_dist;
3676           d->m_saved_match_len = cur_match_len;
3677         }
3678       } else {
3679         tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
3680         len_to_move = d->m_saved_match_len - 1;
3681         d->m_saved_match_len = 0;
3682       }
3683     } else if (!cur_match_dist)
3684       tdefl_record_literal(d,
3685                            d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
3686     else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) ||
3687              (cur_match_len >= 128)) {
3688       tdefl_record_match(d, cur_match_len, cur_match_dist);
3689       len_to_move = cur_match_len;
3690     } else {
3691       d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
3692       d->m_saved_match_dist = cur_match_dist;
3693       d->m_saved_match_len = cur_match_len;
3694     }
3695     // Move the lookahead forward by len_to_move bytes.
3696     d->m_lookahead_pos += len_to_move;
3697     MZ_ASSERT(d->m_lookahead_size >= len_to_move);
3698     d->m_lookahead_size -= len_to_move;
3699     d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
3700     // Check if it's time to flush the current LZ codes to the internal output
3701     // buffer.
3702     if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
3703         ((d->m_total_lz_bytes > 31 * 1024) &&
3704          (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >=
3705            d->m_total_lz_bytes) ||
3706           (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) {
3707       int n;
3708       d->m_pSrc = pSrc;
3709       d->m_src_buf_left = src_buf_left;
3710       if ((n = tdefl_flush_block(d, 0)) != 0)
3711         return (n < 0) ? MZ_FALSE : MZ_TRUE;
3712     }
3713   }
3714 
3715   d->m_pSrc = pSrc;
3716   d->m_src_buf_left = src_buf_left;
3717   return MZ_TRUE;
3718 }
3719 
tdefl_flush_output_buffer(tdefl_compressor * d)3720 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) {
3721   if (d->m_pIn_buf_size) {
3722     *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3723   }
3724 
3725   if (d->m_pOut_buf_size) {
3726     size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs,
3727                       d->m_output_flush_remaining);
3728     memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs,
3729            d->m_output_buf + d->m_output_flush_ofs, n);
3730     d->m_output_flush_ofs += (mz_uint)n;
3731     d->m_output_flush_remaining -= (mz_uint)n;
3732     d->m_out_buf_ofs += n;
3733 
3734     *d->m_pOut_buf_size = d->m_out_buf_ofs;
3735   }
3736 
3737   return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE
3738                                                          : TDEFL_STATUS_OKAY;
3739 }
3740 
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)3741 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
3742                             size_t *pIn_buf_size, void *pOut_buf,
3743                             size_t *pOut_buf_size, tdefl_flush flush) {
3744   if (!d) {
3745     if (pIn_buf_size)
3746       *pIn_buf_size = 0;
3747     if (pOut_buf_size)
3748       *pOut_buf_size = 0;
3749     return TDEFL_STATUS_BAD_PARAM;
3750   }
3751 
3752   d->m_pIn_buf = pIn_buf;
3753   d->m_pIn_buf_size = pIn_buf_size;
3754   d->m_pOut_buf = pOut_buf;
3755   d->m_pOut_buf_size = pOut_buf_size;
3756   d->m_pSrc = (const mz_uint8 *)(pIn_buf);
3757   d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
3758   d->m_out_buf_ofs = 0;
3759   d->m_flush = flush;
3760 
3761   if (((d->m_pPut_buf_func != NULL) ==
3762        ((pOut_buf != NULL) || (pOut_buf_size != NULL))) ||
3763       (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
3764       (d->m_wants_to_finish && (flush != TDEFL_FINISH)) ||
3765       (pIn_buf_size && *pIn_buf_size && !pIn_buf) ||
3766       (pOut_buf_size && *pOut_buf_size && !pOut_buf)) {
3767     if (pIn_buf_size)
3768       *pIn_buf_size = 0;
3769     if (pOut_buf_size)
3770       *pOut_buf_size = 0;
3771     return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
3772   }
3773   d->m_wants_to_finish |= (flush == TDEFL_FINISH);
3774 
3775   if ((d->m_output_flush_remaining) || (d->m_finished))
3776     return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3777 
3778 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3779   if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
3780       ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
3781       ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS |
3782                       TDEFL_RLE_MATCHES)) == 0)) {
3783     if (!tdefl_compress_fast(d))
3784       return d->m_prev_return_status;
3785   } else
3786 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3787   {
3788     if (!tdefl_compress_normal(d))
3789       return d->m_prev_return_status;
3790   }
3791 
3792   if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) &&
3793       (pIn_buf))
3794     d->m_adler32 =
3795         (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf,
3796                               d->m_pSrc - (const mz_uint8 *)pIn_buf);
3797 
3798   if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) &&
3799       (!d->m_output_flush_remaining)) {
3800     if (tdefl_flush_block(d, flush) < 0)
3801       return d->m_prev_return_status;
3802     d->m_finished = (flush == TDEFL_FINISH);
3803     if (flush == TDEFL_FULL_FLUSH) {
3804       MZ_CLEAR_OBJ(d->m_hash);
3805       MZ_CLEAR_OBJ(d->m_next);
3806       d->m_dict_size = 0;
3807     }
3808   }
3809 
3810   return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3811 }
3812 
tdefl_compress_buffer(tdefl_compressor * d,const void * pIn_buf,size_t in_buf_size,tdefl_flush flush)3813 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
3814                                    size_t in_buf_size, tdefl_flush flush) {
3815   MZ_ASSERT(d->m_pPut_buf_func);
3816   return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
3817 }
3818 
tdefl_init(tdefl_compressor * d,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)3819 tdefl_status tdefl_init(tdefl_compressor *d,
3820                         tdefl_put_buf_func_ptr pPut_buf_func,
3821                         void *pPut_buf_user, int flags) {
3822   d->m_pPut_buf_func = pPut_buf_func;
3823   d->m_pPut_buf_user = pPut_buf_user;
3824   d->m_flags = (mz_uint)(flags);
3825   d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
3826   d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
3827   d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
3828   if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
3829     MZ_CLEAR_OBJ(d->m_hash);
3830   d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size =
3831       d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
3832   d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished =
3833       d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
3834   d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3835   d->m_pLZ_flags = d->m_lz_code_buf;
3836   d->m_num_flags_left = 8;
3837   d->m_pOutput_buf = d->m_output_buf;
3838   d->m_pOutput_buf_end = d->m_output_buf;
3839   d->m_prev_return_status = TDEFL_STATUS_OKAY;
3840   d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
3841   d->m_adler32 = 1;
3842   d->m_pIn_buf = NULL;
3843   d->m_pOut_buf = NULL;
3844   d->m_pIn_buf_size = NULL;
3845   d->m_pOut_buf_size = NULL;
3846   d->m_flush = TDEFL_NO_FLUSH;
3847   d->m_pSrc = NULL;
3848   d->m_src_buf_left = 0;
3849   d->m_out_buf_ofs = 0;
3850   memset(&d->m_huff_count[0][0], 0,
3851          sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3852   memset(&d->m_huff_count[1][0], 0,
3853          sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3854   return TDEFL_STATUS_OKAY;
3855 }
3856 
tdefl_get_prev_return_status(tdefl_compressor * d)3857 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
3858   return d->m_prev_return_status;
3859 }
3860 
tdefl_get_adler32(tdefl_compressor * d)3861 mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
3862 
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)3863 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
3864                                      tdefl_put_buf_func_ptr pPut_buf_func,
3865                                      void *pPut_buf_user, int flags) {
3866   tdefl_compressor *pComp;
3867   mz_bool succeeded;
3868   if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
3869     return MZ_FALSE;
3870   pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3871   if (!pComp)
3872     return MZ_FALSE;
3873   succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) ==
3874                TDEFL_STATUS_OKAY);
3875   succeeded =
3876       succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) ==
3877                     TDEFL_STATUS_DONE);
3878   MZ_FREE(pComp);
3879   return succeeded;
3880 }
3881 
3882 typedef struct {
3883   size_t m_size, m_capacity;
3884   mz_uint8 *m_pBuf;
3885   mz_bool m_expandable;
3886 } tdefl_output_buffer;
3887 
tdefl_output_buffer_putter(const void * pBuf,int len,void * pUser)3888 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len,
3889                                           void *pUser) {
3890   tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
3891   size_t new_size = p->m_size + len;
3892   if (new_size > p->m_capacity) {
3893     size_t new_capacity = p->m_capacity;
3894     mz_uint8 *pNew_buf;
3895     if (!p->m_expandable)
3896       return MZ_FALSE;
3897     do {
3898       new_capacity = MZ_MAX(128U, new_capacity << 1U);
3899     } while (new_size > new_capacity);
3900     pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
3901     if (!pNew_buf)
3902       return MZ_FALSE;
3903     p->m_pBuf = pNew_buf;
3904     p->m_capacity = new_capacity;
3905   }
3906   memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
3907   p->m_size = new_size;
3908   return MZ_TRUE;
3909 }
3910 
tdefl_compress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)3911 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
3912                                  size_t *pOut_len, int flags) {
3913   tdefl_output_buffer out_buf;
3914   MZ_CLEAR_OBJ(out_buf);
3915   if (!pOut_len)
3916     return MZ_FALSE;
3917   else
3918     *pOut_len = 0;
3919   out_buf.m_expandable = MZ_TRUE;
3920   if (!tdefl_compress_mem_to_output(
3921           pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3922     return NULL;
3923   *pOut_len = out_buf.m_size;
3924   return out_buf.m_pBuf;
3925 }
3926 
tdefl_compress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)3927 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
3928                                  const void *pSrc_buf, size_t src_buf_len,
3929                                  int flags) {
3930   tdefl_output_buffer out_buf;
3931   MZ_CLEAR_OBJ(out_buf);
3932   if (!pOut_buf)
3933     return 0;
3934   out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
3935   out_buf.m_capacity = out_buf_len;
3936   if (!tdefl_compress_mem_to_output(
3937           pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3938     return 0;
3939   return out_buf.m_size;
3940 }
3941 
3942 #ifndef MINIZ_NO_ZLIB_APIS
3943 static const mz_uint s_tdefl_num_probes[11] = {0,   1,   6,   32,  16,  32,
3944                                                128, 256, 512, 768, 1500};
3945 
3946 // level may actually range from [0,10] (10 is a "hidden" max level, where we
3947 // want a bit more compression and it's fine if throughput to fall off a cliff
3948 // on some files).
tdefl_create_comp_flags_from_zip_params(int level,int window_bits,int strategy)3949 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
3950                                                 int strategy) {
3951   mz_uint comp_flags =
3952       s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] |
3953       ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
3954   if (window_bits > 0)
3955     comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
3956 
3957   if (!level)
3958     comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
3959   else if (strategy == MZ_FILTERED)
3960     comp_flags |= TDEFL_FILTER_MATCHES;
3961   else if (strategy == MZ_HUFFMAN_ONLY)
3962     comp_flags &= ~TDEFL_MAX_PROBES_MASK;
3963   else if (strategy == MZ_FIXED)
3964     comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
3965   else if (strategy == MZ_RLE)
3966     comp_flags |= TDEFL_RLE_MATCHES;
3967 
3968   return comp_flags;
3969 }
3970 #endif // MINIZ_NO_ZLIB_APIS
3971 
3972 #ifdef _MSC_VER
3973 #pragma warning(push)
3974 #pragma warning(disable : 4204) // nonstandard extension used : non-constant
3975                                 // aggregate initializer (also supported by GNU
3976                                 // C and C99, so no big deal)
3977 #endif
3978 
3979 // Simple PNG writer function by Alex Evans, 2011. Released into the public
3980 // domain: https://gist.github.com/908299, more context at
3981 // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
3982 // This is actually a modification of Alex's original code so PNG files
3983 // generated by this function pass pngcheck.
tdefl_write_image_to_png_file_in_memory_ex(const void * pImage,int w,int h,int num_chans,size_t * pLen_out,mz_uint level,mz_bool flip)3984 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
3985                                                  int h, int num_chans,
3986                                                  size_t *pLen_out,
3987                                                  mz_uint level, mz_bool flip) {
3988   // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was
3989   // defined.
3990   static const mz_uint s_tdefl_png_num_probes[11] = {
3991       0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500};
3992   tdefl_compressor *pComp =
3993       (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3994   tdefl_output_buffer out_buf;
3995   int i, bpl = w * num_chans, y, z;
3996   mz_uint32 c;
3997   *pLen_out = 0;
3998   if (!pComp)
3999     return NULL;
4000   MZ_CLEAR_OBJ(out_buf);
4001   out_buf.m_expandable = MZ_TRUE;
4002   out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
4003   if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) {
4004     MZ_FREE(pComp);
4005     return NULL;
4006   }
4007   // write dummy header
4008   for (z = 41; z; --z)
4009     tdefl_output_buffer_putter(&z, 1, &out_buf);
4010   // compress image data
4011   tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf,
4012              s_tdefl_png_num_probes[MZ_MIN(10, level)] |
4013                  TDEFL_WRITE_ZLIB_HEADER);
4014   for (y = 0; y < h; ++y) {
4015     tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
4016     tdefl_compress_buffer(pComp,
4017                           (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl,
4018                           bpl, TDEFL_NO_FLUSH);
4019   }
4020   if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) !=
4021       TDEFL_STATUS_DONE) {
4022     MZ_FREE(pComp);
4023     MZ_FREE(out_buf.m_pBuf);
4024     return NULL;
4025   }
4026   // write real header
4027   *pLen_out = out_buf.m_size - 41;
4028   {
4029     static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
4030     mz_uint8 pnghdr[41] = {0x89,
4031                            0x50,
4032                            0x4e,
4033                            0x47,
4034                            0x0d,
4035                            0x0a,
4036                            0x1a,
4037                            0x0a,
4038                            0x00,
4039                            0x00,
4040                            0x00,
4041                            0x0d,
4042                            0x49,
4043                            0x48,
4044                            0x44,
4045                            0x52,
4046                            0,
4047                            0,
4048                            (mz_uint8)(w >> 8),
4049                            (mz_uint8)w,
4050                            0,
4051                            0,
4052                            (mz_uint8)(h >> 8),
4053                            (mz_uint8)h,
4054                            8,
4055                            chans[num_chans],
4056                            0,
4057                            0,
4058                            0,
4059                            0,
4060                            0,
4061                            0,
4062                            0,
4063                            (mz_uint8)(*pLen_out >> 24),
4064                            (mz_uint8)(*pLen_out >> 16),
4065                            (mz_uint8)(*pLen_out >> 8),
4066                            (mz_uint8)*pLen_out,
4067                            0x49,
4068                            0x44,
4069                            0x41,
4070                            0x54};
4071     c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
4072     for (i = 0; i < 4; ++i, c <<= 8)
4073       ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
4074     memcpy(out_buf.m_pBuf, pnghdr, 41);
4075   }
4076   // write footer (IDAT CRC-32, followed by IEND chunk)
4077   if (!tdefl_output_buffer_putter(
4078           "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) {
4079     *pLen_out = 0;
4080     MZ_FREE(pComp);
4081     MZ_FREE(out_buf.m_pBuf);
4082     return NULL;
4083   }
4084   c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4,
4085                           *pLen_out + 4);
4086   for (i = 0; i < 4; ++i, c <<= 8)
4087     (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
4088   // compute final size of file, grab compressed data buffer and return
4089   *pLen_out += 57;
4090   MZ_FREE(pComp);
4091   return out_buf.m_pBuf;
4092 }
tdefl_write_image_to_png_file_in_memory(const void * pImage,int w,int h,int num_chans,size_t * pLen_out)4093 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
4094                                               int num_chans, size_t *pLen_out) {
4095   // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we
4096   // can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's
4097   // where #defined out)
4098   return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans,
4099                                                     pLen_out, 6, MZ_FALSE);
4100 }
4101 
4102 #ifdef _MSC_VER
4103 #pragma warning(pop)
4104 #endif
4105 
4106 // ------------------- .ZIP archive reading
4107 
4108 #ifndef MINIZ_NO_ARCHIVE_APIS
4109 
4110 #ifdef MINIZ_NO_STDIO
4111 #define MZ_FILE void *
4112 #else
4113 #include <stdio.h>
4114 #include <sys/stat.h>
4115 
4116 #if defined(_MSC_VER) || defined(__MINGW32__)
4117 
4118 #include <windows.h>
4119 
str2wstr(const char * str)4120 static wchar_t *str2wstr(const char *str) {
4121   int len = strlen(str) + 1;
4122   wchar_t *wstr = (wchar_t*)malloc(len * sizeof(wchar_t));
4123   MultiByteToWideChar(CP_UTF8, 0, str, len * sizeof(char), wstr, len);
4124   return wstr;
4125 }
4126 
mz_fopen(const char * pFilename,const char * pMode)4127 static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4128   wchar_t *wFilename = str2wstr(pFilename);
4129   wchar_t *wMode = str2wstr(pMode);
4130   FILE *pFile = _wfopen(wFilename, wMode);
4131 
4132   free(wFilename);
4133   free(wMode);
4134 
4135   return pFile;
4136 }
4137 
mz_freopen(const char * pPath,const char * pMode,FILE * pStream)4138 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4139   wchar_t *wPath = str2wstr(pPath);
4140   wchar_t *wMode = str2wstr(pMode);
4141   FILE *pFile = _wfreopen(wPath, wMode, pStream);
4142 
4143   free(wPath);
4144   free(wMode);
4145 
4146   return pFile;
4147 }
4148 
4149 #ifndef MINIZ_NO_TIME
4150 #include <sys/utime.h>
4151 #endif
4152 #define MZ_FILE FILE
4153 #define MZ_FOPEN mz_fopen
4154 #define MZ_FCLOSE fclose
4155 #define MZ_FREAD fread
4156 #define MZ_FWRITE fwrite
4157 // ZIG_ANDROID_MOD: Zig's mingw64 doesn't have _ftelli64/_fseeki64
4158 #if defined(__MINGW64__)
4159 #define MZ_FTELL64 ftello
4160 #define MZ_FSEEK64 fseeko
4161 #else
4162 #define MZ_FTELL64 _ftelli64
4163 #define MZ_FSEEK64 _fseeki64
4164 #endif
4165 #define MZ_FILE_STAT_STRUCT _stat
4166 #define MZ_FILE_STAT _stat
4167 #define MZ_FFLUSH fflush
4168 #define MZ_FREOPEN mz_freopen
4169 #define MZ_DELETE_FILE remove
4170 #elif defined(__MINGW32__)
4171 #ifndef MINIZ_NO_TIME
4172 #include <sys/utime.h>
4173 #endif
4174 #define MZ_FILE FILE
4175 #define MZ_FOPEN(f, m) mz_fopen
4176 #define MZ_FCLOSE fclose
4177 #define MZ_FREAD fread
4178 #define MZ_FWRITE fwrite
4179 #define MZ_FTELL64 ftell
4180 #define MZ_FSEEK64 fseek
4181 #define MZ_FILE_STAT_STRUCT _stat
4182 #define MZ_FILE_STAT _stat
4183 #define MZ_FFLUSH fflush
4184 #define MZ_FREOPEN(f, m, s) mz_freopen
4185 #define MZ_DELETE_FILE remove
4186 #elif defined(__TINYC__)
4187 #ifndef MINIZ_NO_TIME
4188 #include <sys/utime.h>
4189 #endif
4190 #define MZ_FILE FILE
4191 #define MZ_FOPEN(f, m) fopen(f, m)
4192 #define MZ_FCLOSE fclose
4193 #define MZ_FREAD fread
4194 #define MZ_FWRITE fwrite
4195 #define MZ_FTELL64 ftell
4196 #define MZ_FSEEK64 fseek
4197 #define MZ_FILE_STAT_STRUCT stat
4198 #define MZ_FILE_STAT stat
4199 #define MZ_FFLUSH fflush
4200 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4201 #define MZ_DELETE_FILE remove
4202 #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
4203 #ifndef MINIZ_NO_TIME
4204 #include <utime.h>
4205 #endif
4206 #define MZ_FILE FILE
4207 #define MZ_FOPEN(f, m) fopen64(f, m)
4208 #define MZ_FCLOSE fclose
4209 #define MZ_FREAD fread
4210 #define MZ_FWRITE fwrite
4211 #define MZ_FTELL64 ftello64
4212 #define MZ_FSEEK64 fseeko64
4213 #define MZ_FILE_STAT_STRUCT stat64
4214 #define MZ_FILE_STAT stat64
4215 #define MZ_FFLUSH fflush
4216 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4217 #define MZ_DELETE_FILE remove
4218 #else
4219 #ifndef MINIZ_NO_TIME
4220 #include <utime.h>
4221 #endif
4222 #define MZ_FILE FILE
4223 #define MZ_FOPEN(f, m) fopen(f, m)
4224 #define MZ_FCLOSE fclose
4225 #define MZ_FREAD fread
4226 #define MZ_FWRITE fwrite
4227 #if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L
4228 #define MZ_FTELL64 ftello
4229 #define MZ_FSEEK64 fseeko
4230 #else
4231 #define MZ_FTELL64 ftell
4232 #define MZ_FSEEK64 fseek
4233 #endif
4234 #define MZ_FILE_STAT_STRUCT stat
4235 #define MZ_FILE_STAT stat
4236 #define MZ_FFLUSH fflush
4237 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4238 #define MZ_DELETE_FILE remove
4239 #endif // #ifdef _MSC_VER
4240 #endif // #ifdef MINIZ_NO_STDIO
4241 
4242 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4243 
4244 // Various ZIP archive enums. To completely avoid cross platform compiler
4245 // alignment and platform endian issues, miniz.c doesn't use structs for any of
4246 // this stuff.
4247 enum {
4248   // ZIP archive identifiers and record sizes
4249   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
4250   MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
4251   MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
4252   MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
4253   MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
4254   MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
4255 
4256   /* ZIP64 archive identifier and record sizes */
4257   MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
4258   MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
4259   MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
4260   MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
4261   MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
4262   MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
4263   MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
4264   MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
4265 
4266   // Central directory header record offsets
4267   MZ_ZIP_CDH_SIG_OFS = 0,
4268   MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
4269   MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
4270   MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
4271   MZ_ZIP_CDH_METHOD_OFS = 10,
4272   MZ_ZIP_CDH_FILE_TIME_OFS = 12,
4273   MZ_ZIP_CDH_FILE_DATE_OFS = 14,
4274   MZ_ZIP_CDH_CRC32_OFS = 16,
4275   MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
4276   MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
4277   MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
4278   MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
4279   MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
4280   MZ_ZIP_CDH_DISK_START_OFS = 34,
4281   MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
4282   MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
4283   MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
4284   // Local directory header offsets
4285   MZ_ZIP_LDH_SIG_OFS = 0,
4286   MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
4287   MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
4288   MZ_ZIP_LDH_METHOD_OFS = 8,
4289   MZ_ZIP_LDH_FILE_TIME_OFS = 10,
4290   MZ_ZIP_LDH_FILE_DATE_OFS = 12,
4291   MZ_ZIP_LDH_CRC32_OFS = 14,
4292   MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
4293   MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
4294   MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
4295   MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
4296   // End of central directory offsets
4297   MZ_ZIP_ECDH_SIG_OFS = 0,
4298   MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
4299   MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
4300   MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
4301   MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
4302   MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
4303   MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
4304   MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
4305 
4306   /* ZIP64 End of central directory locator offsets */
4307   MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
4308   MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
4309   MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
4310   MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
4311 
4312   /* ZIP64 End of central directory header offsets */
4313   MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
4314   MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
4315   MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
4316   MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
4317   MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
4318   MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
4319   MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
4320   MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
4321   MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
4322   MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
4323   MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
4324   MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
4325   MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
4326   MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
4327   MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
4328   MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
4329   MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
4330 };
4331 
4332 typedef struct {
4333   void *m_p;
4334   size_t m_size, m_capacity;
4335   mz_uint m_element_size;
4336 } mz_zip_array;
4337 
4338 struct mz_zip_internal_state_tag {
4339   mz_zip_array m_central_dir;
4340   mz_zip_array m_central_dir_offsets;
4341   mz_zip_array m_sorted_central_dir_offsets;
4342 
4343   /* The flags passed in when the archive is initially opened. */
4344   uint32_t m_init_flags;
4345 
4346   /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
4347    */
4348   mz_bool m_zip64;
4349 
4350   /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
4351    * will also be slammed to true too, even if we didn't find a zip64 end of
4352    * central dir header, etc.) */
4353   mz_bool m_zip64_has_extended_info_fields;
4354 
4355   /* These fields are used by the file, FILE, memory, and memory/heap read/write
4356    * helpers. */
4357   MZ_FILE *m_pFile;
4358   mz_uint64 m_file_archive_start_ofs;
4359 
4360   void *m_pMem;
4361   size_t m_mem_size;
4362   size_t m_mem_capacity;
4363 };
4364 
4365 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size)                 \
4366   (array_ptr)->m_element_size = element_size
4367 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index)                   \
4368   ((element_type *)((array_ptr)->m_p))[index]
4369 
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)4370 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
4371                                               mz_zip_array *pArray) {
4372   pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
4373   memset(pArray, 0, sizeof(mz_zip_array));
4374 }
4375 
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)4376 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
4377                                             mz_zip_array *pArray,
4378                                             size_t min_new_capacity,
4379                                             mz_uint growing) {
4380   void *pNew_p;
4381   size_t new_capacity = min_new_capacity;
4382   MZ_ASSERT(pArray->m_element_size);
4383   if (pArray->m_capacity >= min_new_capacity)
4384     return MZ_TRUE;
4385   if (growing) {
4386     new_capacity = MZ_MAX(1, pArray->m_capacity);
4387     while (new_capacity < min_new_capacity)
4388       new_capacity *= 2;
4389   }
4390   if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
4391                                          pArray->m_element_size, new_capacity)))
4392     return MZ_FALSE;
4393   pArray->m_p = pNew_p;
4394   pArray->m_capacity = new_capacity;
4395   return MZ_TRUE;
4396 }
4397 
mz_zip_array_reserve(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_capacity,mz_uint growing)4398 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
4399                                                    mz_zip_array *pArray,
4400                                                    size_t new_capacity,
4401                                                    mz_uint growing) {
4402   if (new_capacity > pArray->m_capacity) {
4403     if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
4404       return MZ_FALSE;
4405   }
4406   return MZ_TRUE;
4407 }
4408 
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)4409 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
4410                                                   mz_zip_array *pArray,
4411                                                   size_t new_size,
4412                                                   mz_uint growing) {
4413   if (new_size > pArray->m_capacity) {
4414     if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
4415       return MZ_FALSE;
4416   }
4417   pArray->m_size = new_size;
4418   return MZ_TRUE;
4419 }
4420 
mz_zip_array_ensure_room(mz_zip_archive * pZip,mz_zip_array * pArray,size_t n)4421 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
4422                                                        mz_zip_array *pArray,
4423                                                        size_t n) {
4424   return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
4425 }
4426 
mz_zip_array_push_back(mz_zip_archive * pZip,mz_zip_array * pArray,const void * pElements,size_t n)4427 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
4428                                                      mz_zip_array *pArray,
4429                                                      const void *pElements,
4430                                                      size_t n) {
4431   if (0 == n)
4432     return MZ_TRUE;
4433   if (!pElements)
4434     return MZ_FALSE;
4435 
4436   size_t orig_size = pArray->m_size;
4437   if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
4438     return MZ_FALSE;
4439   memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
4440          pElements, n * pArray->m_element_size);
4441   return MZ_TRUE;
4442 }
4443 
4444 #ifndef MINIZ_NO_TIME
mz_zip_dos_to_time_t(int dos_time,int dos_date)4445 static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
4446   struct tm tm;
4447   memset(&tm, 0, sizeof(tm));
4448   tm.tm_isdst = -1;
4449   tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
4450   tm.tm_mon = ((dos_date >> 5) & 15) - 1;
4451   tm.tm_mday = dos_date & 31;
4452   tm.tm_hour = (dos_time >> 11) & 31;
4453   tm.tm_min = (dos_time >> 5) & 63;
4454   tm.tm_sec = (dos_time << 1) & 62;
4455   return mktime(&tm);
4456 }
4457 
4458 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_time_t_to_dos_time(time_t time,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)4459 static void mz_zip_time_t_to_dos_time(time_t time, mz_uint16 *pDOS_time,
4460                                       mz_uint16 *pDOS_date) {
4461 #ifdef _MSC_VER
4462   struct tm tm_struct;
4463   struct tm *tm = &tm_struct;
4464   errno_t err = localtime_s(tm, &time);
4465   if (err) {
4466     *pDOS_date = 0;
4467     *pDOS_time = 0;
4468     return;
4469   }
4470 #else
4471   struct tm *tm = localtime(&time);
4472 #endif /* #ifdef _MSC_VER */
4473 
4474   *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
4475                            ((tm->tm_sec) >> 1));
4476   *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
4477                            ((tm->tm_mon + 1) << 5) + tm->tm_mday);
4478 }
4479 #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
4480 
4481 #ifndef MINIZ_NO_STDIO
4482 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_get_file_modified_time(const char * pFilename,time_t * pTime)4483 static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
4484                                              time_t *pTime) {
4485   struct MZ_FILE_STAT_STRUCT file_stat;
4486 
4487   /* On Linux with x86 glibc, this call will fail on large files (I think >=
4488    * 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
4489   if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
4490     return MZ_FALSE;
4491 
4492   *pTime = file_stat.st_mtime;
4493 
4494   return MZ_TRUE;
4495 }
4496 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
4497 
mz_zip_set_file_times(const char * pFilename,time_t access_time,time_t modified_time)4498 static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
4499                                      time_t modified_time) {
4500   struct utimbuf t;
4501 
4502   memset(&t, 0, sizeof(t));
4503   t.actime = access_time;
4504   t.modtime = modified_time;
4505 
4506   return !utime(pFilename, &t);
4507 }
4508 #endif /* #ifndef MINIZ_NO_STDIO */
4509 #endif /* #ifndef MINIZ_NO_TIME */
4510 
mz_zip_set_error(mz_zip_archive * pZip,mz_zip_error err_num)4511 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
4512                                                mz_zip_error err_num) {
4513   if (pZip)
4514     pZip->m_last_error = err_num;
4515   return MZ_FALSE;
4516 }
4517 
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint32 flags)4518 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
4519                                            mz_uint32 flags) {
4520   (void)flags;
4521   if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
4522     return MZ_FALSE;
4523 
4524   if (!pZip->m_pAlloc)
4525     pZip->m_pAlloc = def_alloc_func;
4526   if (!pZip->m_pFree)
4527     pZip->m_pFree = def_free_func;
4528   if (!pZip->m_pRealloc)
4529     pZip->m_pRealloc = def_realloc_func;
4530 
4531   pZip->m_zip_mode = MZ_ZIP_MODE_READING;
4532   pZip->m_archive_size = 0;
4533   pZip->m_central_directory_file_ofs = 0;
4534   pZip->m_total_files = 0;
4535 
4536   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
4537                    pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
4538     return MZ_FALSE;
4539   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
4540   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
4541                                 sizeof(mz_uint8));
4542   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
4543                                 sizeof(mz_uint32));
4544   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
4545                                 sizeof(mz_uint32));
4546   return MZ_TRUE;
4547 }
4548 
4549 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)4550 mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
4551                             const mz_zip_array *pCentral_dir_offsets,
4552                             mz_uint l_index, mz_uint r_index) {
4553   const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
4554                      pCentral_dir_array, mz_uint8,
4555                      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
4556                                           l_index)),
4557                  *pE;
4558   const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
4559       pCentral_dir_array, mz_uint8,
4560       MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
4561   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
4562           r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4563   mz_uint8 l = 0, r = 0;
4564   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4565   pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4566   pE = pL + MZ_MIN(l_len, r_len);
4567   while (pL < pE) {
4568     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4569       break;
4570     pL++;
4571     pR++;
4572   }
4573   return (pL == pE) ? (l_len < r_len) : (l < r);
4574 }
4575 
4576 #define MZ_SWAP_UINT32(a, b)                                                   \
4577   do {                                                                         \
4578     mz_uint32 t = a;                                                           \
4579     a = b;                                                                     \
4580     b = t;                                                                     \
4581   }                                                                            \
4582   MZ_MACRO_END
4583 
4584 // Heap sort of lowercased filenames, used to help accelerate plain central
4585 // directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
4586 // but it could allocate memory.)
4587 static void
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)4588 mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
4589   mz_zip_internal_state *pState = pZip->m_pState;
4590   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4591   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4592   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
4593       &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4594   const int size = pZip->m_total_files;
4595   int start = (size - 2) >> 1, end;
4596   while (start >= 0) {
4597     int child, root = start;
4598     for (;;) {
4599       if ((child = (root << 1) + 1) >= size)
4600         break;
4601       child +=
4602           (((child + 1) < size) &&
4603            (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4604                                         pIndices[child], pIndices[child + 1])));
4605       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4606                                        pIndices[root], pIndices[child]))
4607         break;
4608       MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4609       root = child;
4610     }
4611     start--;
4612   }
4613 
4614   end = size - 1;
4615   while (end > 0) {
4616     int child, root = 0;
4617     MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
4618     for (;;) {
4619       if ((child = (root << 1) + 1) >= end)
4620         break;
4621       child +=
4622           (((child + 1) < end) &&
4623            mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4624                                        pIndices[child], pIndices[child + 1]));
4625       if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4626                                        pIndices[root], pIndices[child]))
4627         break;
4628       MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4629       root = child;
4630     }
4631     end--;
4632   }
4633 }
4634 
mz_zip_reader_locate_header_sig(mz_zip_archive * pZip,mz_uint32 record_sig,mz_uint32 record_size,mz_int64 * pOfs)4635 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
4636                                                mz_uint32 record_sig,
4637                                                mz_uint32 record_size,
4638                                                mz_int64 *pOfs) {
4639   mz_int64 cur_file_ofs;
4640   mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4641   mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4642 
4643   /* Basic sanity checks - reject files which are too small */
4644   if (pZip->m_archive_size < record_size)
4645     return MZ_FALSE;
4646 
4647   /* Find the record by scanning the file from the end towards the beginning. */
4648   cur_file_ofs =
4649       MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
4650   for (;;) {
4651     int i,
4652         n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
4653 
4654     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
4655       return MZ_FALSE;
4656 
4657     for (i = n - 4; i >= 0; --i) {
4658       mz_uint s = MZ_READ_LE32(pBuf + i);
4659       if (s == record_sig) {
4660         if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
4661           break;
4662       }
4663     }
4664 
4665     if (i >= 0) {
4666       cur_file_ofs += i;
4667       break;
4668     }
4669 
4670     /* Give up if we've searched the entire file, or we've gone back "too far"
4671      * (~64kb) */
4672     if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
4673                             (MZ_UINT16_MAX + record_size)))
4674       return MZ_FALSE;
4675 
4676     cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
4677   }
4678 
4679   *pOfs = cur_file_ofs;
4680   return MZ_TRUE;
4681 }
4682 
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint flags)4683 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
4684                                               mz_uint flags) {
4685   mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
4686           cdir_disk_index = 0;
4687   mz_uint64 cdir_ofs = 0;
4688   mz_int64 cur_file_ofs = 0;
4689   const mz_uint8 *p;
4690 
4691   mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4692   mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4693   mz_bool sort_central_dir =
4694       ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
4695   mz_uint32 zip64_end_of_central_dir_locator_u32
4696       [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
4697        sizeof(mz_uint32)];
4698   mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
4699 
4700   mz_uint32 zip64_end_of_central_dir_header_u32
4701       [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
4702        sizeof(mz_uint32)];
4703   mz_uint8 *pZip64_end_of_central_dir =
4704       (mz_uint8 *)zip64_end_of_central_dir_header_u32;
4705 
4706   mz_uint64 zip64_end_of_central_dir_ofs = 0;
4707 
4708   /* Basic sanity checks - reject files which are too small, and check the first
4709    * 4 bytes of the file to make sure a local header is there. */
4710   if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4711     return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4712 
4713   if (!mz_zip_reader_locate_header_sig(
4714           pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
4715           MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
4716     return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
4717 
4718   /* Read and verify the end of central directory record. */
4719   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
4720                     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
4721       MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4722     return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4723 
4724   if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
4725       MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
4726     return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4727 
4728   if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
4729                        MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
4730     if (pZip->m_pRead(pZip->m_pIO_opaque,
4731                       cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
4732                       pZip64_locator,
4733                       MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
4734         MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
4735       if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
4736           MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
4737         zip64_end_of_central_dir_ofs = MZ_READ_LE64(
4738             pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
4739         if (zip64_end_of_central_dir_ofs >
4740             (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
4741           return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4742 
4743         if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
4744                           pZip64_end_of_central_dir,
4745                           MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
4746             MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
4747           if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
4748               MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
4749             pZip->m_pState->m_zip64 = MZ_TRUE;
4750           }
4751         }
4752       }
4753     }
4754   }
4755 
4756   pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4757   cdir_entries_on_this_disk =
4758       MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4759   num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
4760   cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
4761   cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
4762   cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
4763 
4764   if (pZip->m_pState->m_zip64) {
4765     mz_uint32 zip64_total_num_of_disks =
4766         MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
4767     mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
4768         pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4769     mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
4770         pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4771     mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
4772         pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
4773     mz_uint64 zip64_size_of_central_directory =
4774         MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
4775 
4776     if (zip64_size_of_end_of_central_dir_record <
4777         (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
4778       return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4779 
4780     if (zip64_total_num_of_disks != 1U)
4781       return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4782 
4783     /* Check for miniz's practical limits */
4784     if (zip64_cdir_total_entries > MZ_UINT32_MAX)
4785       return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4786 
4787     pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
4788 
4789     if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
4790       return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4791 
4792     cdir_entries_on_this_disk =
4793         (mz_uint32)zip64_cdir_total_entries_on_this_disk;
4794 
4795     /* Check for miniz's current practical limits (sorry, this should be enough
4796      * for millions of files) */
4797     if (zip64_size_of_central_directory > MZ_UINT32_MAX)
4798       return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
4799 
4800     cdir_size = (mz_uint32)zip64_size_of_central_directory;
4801 
4802     num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
4803                                  MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
4804 
4805     cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
4806                                    MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
4807 
4808     cdir_ofs =
4809         MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
4810   }
4811 
4812   if (pZip->m_total_files != cdir_entries_on_this_disk)
4813     return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4814 
4815   if (((num_this_disk | cdir_disk_index) != 0) &&
4816       ((num_this_disk != 1) || (cdir_disk_index != 1)))
4817     return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4818 
4819   if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
4820     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4821 
4822   if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
4823     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4824 
4825   pZip->m_central_directory_file_ofs = cdir_ofs;
4826 
4827   if (pZip->m_total_files) {
4828     mz_uint i, n;
4829     /* Read the entire central directory into a heap block, and allocate another
4830      * heap block to hold the unsorted central dir file record offsets, and
4831      * possibly another to hold the sorted indices. */
4832     if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
4833                               MZ_FALSE)) ||
4834         (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
4835                               pZip->m_total_files, MZ_FALSE)))
4836       return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4837 
4838     if (sort_central_dir) {
4839       if (!mz_zip_array_resize(pZip,
4840                                &pZip->m_pState->m_sorted_central_dir_offsets,
4841                                pZip->m_total_files, MZ_FALSE))
4842         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4843     }
4844 
4845     if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
4846                       pZip->m_pState->m_central_dir.m_p,
4847                       cdir_size) != cdir_size)
4848       return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4849 
4850     /* Now create an index into the central directory file records, do some
4851      * basic sanity checking on each record */
4852     p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
4853     for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
4854       mz_uint total_header_size, disk_index, bit_flags, filename_size,
4855           ext_data_size;
4856       mz_uint64 comp_size, decomp_size, local_header_ofs;
4857 
4858       if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
4859           (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
4860         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4861 
4862       MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
4863                            i) =
4864           (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
4865 
4866       if (sort_central_dir)
4867         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
4868                              mz_uint32, i) = i;
4869 
4870       comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4871       decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4872       local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4873       filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4874       ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4875 
4876       if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
4877           (ext_data_size) &&
4878           (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
4879            MZ_UINT32_MAX)) {
4880         /* Attempt to find zip64 extended information field in the entry's extra
4881          * data */
4882         mz_uint32 extra_size_remaining = ext_data_size;
4883 
4884         if (extra_size_remaining) {
4885           const mz_uint8 *pExtra_data;
4886           void *buf = NULL;
4887 
4888           if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
4889               n) {
4890             buf = MZ_MALLOC(ext_data_size);
4891             if (buf == NULL)
4892               return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4893 
4894             if (pZip->m_pRead(pZip->m_pIO_opaque,
4895                               cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4896                                   filename_size,
4897                               buf, ext_data_size) != ext_data_size) {
4898               MZ_FREE(buf);
4899               return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4900             }
4901 
4902             pExtra_data = (mz_uint8 *)buf;
4903           } else {
4904             pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
4905           }
4906 
4907           do {
4908             mz_uint32 field_id;
4909             mz_uint32 field_data_size;
4910 
4911             if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
4912               MZ_FREE(buf);
4913               return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4914             }
4915 
4916             field_id = MZ_READ_LE16(pExtra_data);
4917             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4918 
4919             if ((field_data_size + sizeof(mz_uint16) * 2) >
4920                 extra_size_remaining) {
4921               MZ_FREE(buf);
4922               return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4923             }
4924 
4925             if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
4926               /* Ok, the archive didn't have any zip64 headers but it uses a
4927                * zip64 extended information field so mark it as zip64 anyway
4928                * (this can occur with infozip's zip util when it reads
4929                * compresses files from stdin). */
4930               pZip->m_pState->m_zip64 = MZ_TRUE;
4931               pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
4932               break;
4933             }
4934 
4935             pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4936             extra_size_remaining =
4937                 extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4938           } while (extra_size_remaining);
4939 
4940           MZ_FREE(buf);
4941         }
4942       }
4943 
4944       /* I've seen archives that aren't marked as zip64 that uses zip64 ext
4945        * data, argh */
4946       if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
4947         if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
4948              (decomp_size != comp_size)) ||
4949             (decomp_size && !comp_size))
4950           return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4951       }
4952 
4953       disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
4954       if ((disk_index == MZ_UINT16_MAX) ||
4955           ((disk_index != num_this_disk) && (disk_index != 1)))
4956         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4957 
4958       if (comp_size != MZ_UINT32_MAX) {
4959         if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
4960              MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
4961           return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4962       }
4963 
4964       bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4965       if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
4966         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4967 
4968       if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4969                                MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
4970                                MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
4971                                MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
4972           n)
4973         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4974 
4975       n -= total_header_size;
4976       p += total_header_size;
4977     }
4978   }
4979 
4980   if (sort_central_dir)
4981     mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
4982 
4983   return MZ_TRUE;
4984 }
4985 
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint32 flags)4986 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
4987                            mz_uint32 flags) {
4988   if ((!pZip) || (!pZip->m_pRead))
4989     return MZ_FALSE;
4990   if (!mz_zip_reader_init_internal(pZip, flags))
4991     return MZ_FALSE;
4992   pZip->m_archive_size = size;
4993   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
4994     mz_zip_reader_end(pZip);
4995     return MZ_FALSE;
4996   }
4997   return MZ_TRUE;
4998 }
4999 
mz_zip_mem_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5000 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
5001                                    void *pBuf, size_t n) {
5002   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5003   size_t s = (file_ofs >= pZip->m_archive_size)
5004                  ? 0
5005                  : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
5006   memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
5007   return s;
5008 }
5009 
mz_zip_reader_init_mem(mz_zip_archive * pZip,const void * pMem,size_t size,mz_uint32 flags)5010 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
5011                                size_t size, mz_uint32 flags) {
5012   if (!mz_zip_reader_init_internal(pZip, flags))
5013     return MZ_FALSE;
5014   pZip->m_archive_size = size;
5015   pZip->m_pRead = mz_zip_mem_read_func;
5016   pZip->m_pIO_opaque = pZip;
5017 #ifdef __cplusplus
5018   pZip->m_pState->m_pMem = const_cast<void *>(pMem);
5019 #else
5020   pZip->m_pState->m_pMem = (void *)pMem;
5021 #endif
5022   pZip->m_pState->m_mem_size = size;
5023   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5024     mz_zip_reader_end(pZip);
5025     return MZ_FALSE;
5026   }
5027   return MZ_TRUE;
5028 }
5029 
5030 #ifndef MINIZ_NO_STDIO
mz_zip_file_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5031 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5032                                     void *pBuf, size_t n) {
5033   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5034   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5035   if (((mz_int64)file_ofs < 0) ||
5036       (((cur_ofs != (mz_int64)file_ofs)) &&
5037        (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5038     return 0;
5039   return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5040 }
5041 
mz_zip_reader_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint32 flags)5042 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5043                                 mz_uint32 flags) {
5044   mz_uint64 file_size;
5045   MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
5046   if (!pFile)
5047     return MZ_FALSE;
5048   if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5049     MZ_FCLOSE(pFile);
5050     return MZ_FALSE;
5051   }
5052   file_size = MZ_FTELL64(pFile);
5053   if (!mz_zip_reader_init_internal(pZip, flags)) {
5054     MZ_FCLOSE(pFile);
5055     return MZ_FALSE;
5056   }
5057   pZip->m_pRead = mz_zip_file_read_func;
5058   pZip->m_pIO_opaque = pZip;
5059   pZip->m_pState->m_pFile = pFile;
5060   pZip->m_archive_size = file_size;
5061   if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5062     mz_zip_reader_end(pZip);
5063     return MZ_FALSE;
5064   }
5065   return MZ_TRUE;
5066 }
5067 #endif // #ifndef MINIZ_NO_STDIO
5068 
mz_zip_reader_get_num_files(mz_zip_archive * pZip)5069 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5070   return pZip ? pZip->m_total_files : 0;
5071 }
5072 
5073 static MZ_FORCEINLINE const mz_uint8 *
mz_zip_reader_get_cdh(mz_zip_archive * pZip,mz_uint file_index)5074 mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) {
5075   if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) ||
5076       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5077     return NULL;
5078   return &MZ_ZIP_ARRAY_ELEMENT(
5079       &pZip->m_pState->m_central_dir, mz_uint8,
5080       MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5081                            file_index));
5082 }
5083 
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)5084 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
5085                                         mz_uint file_index) {
5086   mz_uint m_bit_flag;
5087   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5088   if (!p)
5089     return MZ_FALSE;
5090   m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5091   return (m_bit_flag & 1);
5092 }
5093 
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)5094 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
5095                                           mz_uint file_index) {
5096   mz_uint filename_len, external_attr;
5097   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5098   if (!p)
5099     return MZ_FALSE;
5100 
5101   // First see if the filename ends with a '/' character.
5102   filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5103   if (filename_len) {
5104     if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
5105       return MZ_TRUE;
5106   }
5107 
5108   // Bugfix: This code was also checking if the internal attribute was non-zero,
5109   // which wasn't correct. Most/all zip writers (hopefully) set DOS
5110   // file/directory attributes in the low 16-bits, so check for the DOS
5111   // directory flag and ignore the source OS ID in the created by field.
5112   // FIXME: Remove this check? Is it necessary - we already check the filename.
5113   external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5114   if ((external_attr & 0x10) != 0)
5115     return MZ_TRUE;
5116 
5117   return MZ_FALSE;
5118 }
5119 
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)5120 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
5121                                 mz_zip_archive_file_stat *pStat) {
5122   mz_uint n;
5123   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5124   if ((!p) || (!pStat))
5125     return MZ_FALSE;
5126 
5127   // Unpack the central directory record.
5128   pStat->m_file_index = file_index;
5129   pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
5130       &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
5131   pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
5132   pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
5133   pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5134   pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
5135 #ifndef MINIZ_NO_TIME
5136   pStat->m_time =
5137       mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
5138                            MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
5139 #endif
5140   pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
5141   pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5142   pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5143   pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
5144   pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5145   pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5146 
5147   // Copy as much of the filename and comment as possible.
5148   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5149   n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
5150   memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5151   pStat->m_filename[n] = '\0';
5152 
5153   n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5154   n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
5155   pStat->m_comment_size = n;
5156   memcpy(pStat->m_comment,
5157          p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5158              MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5159              MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5160          n);
5161   pStat->m_comment[n] = '\0';
5162 
5163   return MZ_TRUE;
5164 }
5165 
mz_zip_reader_get_filename(mz_zip_archive * pZip,mz_uint file_index,char * pFilename,mz_uint filename_buf_size)5166 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
5167                                    char *pFilename, mz_uint filename_buf_size) {
5168   mz_uint n;
5169   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5170   if (!p) {
5171     if (filename_buf_size)
5172       pFilename[0] = '\0';
5173     return 0;
5174   }
5175   n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5176   if (filename_buf_size) {
5177     n = MZ_MIN(n, filename_buf_size - 1);
5178     memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5179     pFilename[n] = '\0';
5180   }
5181   return n + 1;
5182 }
5183 
mz_zip_reader_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)5184 static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA,
5185                                                          const char *pB,
5186                                                          mz_uint len,
5187                                                          mz_uint flags) {
5188   mz_uint i;
5189   if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
5190     return 0 == memcmp(pA, pB, len);
5191   for (i = 0; i < len; ++i)
5192     if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
5193       return MZ_FALSE;
5194   return MZ_TRUE;
5195 }
5196 
5197 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)5198 mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array,
5199                                const mz_zip_array *pCentral_dir_offsets,
5200                                mz_uint l_index, const char *pR, mz_uint r_len) {
5201   const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5202                      pCentral_dir_array, mz_uint8,
5203                      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5204                                           l_index)),
5205                  *pE;
5206   mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5207   mz_uint8 l = 0, r = 0;
5208   pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5209   pE = pL + MZ_MIN(l_len, r_len);
5210   while (pL < pE) {
5211     if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
5212       break;
5213     pL++;
5214     pR++;
5215   }
5216   return (pL == pE) ? (int)(l_len - r_len) : (l - r);
5217 }
5218 
mz_zip_reader_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename)5219 static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip,
5220                                                    const char *pFilename) {
5221   mz_zip_internal_state *pState = pZip->m_pState;
5222   const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5223   const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5224   mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
5225       &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
5226   const int size = pZip->m_total_files;
5227   const mz_uint filename_len = (mz_uint)strlen(pFilename);
5228   int l = 0, h = size - 1;
5229   while (l <= h) {
5230     int m = (l + h) >> 1, file_index = pIndices[m],
5231         comp =
5232             mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets,
5233                                            file_index, pFilename, filename_len);
5234     if (!comp)
5235       return file_index;
5236     else if (comp < 0)
5237       l = m + 1;
5238     else
5239       h = m - 1;
5240   }
5241   return -1;
5242 }
5243 
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)5244 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
5245                               const char *pComment, mz_uint flags) {
5246   mz_uint file_index;
5247   size_t name_len, comment_len;
5248   if ((!pZip) || (!pZip->m_pState) || (!pName) ||
5249       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5250     return -1;
5251   if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
5252       (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
5253     return mz_zip_reader_locate_file_binary_search(pZip, pName);
5254   name_len = strlen(pName);
5255   if (name_len > 0xFFFF)
5256     return -1;
5257   comment_len = pComment ? strlen(pComment) : 0;
5258   if (comment_len > 0xFFFF)
5259     return -1;
5260   for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
5261     const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
5262         &pZip->m_pState->m_central_dir, mz_uint8,
5263         MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5264                              file_index));
5265     mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5266     const char *pFilename =
5267         (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5268     if (filename_len < name_len)
5269       continue;
5270     if (comment_len) {
5271       mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5272               file_comment_len =
5273                   MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5274       const char *pFile_comment = pFilename + filename_len + file_extra_len;
5275       if ((file_comment_len != comment_len) ||
5276           (!mz_zip_reader_string_equal(pComment, pFile_comment,
5277                                        file_comment_len, flags)))
5278         continue;
5279     }
5280     if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
5281       int ofs = filename_len - 1;
5282       do {
5283         if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
5284             (pFilename[ofs] == ':'))
5285           break;
5286       } while (--ofs >= 0);
5287       ofs++;
5288       pFilename += ofs;
5289       filename_len -= ofs;
5290     }
5291     if ((filename_len == name_len) &&
5292         (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
5293       return file_index;
5294   }
5295   return -1;
5296 }
5297 
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)5298 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
5299                                               mz_uint file_index, void *pBuf,
5300                                               size_t buf_size, mz_uint flags,
5301                                               void *pUser_read_buf,
5302                                               size_t user_read_buf_size) {
5303   int status = TINFL_STATUS_DONE;
5304   mz_uint64 needed_size, cur_file_ofs, comp_remaining,
5305       out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
5306   mz_zip_archive_file_stat file_stat;
5307   void *pRead_buf;
5308   mz_uint32
5309       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5310                        sizeof(mz_uint32)];
5311   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5312   tinfl_decompressor inflator;
5313 
5314   if ((buf_size) && (!pBuf))
5315     return MZ_FALSE;
5316 
5317   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5318     return MZ_FALSE;
5319 
5320   // Empty file, or a directory (but not always a directory - I've seen odd zips
5321   // with directories that have compressed data which inflates to 0 bytes)
5322   if (!file_stat.m_comp_size)
5323     return MZ_TRUE;
5324 
5325   // Entry is a subdirectory (I've seen old zips with dir entries which have
5326   // compressed deflate data which inflates to 0 bytes, but these entries claim
5327   // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5328   // case - should it fail instead?
5329   if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5330     return MZ_TRUE;
5331 
5332   // Encryption and patch files are not supported.
5333   if (file_stat.m_bit_flag & (1 | 32))
5334     return MZ_FALSE;
5335 
5336   // This function only supports stored and deflate.
5337   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5338       (file_stat.m_method != MZ_DEFLATED))
5339     return MZ_FALSE;
5340 
5341   // Ensure supplied output buffer is large enough.
5342   needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
5343                                                       : file_stat.m_uncomp_size;
5344   if (buf_size < needed_size)
5345     return MZ_FALSE;
5346 
5347   // Read and parse the local directory entry.
5348   cur_file_ofs = file_stat.m_local_header_ofs;
5349   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5350                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5351       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5352     return MZ_FALSE;
5353   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5354     return MZ_FALSE;
5355 
5356   cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5357                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5358                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5359   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5360     return MZ_FALSE;
5361 
5362   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5363     // The file is stored or the caller has requested the compressed data.
5364     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5365                       (size_t)needed_size) != needed_size)
5366       return MZ_FALSE;
5367     return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) ||
5368            (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5369                      (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
5370   }
5371 
5372   // Decompress the file either directly from memory or from a file input
5373   // buffer.
5374   tinfl_init(&inflator);
5375 
5376   if (pZip->m_pState->m_pMem) {
5377     // Read directly from the archive in memory.
5378     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5379     read_buf_size = read_buf_avail = file_stat.m_comp_size;
5380     comp_remaining = 0;
5381   } else if (pUser_read_buf) {
5382     // Use a user provided read buffer.
5383     if (!user_read_buf_size)
5384       return MZ_FALSE;
5385     pRead_buf = (mz_uint8 *)pUser_read_buf;
5386     read_buf_size = user_read_buf_size;
5387     read_buf_avail = 0;
5388     comp_remaining = file_stat.m_comp_size;
5389   } else {
5390     // Temporarily allocate a read buffer.
5391     read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5392     if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
5393       return MZ_FALSE;
5394 
5395     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5396                                             (size_t)read_buf_size)))
5397       return MZ_FALSE;
5398     read_buf_avail = 0;
5399     comp_remaining = file_stat.m_comp_size;
5400   }
5401 
5402   do {
5403     size_t in_buf_size,
5404         out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
5405     if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5406       read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5407       if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5408                         (size_t)read_buf_avail) != read_buf_avail) {
5409         status = TINFL_STATUS_FAILED;
5410         break;
5411       }
5412       cur_file_ofs += read_buf_avail;
5413       comp_remaining -= read_buf_avail;
5414       read_buf_ofs = 0;
5415     }
5416     in_buf_size = (size_t)read_buf_avail;
5417     status = tinfl_decompress(
5418         &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5419         (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
5420         TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
5421             (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
5422     read_buf_avail -= in_buf_size;
5423     read_buf_ofs += in_buf_size;
5424     out_buf_ofs += out_buf_size;
5425   } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
5426 
5427   if (status == TINFL_STATUS_DONE) {
5428     // Make sure the entire file was decompressed, and check its CRC.
5429     if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5430         (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5431                   (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
5432       status = TINFL_STATUS_FAILED;
5433   }
5434 
5435   if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
5436     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5437 
5438   return status == TINFL_STATUS_DONE;
5439 }
5440 
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)5441 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
5442     mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
5443     mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
5444   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5445   if (file_index < 0)
5446     return MZ_FALSE;
5447   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5448                                                flags, pUser_read_buf,
5449                                                user_read_buf_size);
5450 }
5451 
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)5452 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
5453                                      void *pBuf, size_t buf_size,
5454                                      mz_uint flags) {
5455   return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5456                                                flags, NULL, 0);
5457 }
5458 
mz_zip_reader_extract_file_to_mem(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags)5459 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
5460                                           const char *pFilename, void *pBuf,
5461                                           size_t buf_size, mz_uint flags) {
5462   return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
5463                                                     buf_size, flags, NULL, 0);
5464 }
5465 
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)5466 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
5467                                     size_t *pSize, mz_uint flags) {
5468   mz_uint64 comp_size, uncomp_size, alloc_size;
5469   const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5470   void *pBuf;
5471 
5472   if (pSize)
5473     *pSize = 0;
5474   if (!p)
5475     return NULL;
5476 
5477   comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5478   uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5479 
5480   alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
5481   if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5482     return NULL;
5483   if (NULL ==
5484       (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
5485     return NULL;
5486 
5487   if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
5488                                     flags)) {
5489     pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
5490     return NULL;
5491   }
5492 
5493   if (pSize)
5494     *pSize = (size_t)alloc_size;
5495   return pBuf;
5496 }
5497 
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)5498 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
5499                                          const char *pFilename, size_t *pSize,
5500                                          mz_uint flags) {
5501   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5502   if (file_index < 0) {
5503     if (pSize)
5504       *pSize = 0;
5505     return MZ_FALSE;
5506   }
5507   return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
5508 }
5509 
mz_zip_reader_extract_to_callback(mz_zip_archive * pZip,mz_uint file_index,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5510 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
5511                                           mz_uint file_index,
5512                                           mz_file_write_func pCallback,
5513                                           void *pOpaque, mz_uint flags) {
5514   int status = TINFL_STATUS_DONE;
5515   mz_uint file_crc32 = MZ_CRC32_INIT;
5516   mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
5517                            out_buf_ofs = 0, cur_file_ofs;
5518   mz_zip_archive_file_stat file_stat;
5519   void *pRead_buf = NULL;
5520   void *pWrite_buf = NULL;
5521   mz_uint32
5522       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5523                        sizeof(mz_uint32)];
5524   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5525 
5526   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5527     return MZ_FALSE;
5528 
5529   // Empty file, or a directory (but not always a directory - I've seen odd zips
5530   // with directories that have compressed data which inflates to 0 bytes)
5531   if (!file_stat.m_comp_size)
5532     return MZ_TRUE;
5533 
5534   // Entry is a subdirectory (I've seen old zips with dir entries which have
5535   // compressed deflate data which inflates to 0 bytes, but these entries claim
5536   // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5537   // case - should it fail instead?
5538   if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5539     return MZ_TRUE;
5540 
5541   // Encryption and patch files are not supported.
5542   if (file_stat.m_bit_flag & (1 | 32))
5543     return MZ_FALSE;
5544 
5545   // This function only supports stored and deflate.
5546   if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5547       (file_stat.m_method != MZ_DEFLATED))
5548     return MZ_FALSE;
5549 
5550   // Read and parse the local directory entry.
5551   cur_file_ofs = file_stat.m_local_header_ofs;
5552   if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5553                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5554       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5555     return MZ_FALSE;
5556   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5557     return MZ_FALSE;
5558 
5559   cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5560                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5561                   MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5562   if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5563     return MZ_FALSE;
5564 
5565   // Decompress the file either directly from memory or from a file input
5566   // buffer.
5567   if (pZip->m_pState->m_pMem) {
5568     pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5569     read_buf_size = read_buf_avail = file_stat.m_comp_size;
5570     comp_remaining = 0;
5571   } else {
5572     read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5573     if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5574                                             (size_t)read_buf_size)))
5575       return MZ_FALSE;
5576     read_buf_avail = 0;
5577     comp_remaining = file_stat.m_comp_size;
5578   }
5579 
5580   if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5581     // The file is stored or the caller has requested the compressed data.
5582     if (pZip->m_pState->m_pMem) {
5583       if (((sizeof(size_t) == sizeof(mz_uint32))) &&
5584           (file_stat.m_comp_size > 0xFFFFFFFF))
5585         return MZ_FALSE;
5586 
5587       if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5588                     (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
5589         status = TINFL_STATUS_FAILED;
5590       else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5591         file_crc32 =
5592             (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
5593                                 (size_t)file_stat.m_comp_size);
5594       // cur_file_ofs += file_stat.m_comp_size;
5595       out_buf_ofs += file_stat.m_comp_size;
5596       // comp_remaining = 0;
5597     } else {
5598       while (comp_remaining) {
5599         read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5600         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5601                           (size_t)read_buf_avail) != read_buf_avail) {
5602           status = TINFL_STATUS_FAILED;
5603           break;
5604         }
5605 
5606         if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5607           file_crc32 = (mz_uint32)mz_crc32(
5608               file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
5609 
5610         if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5611                       (size_t)read_buf_avail) != read_buf_avail) {
5612           status = TINFL_STATUS_FAILED;
5613           break;
5614         }
5615         cur_file_ofs += read_buf_avail;
5616         out_buf_ofs += read_buf_avail;
5617         comp_remaining -= read_buf_avail;
5618       }
5619     }
5620   } else {
5621     tinfl_decompressor inflator;
5622     tinfl_init(&inflator);
5623 
5624     if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5625                                              TINFL_LZ_DICT_SIZE)))
5626       status = TINFL_STATUS_FAILED;
5627     else {
5628       do {
5629         mz_uint8 *pWrite_buf_cur =
5630             (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5631         size_t in_buf_size,
5632             out_buf_size =
5633                 TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5634         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5635           read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5636           if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5637                             (size_t)read_buf_avail) != read_buf_avail) {
5638             status = TINFL_STATUS_FAILED;
5639             break;
5640           }
5641           cur_file_ofs += read_buf_avail;
5642           comp_remaining -= read_buf_avail;
5643           read_buf_ofs = 0;
5644         }
5645 
5646         in_buf_size = (size_t)read_buf_avail;
5647         status = tinfl_decompress(
5648             &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5649             (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
5650             comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5651         read_buf_avail -= in_buf_size;
5652         read_buf_ofs += in_buf_size;
5653 
5654         if (out_buf_size) {
5655           if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
5656               out_buf_size) {
5657             status = TINFL_STATUS_FAILED;
5658             break;
5659           }
5660           file_crc32 =
5661               (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
5662           if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
5663             status = TINFL_STATUS_FAILED;
5664             break;
5665           }
5666         }
5667       } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
5668                (status == TINFL_STATUS_HAS_MORE_OUTPUT));
5669     }
5670   }
5671 
5672   if ((status == TINFL_STATUS_DONE) &&
5673       (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
5674     // Make sure the entire file was decompressed, and check its CRC.
5675     if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5676         (file_crc32 != file_stat.m_crc32))
5677       status = TINFL_STATUS_FAILED;
5678   }
5679 
5680   if (!pZip->m_pState->m_pMem)
5681     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5682   if (pWrite_buf)
5683     pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
5684 
5685   return status == TINFL_STATUS_DONE;
5686 }
5687 
mz_zip_reader_extract_file_to_callback(mz_zip_archive * pZip,const char * pFilename,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5688 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
5689                                                const char *pFilename,
5690                                                mz_file_write_func pCallback,
5691                                                void *pOpaque, mz_uint flags) {
5692   int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5693   if (file_index < 0)
5694     return MZ_FALSE;
5695   return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
5696                                            flags);
5697 }
5698 
5699 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_callback(void * pOpaque,mz_uint64 ofs,const void * pBuf,size_t n)5700 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
5701                                          const void *pBuf, size_t n) {
5702   (void)ofs;
5703   return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5704 }
5705 
mz_zip_reader_extract_to_file(mz_zip_archive * pZip,mz_uint file_index,const char * pDst_filename,mz_uint flags)5706 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
5707                                       const char *pDst_filename,
5708                                       mz_uint flags) {
5709   mz_bool status;
5710   mz_zip_archive_file_stat file_stat;
5711   MZ_FILE *pFile;
5712   if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5713     return MZ_FALSE;
5714 
5715   pFile = MZ_FOPEN(pDst_filename, "wb");
5716   if (!pFile)
5717     return MZ_FALSE;
5718   status = mz_zip_reader_extract_to_callback(
5719       pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5720   if (MZ_FCLOSE(pFile) == EOF)
5721     return MZ_FALSE;
5722 #ifndef MINIZ_NO_TIME
5723   if (status) {
5724     mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5725   }
5726 #endif
5727 
5728   return status;
5729 }
5730 #endif // #ifndef MINIZ_NO_STDIO
5731 
mz_zip_reader_end(mz_zip_archive * pZip)5732 mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5733   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5734       (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5735     return MZ_FALSE;
5736 
5737   mz_zip_internal_state *pState = pZip->m_pState;
5738   pZip->m_pState = NULL;
5739   mz_zip_array_clear(pZip, &pState->m_central_dir);
5740   mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5741   mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5742 
5743 #ifndef MINIZ_NO_STDIO
5744   if (pState->m_pFile) {
5745     MZ_FCLOSE(pState->m_pFile);
5746     pState->m_pFile = NULL;
5747   }
5748 #endif // #ifndef MINIZ_NO_STDIO
5749 
5750   pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5751 
5752   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5753 
5754   return MZ_TRUE;
5755 }
5756 
5757 #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)5758 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
5759                                            const char *pArchive_filename,
5760                                            const char *pDst_filename,
5761                                            mz_uint flags) {
5762   int file_index =
5763       mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
5764   if (file_index < 0)
5765     return MZ_FALSE;
5766   return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5767 }
5768 #endif
5769 
5770 // ------------------- .ZIP archive writing
5771 
5772 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5773 
mz_write_le16(mz_uint8 * p,mz_uint16 v)5774 static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5775   p[0] = (mz_uint8)v;
5776   p[1] = (mz_uint8)(v >> 8);
5777 }
mz_write_le32(mz_uint8 * p,mz_uint32 v)5778 static void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
5779   p[0] = (mz_uint8)v;
5780   p[1] = (mz_uint8)(v >> 8);
5781   p[2] = (mz_uint8)(v >> 16);
5782   p[3] = (mz_uint8)(v >> 24);
5783 }
5784 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5785 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5786 
mz_zip_writer_init(mz_zip_archive * pZip,mz_uint64 existing_size)5787 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
5788   if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
5789       (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5790     return MZ_FALSE;
5791 
5792   if (pZip->m_file_offset_alignment) {
5793     // Ensure user specified file offset alignment is a power of 2.
5794     if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5795       return MZ_FALSE;
5796   }
5797 
5798   if (!pZip->m_pAlloc)
5799     pZip->m_pAlloc = def_alloc_func;
5800   if (!pZip->m_pFree)
5801     pZip->m_pFree = def_free_func;
5802   if (!pZip->m_pRealloc)
5803     pZip->m_pRealloc = def_realloc_func;
5804 
5805   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5806   pZip->m_archive_size = existing_size;
5807   pZip->m_central_directory_file_ofs = 0;
5808   pZip->m_total_files = 0;
5809 
5810   if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5811                    pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5812     return MZ_FALSE;
5813   memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5814   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5815                                 sizeof(mz_uint8));
5816   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5817                                 sizeof(mz_uint32));
5818   MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5819                                 sizeof(mz_uint32));
5820   return MZ_TRUE;
5821 }
5822 
mz_zip_heap_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5823 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
5824                                      const void *pBuf, size_t n) {
5825   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5826   mz_zip_internal_state *pState = pZip->m_pState;
5827   mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5828 
5829   if ((!n) ||
5830       ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5831     return 0;
5832 
5833   if (new_size > pState->m_mem_capacity) {
5834     void *pNew_block;
5835     size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5836     while (new_capacity < new_size)
5837       new_capacity *= 2;
5838     if (NULL == (pNew_block = pZip->m_pRealloc(
5839                      pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5840       return 0;
5841     pState->m_pMem = pNew_block;
5842     pState->m_mem_capacity = new_capacity;
5843   }
5844   memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5845   pState->m_mem_size = (size_t)new_size;
5846   return n;
5847 }
5848 
mz_zip_writer_init_heap(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size)5849 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
5850                                 size_t size_to_reserve_at_beginning,
5851                                 size_t initial_allocation_size) {
5852   pZip->m_pWrite = mz_zip_heap_write_func;
5853   pZip->m_pIO_opaque = pZip;
5854   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5855     return MZ_FALSE;
5856   if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
5857                                              size_to_reserve_at_beginning))) {
5858     if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
5859                      pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
5860       mz_zip_writer_end(pZip);
5861       return MZ_FALSE;
5862     }
5863     pZip->m_pState->m_mem_capacity = initial_allocation_size;
5864   }
5865   return MZ_TRUE;
5866 }
5867 
5868 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5869 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
5870                                      const void *pBuf, size_t n) {
5871   mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5872   mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5873   if (((mz_int64)file_ofs < 0) ||
5874       (((cur_ofs != (mz_int64)file_ofs)) &&
5875        (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5876     return 0;
5877   return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5878 }
5879 
mz_zip_writer_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning)5880 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
5881                                 mz_uint64 size_to_reserve_at_beginning) {
5882   MZ_FILE *pFile;
5883   pZip->m_pWrite = mz_zip_file_write_func;
5884   pZip->m_pIO_opaque = pZip;
5885   if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5886     return MZ_FALSE;
5887   if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) {
5888     mz_zip_writer_end(pZip);
5889     return MZ_FALSE;
5890   }
5891   pZip->m_pState->m_pFile = pFile;
5892   if (size_to_reserve_at_beginning) {
5893     mz_uint64 cur_ofs = 0;
5894     char buf[4096];
5895     MZ_CLEAR_OBJ(buf);
5896     do {
5897       size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5898       if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
5899         mz_zip_writer_end(pZip);
5900         return MZ_FALSE;
5901       }
5902       cur_ofs += n;
5903       size_to_reserve_at_beginning -= n;
5904     } while (size_to_reserve_at_beginning);
5905   }
5906   return MZ_TRUE;
5907 }
5908 #endif // #ifndef MINIZ_NO_STDIO
5909 
mz_zip_writer_init_from_reader(mz_zip_archive * pZip,const char * pFilename)5910 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
5911                                        const char *pFilename) {
5912   mz_zip_internal_state *pState;
5913   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5914     return MZ_FALSE;
5915   // No sense in trying to write to an archive that's already at the support max
5916   // size
5917   if ((pZip->m_total_files == 0xFFFF) ||
5918       ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5919         MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
5920     return MZ_FALSE;
5921 
5922   pState = pZip->m_pState;
5923 
5924   if (pState->m_pFile) {
5925 #ifdef MINIZ_NO_STDIO
5926     pFilename;
5927     return MZ_FALSE;
5928 #else
5929     // Archive is being read from stdio - try to reopen as writable.
5930     if (pZip->m_pIO_opaque != pZip)
5931       return MZ_FALSE;
5932     if (!pFilename)
5933       return MZ_FALSE;
5934     pZip->m_pWrite = mz_zip_file_write_func;
5935     if (NULL ==
5936         (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
5937       // The mz_zip_archive is now in a bogus state because pState->m_pFile is
5938       // NULL, so just close it.
5939       mz_zip_reader_end(pZip);
5940       return MZ_FALSE;
5941     }
5942 #endif // #ifdef MINIZ_NO_STDIO
5943   } else if (pState->m_pMem) {
5944     // Archive lives in a memory block. Assume it's from the heap that we can
5945     // resize using the realloc callback.
5946     if (pZip->m_pIO_opaque != pZip)
5947       return MZ_FALSE;
5948     pState->m_mem_capacity = pState->m_mem_size;
5949     pZip->m_pWrite = mz_zip_heap_write_func;
5950   }
5951   // Archive is being read via a user provided read function - make sure the
5952   // user has specified a write function too.
5953   else if (!pZip->m_pWrite)
5954     return MZ_FALSE;
5955 
5956   // Start writing new files at the archive's current central directory
5957   // location.
5958   pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5959   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5960   pZip->m_central_directory_file_ofs = 0;
5961 
5962   return MZ_TRUE;
5963 }
5964 
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)5965 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
5966                               const void *pBuf, size_t buf_size,
5967                               mz_uint level_and_flags) {
5968   return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
5969                                   level_and_flags, 0, 0);
5970 }
5971 
5972 typedef struct {
5973   mz_zip_archive *m_pZip;
5974   mz_uint64 m_cur_archive_file_ofs;
5975   mz_uint64 m_comp_size;
5976 } mz_zip_writer_add_state;
5977 
mz_zip_writer_add_put_buf_callback(const void * pBuf,int len,void * pUser)5978 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
5979                                                   void *pUser) {
5980   mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
5981   if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
5982                                     pState->m_cur_archive_file_ofs, pBuf,
5983                                     len) != len)
5984     return MZ_FALSE;
5985   pState->m_cur_archive_file_ofs += len;
5986   pState->m_comp_size += len;
5987   return MZ_TRUE;
5988 }
5989 
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)5990 static mz_bool mz_zip_writer_create_local_dir_header(
5991     mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
5992     mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
5993     mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
5994     mz_uint16 dos_time, mz_uint16 dos_date) {
5995   (void)pZip;
5996   memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5997   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5998   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5999   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6000   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6001   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6002   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6003   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6004   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
6005   MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6006   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6007   MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6008   return MZ_TRUE;
6009 }
6010 
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)6011 static mz_bool mz_zip_writer_create_central_dir_header(
6012     mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6013     mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
6014     mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
6015     mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6016     mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
6017   (void)pZip;
6018   mz_uint16 version_made_by = 10 * MZ_VER_MAJOR + MZ_VER_MINOR;
6019   version_made_by |= (MZ_PLATFORM << 8);
6020 
6021   memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6022   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6023   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, version_made_by);
6024   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6025   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6026   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6027   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6028   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6029   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6030   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
6031   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6032   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6033   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6034   MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6035   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6036   MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
6037   return MZ_TRUE;
6038 }
6039 
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)6040 static mz_bool mz_zip_writer_add_to_central_dir(
6041     mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6042     const void *pExtra, mz_uint16 extra_size, const void *pComment,
6043     mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6044     mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6045     mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
6046     mz_uint32 ext_attributes) {
6047   mz_zip_internal_state *pState = pZip->m_pState;
6048   mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6049   size_t orig_central_dir_size = pState->m_central_dir.m_size;
6050   mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6051 
6052   // No zip64 support yet
6053   if ((local_header_ofs > 0xFFFFFFFF) ||
6054       (((mz_uint64)pState->m_central_dir.m_size +
6055         MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
6056         comment_size) > 0xFFFFFFFF))
6057     return MZ_FALSE;
6058 
6059   if (!mz_zip_writer_create_central_dir_header(
6060           pZip, central_dir_header, filename_size, extra_size, comment_size,
6061           uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
6062           dos_date, local_header_ofs, ext_attributes))
6063     return MZ_FALSE;
6064 
6065   if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
6066                                MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6067       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
6068                                filename_size)) ||
6069       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
6070                                extra_size)) ||
6071       (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
6072                                comment_size)) ||
6073       (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
6074                                &central_dir_ofs, 1))) {
6075     // Try to push the central directory array back into its original state.
6076     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6077                         MZ_FALSE);
6078     return MZ_FALSE;
6079   }
6080 
6081   return MZ_TRUE;
6082 }
6083 
mz_zip_writer_validate_archive_name(const char * pArchive_name)6084 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
6085   // Basic ZIP archive filename validity checks: Valid filenames cannot start
6086   // with a forward slash, cannot contain a drive letter, and cannot use
6087   // DOS-style backward slashes.
6088   if (*pArchive_name == '/')
6089     return MZ_FALSE;
6090   while (*pArchive_name) {
6091     if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
6092       return MZ_FALSE;
6093     pArchive_name++;
6094   }
6095   return MZ_TRUE;
6096 }
6097 
6098 static mz_uint
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive * pZip)6099 mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
6100   mz_uint32 n;
6101   if (!pZip->m_file_offset_alignment)
6102     return 0;
6103   n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6104   return (pZip->m_file_offset_alignment - n) &
6105          (pZip->m_file_offset_alignment - 1);
6106 }
6107 
mz_zip_writer_write_zeros(mz_zip_archive * pZip,mz_uint64 cur_file_ofs,mz_uint32 n)6108 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
6109                                          mz_uint64 cur_file_ofs, mz_uint32 n) {
6110   char buf[4096];
6111   memset(buf, 0, MZ_MIN(sizeof(buf), n));
6112   while (n) {
6113     mz_uint32 s = MZ_MIN(sizeof(buf), n);
6114     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6115       return MZ_FALSE;
6116     cur_file_ofs += s;
6117     n -= s;
6118   }
6119   return MZ_TRUE;
6120 }
6121 
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)6122 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
6123                                  const char *pArchive_name, const void *pBuf,
6124                                  size_t buf_size, const void *pComment,
6125                                  mz_uint16 comment_size,
6126                                  mz_uint level_and_flags, mz_uint64 uncomp_size,
6127                                  mz_uint32 uncomp_crc32) {
6128   mz_uint32 ext_attributes = 0;
6129   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6130   mz_uint level, num_alignment_padding_bytes;
6131   mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0;
6132   size_t archive_name_size;
6133   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6134   tdefl_compressor *pComp = NULL;
6135   mz_bool store_data_uncompressed;
6136   mz_zip_internal_state *pState;
6137 
6138   if ((int)level_and_flags < 0)
6139     level_and_flags = MZ_DEFAULT_LEVEL;
6140   level = level_and_flags & 0xF;
6141   store_data_uncompressed =
6142       ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6143 
6144   if ((!pZip) || (!pZip->m_pState) ||
6145       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
6146       (!pArchive_name) || ((comment_size) && (!pComment)) ||
6147       (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
6148     return MZ_FALSE;
6149 
6150   local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6151   pState = pZip->m_pState;
6152 
6153   if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6154     return MZ_FALSE;
6155   // No zip64 support yet
6156   if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6157     return MZ_FALSE;
6158   if (!mz_zip_writer_validate_archive_name(pArchive_name))
6159     return MZ_FALSE;
6160 
6161 #ifndef MINIZ_NO_TIME
6162   {
6163     time_t cur_time;
6164     time(&cur_time);
6165     mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6166   }
6167 #endif // #ifndef MINIZ_NO_TIME
6168 
6169   archive_name_size = strlen(pArchive_name);
6170   if (archive_name_size > 0xFFFF)
6171     return MZ_FALSE;
6172 
6173   num_alignment_padding_bytes =
6174       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6175 
6176   // no zip64 support yet
6177   if ((pZip->m_total_files == 0xFFFF) ||
6178       ((pZip->m_archive_size + num_alignment_padding_bytes +
6179         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6180         comment_size + archive_name_size) > 0xFFFFFFFF))
6181     return MZ_FALSE;
6182 
6183   if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
6184     // Set DOS Subdirectory attribute bit.
6185     ext_attributes |= 0x10;
6186     // Subdirectories cannot contain data.
6187     if ((buf_size) || (uncomp_size))
6188       return MZ_FALSE;
6189   }
6190 
6191   // Try to do any allocations before writing to the archive, so if an
6192   // allocation fails the file remains unmodified. (A good idea if we're doing
6193   // an in-place modification.)
6194   if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir,
6195                                  MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6196                                      archive_name_size + comment_size)) ||
6197       (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6198     return MZ_FALSE;
6199 
6200   if ((!store_data_uncompressed) && (buf_size)) {
6201     if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
6202                      pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6203       return MZ_FALSE;
6204   }
6205 
6206   if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6207                                  num_alignment_padding_bytes +
6208                                      sizeof(local_dir_header))) {
6209     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6210     return MZ_FALSE;
6211   }
6212   local_dir_header_ofs += num_alignment_padding_bytes;
6213   if (pZip->m_file_offset_alignment) {
6214     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6215               0);
6216   }
6217   cur_archive_file_ofs +=
6218       num_alignment_padding_bytes + sizeof(local_dir_header);
6219 
6220   MZ_CLEAR_OBJ(local_dir_header);
6221   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6222                      archive_name_size) != archive_name_size) {
6223     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6224     return MZ_FALSE;
6225   }
6226   cur_archive_file_ofs += archive_name_size;
6227 
6228   if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6229     uncomp_crc32 =
6230         (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6231     uncomp_size = buf_size;
6232     if (uncomp_size <= 3) {
6233       level = 0;
6234       store_data_uncompressed = MZ_TRUE;
6235     }
6236   }
6237 
6238   if (store_data_uncompressed) {
6239     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
6240                        buf_size) != buf_size) {
6241       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6242       return MZ_FALSE;
6243     }
6244 
6245     cur_archive_file_ofs += buf_size;
6246     comp_size = buf_size;
6247 
6248     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6249       method = MZ_DEFLATED;
6250   } else if (buf_size) {
6251     mz_zip_writer_add_state state;
6252 
6253     state.m_pZip = pZip;
6254     state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6255     state.m_comp_size = 0;
6256 
6257     if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6258                     tdefl_create_comp_flags_from_zip_params(
6259                         level, -15, MZ_DEFAULT_STRATEGY)) !=
6260          TDEFL_STATUS_OKAY) ||
6261         (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
6262          TDEFL_STATUS_DONE)) {
6263       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6264       return MZ_FALSE;
6265     }
6266 
6267     comp_size = state.m_comp_size;
6268     cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6269 
6270     method = MZ_DEFLATED;
6271   }
6272 
6273   pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6274   pComp = NULL;
6275 
6276   // no zip64 support yet
6277   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6278     return MZ_FALSE;
6279 
6280   if (!mz_zip_writer_create_local_dir_header(
6281           pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6282           comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6283     return MZ_FALSE;
6284 
6285   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6286                      sizeof(local_dir_header)) != sizeof(local_dir_header))
6287     return MZ_FALSE;
6288 
6289   if (!mz_zip_writer_add_to_central_dir(
6290           pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6291           comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6292           dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6293     return MZ_FALSE;
6294 
6295   pZip->m_total_files++;
6296   pZip->m_archive_size = cur_archive_file_ofs;
6297 
6298   return MZ_TRUE;
6299 }
6300 
6301 #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,mz_uint32 ext_attributes)6302 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
6303                                const char *pSrc_filename, const void *pComment,
6304                                mz_uint16 comment_size, mz_uint level_and_flags,
6305                                mz_uint32 ext_attributes) {
6306   mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6307   mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6308 #ifndef MINIZ_NO_TIME
6309   time_t file_modified_time;
6310 #endif
6311 
6312   mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
6313                                                         comp_size = 0;
6314   size_t archive_name_size;
6315   mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6316   MZ_FILE *pSrc_file = NULL;
6317 
6318   if ((int)level_and_flags < 0)
6319     level_and_flags = MZ_DEFAULT_LEVEL;
6320   level = level_and_flags & 0xF;
6321 
6322   if ((!pZip) || (!pZip->m_pState) ||
6323       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
6324       ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6325     return MZ_FALSE;
6326 
6327   local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6328 
6329   if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6330     return MZ_FALSE;
6331   if (!mz_zip_writer_validate_archive_name(pArchive_name))
6332     return MZ_FALSE;
6333 
6334   archive_name_size = strlen(pArchive_name);
6335   if (archive_name_size > 0xFFFF)
6336     return MZ_FALSE;
6337 
6338   num_alignment_padding_bytes =
6339       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6340 
6341   // no zip64 support yet
6342   if ((pZip->m_total_files == 0xFFFF) ||
6343       ((pZip->m_archive_size + num_alignment_padding_bytes +
6344         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6345         comment_size + archive_name_size) > 0xFFFFFFFF))
6346     return MZ_FALSE;
6347 
6348 #ifndef MINIZ_NO_TIME
6349   memset(&file_modified_time, 0, sizeof(file_modified_time));
6350   if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6351     return MZ_FALSE;
6352   mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
6353 #endif
6354 
6355   pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6356   if (!pSrc_file)
6357     return MZ_FALSE;
6358   MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6359   uncomp_size = MZ_FTELL64(pSrc_file);
6360   MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6361 
6362   if (uncomp_size > 0xFFFFFFFF) {
6363     // No zip64 support yet
6364     MZ_FCLOSE(pSrc_file);
6365     return MZ_FALSE;
6366   }
6367   if (uncomp_size <= 3)
6368     level = 0;
6369 
6370   if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6371                                  num_alignment_padding_bytes +
6372                                      sizeof(local_dir_header))) {
6373     MZ_FCLOSE(pSrc_file);
6374     return MZ_FALSE;
6375   }
6376   local_dir_header_ofs += num_alignment_padding_bytes;
6377   if (pZip->m_file_offset_alignment) {
6378     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6379               0);
6380   }
6381   cur_archive_file_ofs +=
6382       num_alignment_padding_bytes + sizeof(local_dir_header);
6383 
6384   MZ_CLEAR_OBJ(local_dir_header);
6385   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6386                      archive_name_size) != archive_name_size) {
6387     MZ_FCLOSE(pSrc_file);
6388     return MZ_FALSE;
6389   }
6390   cur_archive_file_ofs += archive_name_size;
6391 
6392   if (uncomp_size) {
6393     mz_uint64 uncomp_remaining = uncomp_size;
6394     void *pRead_buf =
6395         pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6396     if (!pRead_buf) {
6397       MZ_FCLOSE(pSrc_file);
6398       return MZ_FALSE;
6399     }
6400 
6401     if (!level) {
6402       while (uncomp_remaining) {
6403         mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6404         if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) ||
6405             (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
6406                             n) != n)) {
6407           pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6408           MZ_FCLOSE(pSrc_file);
6409           return MZ_FALSE;
6410         }
6411         uncomp_crc32 =
6412             (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6413         uncomp_remaining -= n;
6414         cur_archive_file_ofs += n;
6415       }
6416       comp_size = uncomp_size;
6417     } else {
6418       mz_bool result = MZ_FALSE;
6419       mz_zip_writer_add_state state;
6420       tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
6421           pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6422       if (!pComp) {
6423         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6424         MZ_FCLOSE(pSrc_file);
6425         return MZ_FALSE;
6426       }
6427 
6428       state.m_pZip = pZip;
6429       state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6430       state.m_comp_size = 0;
6431 
6432       if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6433                      tdefl_create_comp_flags_from_zip_params(
6434                          level, -15, MZ_DEFAULT_STRATEGY)) !=
6435           TDEFL_STATUS_OKAY) {
6436         pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6437         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6438         MZ_FCLOSE(pSrc_file);
6439         return MZ_FALSE;
6440       }
6441 
6442       for (;;) {
6443         size_t in_buf_size =
6444             (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
6445         tdefl_status status;
6446 
6447         if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6448           break;
6449 
6450         uncomp_crc32 = (mz_uint32)mz_crc32(
6451             uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6452         uncomp_remaining -= in_buf_size;
6453 
6454         status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size,
6455                                        uncomp_remaining ? TDEFL_NO_FLUSH
6456                                                         : TDEFL_FINISH);
6457         if (status == TDEFL_STATUS_DONE) {
6458           result = MZ_TRUE;
6459           break;
6460         } else if (status != TDEFL_STATUS_OKAY)
6461           break;
6462       }
6463 
6464       pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6465 
6466       if (!result) {
6467         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6468         MZ_FCLOSE(pSrc_file);
6469         return MZ_FALSE;
6470       }
6471 
6472       comp_size = state.m_comp_size;
6473       cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6474 
6475       method = MZ_DEFLATED;
6476     }
6477 
6478     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6479   }
6480 
6481   MZ_FCLOSE(pSrc_file);
6482   pSrc_file = NULL;
6483 
6484   // no zip64 support yet
6485   if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6486     return MZ_FALSE;
6487 
6488   if (!mz_zip_writer_create_local_dir_header(
6489           pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6490           comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6491     return MZ_FALSE;
6492 
6493   if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6494                      sizeof(local_dir_header)) != sizeof(local_dir_header))
6495     return MZ_FALSE;
6496 
6497   if (!mz_zip_writer_add_to_central_dir(
6498           pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6499           comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6500           dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6501     return MZ_FALSE;
6502 
6503   pZip->m_total_files++;
6504   pZip->m_archive_size = cur_archive_file_ofs;
6505 
6506   return MZ_TRUE;
6507 }
6508 #endif // #ifndef MINIZ_NO_STDIO
6509 
mz_zip_writer_add_from_zip_reader(mz_zip_archive * pZip,mz_zip_archive * pSource_zip,mz_uint file_index)6510 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
6511                                           mz_zip_archive *pSource_zip,
6512                                           mz_uint file_index) {
6513   mz_uint n, bit_flags, num_alignment_padding_bytes;
6514   mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
6515   mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6516   mz_uint32
6517       local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6518                        sizeof(mz_uint32)];
6519   mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6520   mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6521   size_t orig_central_dir_size;
6522   mz_zip_internal_state *pState;
6523   void *pBuf;
6524   const mz_uint8 *pSrc_central_header;
6525 
6526   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6527     return MZ_FALSE;
6528   if (NULL ==
6529       (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
6530     return MZ_FALSE;
6531   pState = pZip->m_pState;
6532 
6533   num_alignment_padding_bytes =
6534       mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6535 
6536   // no zip64 support yet
6537   if ((pZip->m_total_files == 0xFFFF) ||
6538       ((pZip->m_archive_size + num_alignment_padding_bytes +
6539         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) >
6540        0xFFFFFFFF))
6541     return MZ_FALSE;
6542 
6543   cur_src_file_ofs =
6544       MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6545   cur_dst_file_ofs = pZip->m_archive_size;
6546 
6547   if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
6548                            pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6549       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6550     return MZ_FALSE;
6551   if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6552     return MZ_FALSE;
6553   cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6554 
6555   if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
6556                                  num_alignment_padding_bytes))
6557     return MZ_FALSE;
6558   cur_dst_file_ofs += num_alignment_padding_bytes;
6559   local_dir_header_ofs = cur_dst_file_ofs;
6560   if (pZip->m_file_offset_alignment) {
6561     MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6562               0);
6563   }
6564 
6565   if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
6566                      MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6567       MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6568     return MZ_FALSE;
6569   cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6570 
6571   n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6572       MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6573   comp_bytes_remaining =
6574       n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6575 
6576   if (NULL ==
6577       (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6578                              (size_t)MZ_MAX(sizeof(mz_uint32) * 4,
6579                                             MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE,
6580                                                    comp_bytes_remaining)))))
6581     return MZ_FALSE;
6582 
6583   while (comp_bytes_remaining) {
6584     n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
6585     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6586                              n) != n) {
6587       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6588       return MZ_FALSE;
6589     }
6590     cur_src_file_ofs += n;
6591 
6592     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6593       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6594       return MZ_FALSE;
6595     }
6596     cur_dst_file_ofs += n;
6597 
6598     comp_bytes_remaining -= n;
6599   }
6600 
6601   bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6602   if (bit_flags & 8) {
6603     // Copy data descriptor
6604     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6605                              sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) {
6606       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6607       return MZ_FALSE;
6608     }
6609 
6610     n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
6611     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6612       pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6613       return MZ_FALSE;
6614     }
6615 
6616     // cur_src_file_ofs += n;
6617     cur_dst_file_ofs += n;
6618   }
6619   pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6620 
6621   // no zip64 support yet
6622   if (cur_dst_file_ofs > 0xFFFFFFFF)
6623     return MZ_FALSE;
6624 
6625   orig_central_dir_size = pState->m_central_dir.m_size;
6626 
6627   memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6628   MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
6629                 local_dir_header_ofs);
6630   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header,
6631                               MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6632     return MZ_FALSE;
6633 
6634   n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6635       MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
6636       MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6637   if (!mz_zip_array_push_back(
6638           pZip, &pState->m_central_dir,
6639           pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) {
6640     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6641                         MZ_FALSE);
6642     return MZ_FALSE;
6643   }
6644 
6645   if (pState->m_central_dir.m_size > 0xFFFFFFFF)
6646     return MZ_FALSE;
6647   n = (mz_uint32)orig_central_dir_size;
6648   if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
6649     mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6650                         MZ_FALSE);
6651     return MZ_FALSE;
6652   }
6653 
6654   pZip->m_total_files++;
6655   pZip->m_archive_size = cur_dst_file_ofs;
6656 
6657   return MZ_TRUE;
6658 }
6659 
mz_zip_writer_finalize_archive(mz_zip_archive * pZip)6660 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
6661   mz_zip_internal_state *pState;
6662   mz_uint64 central_dir_ofs, central_dir_size;
6663   mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
6664 
6665   if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6666     return MZ_FALSE;
6667 
6668   pState = pZip->m_pState;
6669 
6670   // no zip64 support yet
6671   if ((pZip->m_total_files > 0xFFFF) ||
6672       ((pZip->m_archive_size + pState->m_central_dir.m_size +
6673         MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6674     return MZ_FALSE;
6675 
6676   central_dir_ofs = 0;
6677   central_dir_size = 0;
6678   if (pZip->m_total_files) {
6679     // Write central directory
6680     central_dir_ofs = pZip->m_archive_size;
6681     central_dir_size = pState->m_central_dir.m_size;
6682     pZip->m_central_directory_file_ofs = central_dir_ofs;
6683     if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
6684                        pState->m_central_dir.m_p,
6685                        (size_t)central_dir_size) != central_dir_size)
6686       return MZ_FALSE;
6687     pZip->m_archive_size += central_dir_size;
6688   }
6689 
6690   // Write end of central directory record
6691   MZ_CLEAR_OBJ(hdr);
6692   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
6693                 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
6694   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
6695                 pZip->m_total_files);
6696   MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
6697   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
6698   MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6699 
6700   if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
6701                      sizeof(hdr)) != sizeof(hdr))
6702     return MZ_FALSE;
6703 #ifndef MINIZ_NO_STDIO
6704   if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
6705     return MZ_FALSE;
6706 #endif // #ifndef MINIZ_NO_STDIO
6707 
6708   pZip->m_archive_size += sizeof(hdr);
6709 
6710   pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
6711   return MZ_TRUE;
6712 }
6713 
mz_zip_writer_finalize_heap_archive(mz_zip_archive * pZip,void ** pBuf,size_t * pSize)6714 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
6715                                             size_t *pSize) {
6716   if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
6717     return MZ_FALSE;
6718   if (pZip->m_pWrite != mz_zip_heap_write_func)
6719     return MZ_FALSE;
6720   if (!mz_zip_writer_finalize_archive(pZip))
6721     return MZ_FALSE;
6722 
6723   *pBuf = pZip->m_pState->m_pMem;
6724   *pSize = pZip->m_pState->m_mem_size;
6725   pZip->m_pState->m_pMem = NULL;
6726   pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6727   return MZ_TRUE;
6728 }
6729 
mz_zip_writer_end(mz_zip_archive * pZip)6730 mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
6731   mz_zip_internal_state *pState;
6732   mz_bool status = MZ_TRUE;
6733   if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
6734       ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
6735        (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
6736     return MZ_FALSE;
6737 
6738   pState = pZip->m_pState;
6739   pZip->m_pState = NULL;
6740   mz_zip_array_clear(pZip, &pState->m_central_dir);
6741   mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
6742   mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
6743 
6744 #ifndef MINIZ_NO_STDIO
6745   if (pState->m_pFile) {
6746     MZ_FCLOSE(pState->m_pFile);
6747     pState->m_pFile = NULL;
6748   }
6749 #endif // #ifndef MINIZ_NO_STDIO
6750 
6751   if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
6752     pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
6753     pState->m_pMem = NULL;
6754   }
6755 
6756   pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6757   pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
6758   return status;
6759 }
6760 
6761 #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)6762 mz_bool mz_zip_add_mem_to_archive_file_in_place(
6763     const char *pZip_filename, const char *pArchive_name, const void *pBuf,
6764     size_t buf_size, const void *pComment, mz_uint16 comment_size,
6765     mz_uint level_and_flags) {
6766   mz_bool status, created_new_archive = MZ_FALSE;
6767   mz_zip_archive zip_archive;
6768   struct MZ_FILE_STAT_STRUCT file_stat;
6769   MZ_CLEAR_OBJ(zip_archive);
6770   if ((int)level_and_flags < 0)
6771     level_and_flags = MZ_DEFAULT_LEVEL;
6772   if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
6773       ((comment_size) && (!pComment)) ||
6774       ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6775     return MZ_FALSE;
6776   if (!mz_zip_writer_validate_archive_name(pArchive_name))
6777     return MZ_FALSE;
6778   if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
6779     // Create a new archive.
6780     if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
6781       return MZ_FALSE;
6782     created_new_archive = MZ_TRUE;
6783   } else {
6784     // Append to an existing archive.
6785     if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6786                                  level_and_flags |
6787                                      MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6788       return MZ_FALSE;
6789     if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) {
6790       mz_zip_reader_end(&zip_archive);
6791       return MZ_FALSE;
6792     }
6793   }
6794   status =
6795       mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
6796                                pComment, comment_size, level_and_flags, 0, 0);
6797   // Always finalize, even if adding failed for some reason, so we have a valid
6798   // central directory. (This may not always succeed, but we can try.)
6799   if (!mz_zip_writer_finalize_archive(&zip_archive))
6800     status = MZ_FALSE;
6801   if (!mz_zip_writer_end(&zip_archive))
6802     status = MZ_FALSE;
6803   if ((!status) && (created_new_archive)) {
6804     // It's a new archive and something went wrong, so just delete it.
6805     int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6806     (void)ignoredStatus;
6807   }
6808   return status;
6809 }
6810 
mz_zip_extract_archive_file_to_heap(const char * pZip_filename,const char * pArchive_name,size_t * pSize,mz_uint flags)6811 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
6812                                           const char *pArchive_name,
6813                                           size_t *pSize, mz_uint flags) {
6814   int file_index;
6815   mz_zip_archive zip_archive;
6816   void *p = NULL;
6817 
6818   if (pSize)
6819     *pSize = 0;
6820 
6821   if ((!pZip_filename) || (!pArchive_name))
6822     return NULL;
6823 
6824   MZ_CLEAR_OBJ(zip_archive);
6825   if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6826                                flags |
6827                                    MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6828     return NULL;
6829 
6830   if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL,
6831                                               flags)) >= 0)
6832     p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6833 
6834   mz_zip_reader_end(&zip_archive);
6835   return p;
6836 }
6837 
6838 #endif // #ifndef MINIZ_NO_STDIO
6839 
6840 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
6841 
6842 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
6843 
6844 #ifdef __cplusplus
6845 }
6846 #endif
6847 
6848 #endif // MINIZ_HEADER_FILE_ONLY
6849 
6850 /*
6851   This is free and unencumbered software released into the public domain.
6852 
6853   Anyone is free to copy, modify, publish, use, compile, sell, or
6854   distribute this software, either in source code form or as a compiled
6855   binary, for any purpose, commercial or non-commercial, and by any
6856   means.
6857 
6858   In jurisdictions that recognize copyright laws, the author or authors
6859   of this software dedicate any and all copyright interest in the
6860   software to the public domain. We make this dedication for the benefit
6861   of the public at large and to the detriment of our heirs and
6862   successors. We intend this dedication to be an overt act of
6863   relinquishment in perpetuity of all present and future rights to this
6864   software under copyright law.
6865 
6866   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6867   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6868   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6869   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6870   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6871   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6872   OTHER DEALINGS IN THE SOFTWARE.
6873 
6874   For more information, please refer to <http://unlicense.org/>
6875 */
6876