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
326extern "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!
333typedef 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.
338void 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.
343mz_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.
348mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
349
350// Compression strategies.
351enum {
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. */
361typedef 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 purpsosely differ from zlib's:
404// items/size is size_t, not unsigned long.
405typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
406typedef void (*mz_free_func)(void *opaque, void *address);
407typedef 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).
419enum {
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.
429enum {
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.
445enum {
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
457struct mz_internal_state;
458
459// Compression/decompression stream struct.
460typedef 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
482typedef mz_stream *mz_streamp;
483
484// Returns the version string of miniz.c.
485const 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.
500int 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)
509int 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().
514int 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.)
531int 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.
537int 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.
542mz_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.
547int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
548 const unsigned char *pSource, mz_ulong source_len);
549int 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().
554mz_ulong mz_compressBound(mz_ulong source_len);
555
556// Initializes a decompressor.
557int 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).
563int 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).
588int mz_inflate(mz_streamp pStream, int flush);
589
590// Deinitializes a decompressor.
591int 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.
596int 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.
601const 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
608typedef unsigned char Byte;
609typedef unsigned int uInt;
610typedef mz_ulong uLong;
611typedef Byte Bytef;
612typedef uInt uIntf;
613typedef char charf;
614typedef int intf;
615typedef void *voidpf;
616typedef uLong uLongf;
617typedef void *voidp;
618typedef 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
684typedef unsigned char mz_uint8;
685typedef signed short mz_int16;
686typedef unsigned short mz_uint16;
687typedef unsigned int mz_uint32;
688typedef unsigned int mz_uint;
689typedef long long mz_int64;
690typedef unsigned long long mz_uint64;
691typedef 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
708enum {
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
714typedef 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
735typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
736 void *pBuf, size_t n);
737typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
738 const void *pBuf, size_t n);
739typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
740
741struct mz_zip_internal_state_tag;
742typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
743
744typedef 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
751typedef 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
761typedef 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
787typedef 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.
798mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
799 mz_uint32 flags);
800mz_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
804mz_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.
809mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
810
811// Returns detailed information about an archive file entry.
812mz_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.
816mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
817 mz_uint file_index);
818mz_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.
825mz_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.
831int 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.
835mz_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);
840mz_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.
845mz_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);
848mz_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.
853void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
854 size_t *pSize, mz_uint flags);
855void *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.
860mz_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);
864mz_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.
873mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
874 const char *pDst_filename, mz_uint flags);
875mz_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.
883mz_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.
890mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
891mz_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
896mz_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.
912mz_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.
921mz_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);
924mz_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.
936mz_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.
945mz_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.
953mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
954mz_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.
960mz_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.
968mz_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.
975void *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.
996enum {
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.
1013void *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))
1020size_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.
1027typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1028int 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
1032struct tinfl_decompressor_tag;
1033typedef struct tinfl_decompressor_tag tinfl_decompressor;
1034
1035// Max size of LZ dictionary.
1036#define TINFL_LZ_DICT_SIZE 32768
1037
1038// Return status.
1039typedef 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.
1062tinfl_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.
1069enum {
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
1078typedef 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
1089typedef mz_uint64 tinfl_bit_buf_t;
1090#define TINFL_BITBUF_SIZE (64)
1091#else
1092typedef mz_uint32 tinfl_bit_buf_t;
1093#define TINFL_BITBUF_SIZE (32)
1094#endif
1095
1096struct 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).
1118enum {
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).
1138enum {
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.
1160void *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.
1165size_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.
1182void *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);
1186void *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.
1191typedef 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.
1196mz_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
1200enum {
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
1214enum {
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
1224enum {
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.
1238typedef 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
1246typedef 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.
1254typedef 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.)
1290tdefl_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.
1297tdefl_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.
1304tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1305 size_t in_buf_size, tdefl_flush flush);
1306
1307tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1308mz_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
1318mz_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
1336typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1337typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1338typedef 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
1387extern "C" {
1388#endif
1389
1390// ------------------- zlib-style API's
1391
1392mz_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/
1420mz_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
1437void mz_free(void *p) { MZ_FREE(p); }
1438
1439#ifndef MINIZ_NO_ZLIB_APIS
1440
1441static 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}
1445static void def_free_func(void *opaque, void *address) {
1446 (void)opaque, (void)address;
1447 MZ_FREE(address);
1448}
1449static 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
1455const char *mz_version(void) { return MZ_VERSION; }
1456
1457int 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
1462int 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
1502int 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
1512int 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
1567int 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
1577mz_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
1585int 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
1614int 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
1620mz_ulong mz_compressBound(mz_ulong source_len) {
1621 return mz_deflateBound(NULL, source_len);
1622}
1623
1624typedef 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
1632int 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
1669int mz_inflateInit(mz_streamp pStream) {
1670 return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
1671}
1672
1673int 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
1796int 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
1806int 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
1836const 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
2000tinfl_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
2400common_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.
2444void *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
2484size_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
2499int 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.
2536static 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
2556static 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
2569static 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
2598static 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
2621static 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
2630static 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.
2641typedef struct {
2642 mz_uint16 m_key, m_sym_index;
2643} tdefl_sym_freq;
2644static 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.
2678static 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.
2724enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
2725static 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
2748static 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
2856static 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
2859static 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
2945static 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
2966static 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
2972static 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
3067static 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
3111static 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
3119static 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)
3251static MZ_FORCEINLINE void
3252tdefl_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
3307static MZ_FORCEINLINE void
3308tdefl_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
3356static 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
3535static 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
3547static MZ_FORCEINLINE void
3548tdefl_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
3577static 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
3720static 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
3741tdefl_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
3813tdefl_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
3819tdefl_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
3857tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
3858 return d->m_prev_return_status;
3859}
3860
3861mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
3862
3863mz_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
3882typedef struct {
3883 size_t m_size, m_capacity;
3884 mz_uint8 *m_pBuf;
3885 mz_bool m_expandable;
3886} tdefl_output_buffer;
3887
3888static 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
3911void *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
3927size_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
3943static 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).
3949mz_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.
3984void *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}
4093void *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
4120static wchar_t* str2wstr(const char *str) {
4121 int len = strlen(str) + 1;
4122 wchar_t* wstr = malloc(len * sizeof(wchar_t));
4123 MultiByteToWideChar(CP_UTF8, 0, str, len * sizeof(char), wstr, len);
4124 return wstr;
4125}
4126
4127static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4128 FILE *pFile = NULL;
4129
4130 wchar_t* wFilename = str2wstr(pFilename);
4131 wchar_t* wMode = str2wstr(pMode);
4132 _wfopen_s(&pFile, wFilename, wMode);
4133 free(wFilename);
4134 free(wMode);
4135
4136 return pFile;
4137}
4138
4139static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4140 FILE *pFile = NULL;
4141
4142 wchar_t* wPath = str2wstr(pPath);
4143 wchar_t* wMode = str2wstr(pMode);
4144 int res = _wfreopen_s(&pFile, wPath, wMode, pStream);
4145 free(wPath);
4146 free(wMode);
4147
4148 if (res)
4149 return NULL;
4150
4151 return pFile;
4152}
4153
4154#ifndef MINIZ_NO_TIME
4155#include <sys/utime.h>
4156#endif
4157#define MZ_FILE FILE
4158#define MZ_FOPEN mz_fopen
4159#define MZ_FCLOSE fclose
4160#define MZ_FREAD fread
4161#define MZ_FWRITE fwrite
4162#define MZ_FTELL64 _ftelli64
4163#define MZ_FSEEK64 _fseeki64
4164#define MZ_FILE_STAT_STRUCT _stat
4165#define MZ_FILE_STAT _stat
4166#define MZ_FFLUSH fflush
4167#define MZ_FREOPEN mz_freopen
4168#define MZ_DELETE_FILE remove
4169#elif defined(__MINGW32__)
4170#ifndef MINIZ_NO_TIME
4171#include <sys/utime.h>
4172#endif
4173#define MZ_FILE FILE
4174#define MZ_FOPEN(f, m) mz_fopen
4175#define MZ_FCLOSE fclose
4176#define MZ_FREAD fread
4177#define MZ_FWRITE fwrite
4178#define MZ_FTELL64 ftell
4179#define MZ_FSEEK64 fseek
4180#define MZ_FILE_STAT_STRUCT _stat
4181#define MZ_FILE_STAT _stat
4182#define MZ_FFLUSH fflush
4183#define MZ_FREOPEN(f, m, s) mz_freopen
4184#define MZ_DELETE_FILE remove
4185#elif defined(__TINYC__)
4186#ifndef MINIZ_NO_TIME
4187#include <sys/utime.h>
4188#endif
4189#define MZ_FILE FILE
4190#define MZ_FOPEN(f, m) fopen(f, m)
4191#define MZ_FCLOSE fclose
4192#define MZ_FREAD fread
4193#define MZ_FWRITE fwrite
4194#define MZ_FTELL64 ftell
4195#define MZ_FSEEK64 fseek
4196#define MZ_FILE_STAT_STRUCT stat
4197#define MZ_FILE_STAT stat
4198#define MZ_FFLUSH fflush
4199#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4200#define MZ_DELETE_FILE remove
4201#elif defined(__GNUC__) && _LARGEFILE64_SOURCE
4202#ifndef MINIZ_NO_TIME
4203#include <utime.h>
4204#endif
4205#define MZ_FILE FILE
4206#define MZ_FOPEN(f, m) fopen64(f, m)
4207#define MZ_FCLOSE fclose
4208#define MZ_FREAD fread
4209#define MZ_FWRITE fwrite
4210#define MZ_FTELL64 ftello64
4211#define MZ_FSEEK64 fseeko64
4212#define MZ_FILE_STAT_STRUCT stat64
4213#define MZ_FILE_STAT stat64
4214#define MZ_FFLUSH fflush
4215#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4216#define MZ_DELETE_FILE remove
4217#else
4218#ifndef MINIZ_NO_TIME
4219#include <utime.h>
4220#endif
4221#define MZ_FILE FILE
4222#define MZ_FOPEN(f, m) fopen(f, m)
4223#define MZ_FCLOSE fclose
4224#define MZ_FREAD fread
4225#define MZ_FWRITE fwrite
4226#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L
4227#define MZ_FTELL64 ftello
4228#define MZ_FSEEK64 fseeko
4229#else
4230#define MZ_FTELL64 ftell
4231#define MZ_FSEEK64 fseek
4232#endif
4233#define MZ_FILE_STAT_STRUCT stat
4234#define MZ_FILE_STAT stat
4235#define MZ_FFLUSH fflush
4236#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4237#define MZ_DELETE_FILE remove
4238#endif // #ifdef _MSC_VER
4239#endif // #ifdef MINIZ_NO_STDIO
4240
4241#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4242
4243// Various ZIP archive enums. To completely avoid cross platform compiler
4244// alignment and platform endian issues, miniz.c doesn't use structs for any of
4245// this stuff.
4246enum {
4247 // ZIP archive identifiers and record sizes
4248 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
4249 MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
4250 MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
4251 MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
4252 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
4253 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
4254
4255 /* ZIP64 archive identifier and record sizes */
4256 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
4257 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
4258 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
4259 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
4260 MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
4261 MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
4262 MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
4263 MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
4264
4265 // Central directory header record offsets
4266 MZ_ZIP_CDH_SIG_OFS = 0,
4267 MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
4268 MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
4269 MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
4270 MZ_ZIP_CDH_METHOD_OFS = 10,
4271 MZ_ZIP_CDH_FILE_TIME_OFS = 12,
4272 MZ_ZIP_CDH_FILE_DATE_OFS = 14,
4273 MZ_ZIP_CDH_CRC32_OFS = 16,
4274 MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
4275 MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
4276 MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
4277 MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
4278 MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
4279 MZ_ZIP_CDH_DISK_START_OFS = 34,
4280 MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
4281 MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
4282 MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
4283 // Local directory header offsets
4284 MZ_ZIP_LDH_SIG_OFS = 0,
4285 MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
4286 MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
4287 MZ_ZIP_LDH_METHOD_OFS = 8,
4288 MZ_ZIP_LDH_FILE_TIME_OFS = 10,
4289 MZ_ZIP_LDH_FILE_DATE_OFS = 12,
4290 MZ_ZIP_LDH_CRC32_OFS = 14,
4291 MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
4292 MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
4293 MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
4294 MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
4295 // End of central directory offsets
4296 MZ_ZIP_ECDH_SIG_OFS = 0,
4297 MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
4298 MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
4299 MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
4300 MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
4301 MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
4302 MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
4303 MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
4304
4305 /* ZIP64 End of central directory locator offsets */
4306 MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
4307 MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
4308 MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
4309 MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
4310
4311 /* ZIP64 End of central directory header offsets */
4312 MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
4313 MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
4314 MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
4315 MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
4316 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
4317 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
4318 MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
4319 MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
4320 MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
4321 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
4322 MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
4323 MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
4324 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
4325 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
4326 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
4327 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
4328 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
4329};
4330
4331typedef struct {
4332 void *m_p;
4333 size_t m_size, m_capacity;
4334 mz_uint m_element_size;
4335} mz_zip_array;
4336
4337struct mz_zip_internal_state_tag {
4338 mz_zip_array m_central_dir;
4339 mz_zip_array m_central_dir_offsets;
4340 mz_zip_array m_sorted_central_dir_offsets;
4341
4342 /* The flags passed in when the archive is initially opened. */
4343 uint32_t m_init_flags;
4344
4345 /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
4346 */
4347 mz_bool m_zip64;
4348
4349 /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
4350 * will also be slammed to true too, even if we didn't find a zip64 end of
4351 * central dir header, etc.) */
4352 mz_bool m_zip64_has_extended_info_fields;
4353
4354 /* These fields are used by the file, FILE, memory, and memory/heap read/write
4355 * helpers. */
4356 MZ_FILE *m_pFile;
4357 mz_uint64 m_file_archive_start_ofs;
4358
4359 void *m_pMem;
4360 size_t m_mem_size;
4361 size_t m_mem_capacity;
4362};
4363
4364#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) \
4365 (array_ptr)->m_element_size = element_size
4366#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \
4367 ((element_type *)((array_ptr)->m_p))[index]
4368
4369static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
4370 mz_zip_array *pArray) {
4371 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
4372 memset(pArray, 0, sizeof(mz_zip_array));
4373}
4374
4375static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
4376 mz_zip_array *pArray,
4377 size_t min_new_capacity,
4378 mz_uint growing) {
4379 void *pNew_p;
4380 size_t new_capacity = min_new_capacity;
4381 MZ_ASSERT(pArray->m_element_size);
4382 if (pArray->m_capacity >= min_new_capacity)
4383 return MZ_TRUE;
4384 if (growing) {
4385 new_capacity = MZ_MAX(1, pArray->m_capacity);
4386 while (new_capacity < min_new_capacity)
4387 new_capacity *= 2;
4388 }
4389 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
4390 pArray->m_element_size, new_capacity)))
4391 return MZ_FALSE;
4392 pArray->m_p = pNew_p;
4393 pArray->m_capacity = new_capacity;
4394 return MZ_TRUE;
4395}
4396
4397static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
4398 mz_zip_array *pArray,
4399 size_t new_capacity,
4400 mz_uint growing) {
4401 if (new_capacity > pArray->m_capacity) {
4402 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
4403 return MZ_FALSE;
4404 }
4405 return MZ_TRUE;
4406}
4407
4408static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
4409 mz_zip_array *pArray,
4410 size_t new_size,
4411 mz_uint growing) {
4412 if (new_size > pArray->m_capacity) {
4413 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
4414 return MZ_FALSE;
4415 }
4416 pArray->m_size = new_size;
4417 return MZ_TRUE;
4418}
4419
4420static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
4421 mz_zip_array *pArray,
4422 size_t n) {
4423 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
4424}
4425
4426static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
4427 mz_zip_array *pArray,
4428 const void *pElements,
4429 size_t n) {
4430 if (0 == n)
4431 return MZ_TRUE;
4432 if (!pElements)
4433 return MZ_FALSE;
4434
4435 size_t orig_size = pArray->m_size;
4436 if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
4437 return MZ_FALSE;
4438 memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
4439 pElements, n * pArray->m_element_size);
4440 return MZ_TRUE;
4441}
4442
4443#ifndef MINIZ_NO_TIME
4444static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
4445 struct tm tm;
4446 memset(&tm, 0, sizeof(tm));
4447 tm.tm_isdst = -1;
4448 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
4449 tm.tm_mon = ((dos_date >> 5) & 15) - 1;
4450 tm.tm_mday = dos_date & 31;
4451 tm.tm_hour = (dos_time >> 11) & 31;
4452 tm.tm_min = (dos_time >> 5) & 63;
4453 tm.tm_sec = (dos_time << 1) & 62;
4454 return mktime(&tm);
4455}
4456
4457#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4458static void mz_zip_time_t_to_dos_time(time_t time, mz_uint16 *pDOS_time,
4459 mz_uint16 *pDOS_date) {
4460#ifdef _MSC_VER
4461 struct tm tm_struct;
4462 struct tm *tm = &tm_struct;
4463 errno_t err = localtime_s(tm, &time);
4464 if (err) {
4465 *pDOS_date = 0;
4466 *pDOS_time = 0;
4467 return;
4468 }
4469#else
4470 struct tm *tm = localtime(&time);
4471#endif /* #ifdef _MSC_VER */
4472
4473 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
4474 ((tm->tm_sec) >> 1));
4475 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
4476 ((tm->tm_mon + 1) << 5) + tm->tm_mday);
4477}
4478#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
4479
4480#ifndef MINIZ_NO_STDIO
4481#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4482static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
4483 time_t *pTime) {
4484 struct MZ_FILE_STAT_STRUCT file_stat;
4485
4486 /* On Linux with x86 glibc, this call will fail on large files (I think >=
4487 * 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
4488 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
4489 return MZ_FALSE;
4490
4491 *pTime = file_stat.st_mtime;
4492
4493 return MZ_TRUE;
4494}
4495#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
4496
4497static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
4498 time_t modified_time) {
4499 struct utimbuf t;
4500
4501 memset(&t, 0, sizeof(t));
4502 t.actime = access_time;
4503 t.modtime = modified_time;
4504
4505 return !utime(pFilename, &t);
4506}
4507#endif /* #ifndef MINIZ_NO_STDIO */
4508#endif /* #ifndef MINIZ_NO_TIME */
4509
4510static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
4511 mz_zip_error err_num) {
4512 if (pZip)
4513 pZip->m_last_error = err_num;
4514 return MZ_FALSE;
4515}
4516
4517static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
4518 mz_uint32 flags) {
4519 (void)flags;
4520 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
4521 return MZ_FALSE;
4522
4523 if (!pZip->m_pAlloc)
4524 pZip->m_pAlloc = def_alloc_func;
4525 if (!pZip->m_pFree)
4526 pZip->m_pFree = def_free_func;
4527 if (!pZip->m_pRealloc)
4528 pZip->m_pRealloc = def_realloc_func;
4529
4530 pZip->m_zip_mode = MZ_ZIP_MODE_READING;
4531 pZip->m_archive_size = 0;
4532 pZip->m_central_directory_file_ofs = 0;
4533 pZip->m_total_files = 0;
4534
4535 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
4536 pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
4537 return MZ_FALSE;
4538 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
4539 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
4540 sizeof(mz_uint8));
4541 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
4542 sizeof(mz_uint32));
4543 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
4544 sizeof(mz_uint32));
4545 return MZ_TRUE;
4546}
4547
4548static MZ_FORCEINLINE mz_bool
4549mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
4550 const mz_zip_array *pCentral_dir_offsets,
4551 mz_uint l_index, mz_uint r_index) {
4552 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
4553 pCentral_dir_array, mz_uint8,
4554 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
4555 l_index)),
4556 *pE;
4557 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
4558 pCentral_dir_array, mz_uint8,
4559 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
4560 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
4561 r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4562 mz_uint8 l = 0, r = 0;
4563 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4564 pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4565 pE = pL + MZ_MIN(l_len, r_len);
4566 while (pL < pE) {
4567 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4568 break;
4569 pL++;
4570 pR++;
4571 }
4572 return (pL == pE) ? (l_len < r_len) : (l < r);
4573}
4574
4575#define MZ_SWAP_UINT32(a, b) \
4576 do { \
4577 mz_uint32 t = a; \
4578 a = b; \
4579 b = t; \
4580 } \
4581 MZ_MACRO_END
4582
4583// Heap sort of lowercased filenames, used to help accelerate plain central
4584// directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
4585// but it could allocate memory.)
4586static void
4587mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
4588 mz_zip_internal_state *pState = pZip->m_pState;
4589 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4590 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4591 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
4592 &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4593 const int size = pZip->m_total_files;
4594 int start = (size - 2) >> 1, end;
4595 while (start >= 0) {
4596 int child, root = start;
4597 for (;;) {
4598 if ((child = (root << 1) + 1) >= size)
4599 break;
4600 child +=
4601 (((child + 1) < size) &&
4602 (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4603 pIndices[child], pIndices[child + 1])));
4604 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4605 pIndices[root], pIndices[child]))
4606 break;
4607 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4608 root = child;
4609 }
4610 start--;
4611 }
4612
4613 end = size - 1;
4614 while (end > 0) {
4615 int child, root = 0;
4616 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
4617 for (;;) {
4618 if ((child = (root << 1) + 1) >= end)
4619 break;
4620 child +=
4621 (((child + 1) < end) &&
4622 mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4623 pIndices[child], pIndices[child + 1]));
4624 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4625 pIndices[root], pIndices[child]))
4626 break;
4627 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4628 root = child;
4629 }
4630 end--;
4631 }
4632}
4633
4634static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
4635 mz_uint32 record_sig,
4636 mz_uint32 record_size,
4637 mz_int64 *pOfs) {
4638 mz_int64 cur_file_ofs;
4639 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4640 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4641
4642 /* Basic sanity checks - reject files which are too small */
4643 if (pZip->m_archive_size < record_size)
4644 return MZ_FALSE;
4645
4646 /* Find the record by scanning the file from the end towards the beginning. */
4647 cur_file_ofs =
4648 MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
4649 for (;;) {
4650 int i,
4651 n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
4652
4653 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
4654 return MZ_FALSE;
4655
4656 for (i = n - 4; i >= 0; --i) {
4657 mz_uint s = MZ_READ_LE32(pBuf + i);
4658 if (s == record_sig) {
4659 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
4660 break;
4661 }
4662 }
4663
4664 if (i >= 0) {
4665 cur_file_ofs += i;
4666 break;
4667 }
4668
4669 /* Give up if we've searched the entire file, or we've gone back "too far"
4670 * (~64kb) */
4671 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
4672 (MZ_UINT16_MAX + record_size)))
4673 return MZ_FALSE;
4674
4675 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
4676 }
4677
4678 *pOfs = cur_file_ofs;
4679 return MZ_TRUE;
4680}
4681
4682static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
4683 mz_uint flags) {
4684 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
4685 cdir_disk_index = 0;
4686 mz_uint64 cdir_ofs = 0;
4687 mz_int64 cur_file_ofs = 0;
4688 const mz_uint8 *p;
4689
4690 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4691 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4692 mz_bool sort_central_dir =
4693 ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
4694 mz_uint32 zip64_end_of_central_dir_locator_u32
4695 [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
4696 sizeof(mz_uint32)];
4697 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
4698
4699 mz_uint32 zip64_end_of_central_dir_header_u32
4700 [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
4701 sizeof(mz_uint32)];
4702 mz_uint8 *pZip64_end_of_central_dir =
4703 (mz_uint8 *)zip64_end_of_central_dir_header_u32;
4704
4705 mz_uint64 zip64_end_of_central_dir_ofs = 0;
4706
4707 /* Basic sanity checks - reject files which are too small, and check the first
4708 * 4 bytes of the file to make sure a local header is there. */
4709 if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4710 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4711
4712 if (!mz_zip_reader_locate_header_sig(
4713 pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
4714 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
4715 return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
4716
4717 /* Read and verify the end of central directory record. */
4718 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
4719 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
4720 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4721 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4722
4723 if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
4724 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
4725 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4726
4727 if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
4728 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
4729 if (pZip->m_pRead(pZip->m_pIO_opaque,
4730 cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
4731 pZip64_locator,
4732 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
4733 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
4734 if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
4735 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
4736 zip64_end_of_central_dir_ofs = MZ_READ_LE64(
4737 pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
4738 if (zip64_end_of_central_dir_ofs >
4739 (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
4740 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4741
4742 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
4743 pZip64_end_of_central_dir,
4744 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
4745 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
4746 if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
4747 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
4748 pZip->m_pState->m_zip64 = MZ_TRUE;
4749 }
4750 }
4751 }
4752 }
4753 }
4754
4755 pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4756 cdir_entries_on_this_disk =
4757 MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4758 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
4759 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
4760 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
4761 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
4762
4763 if (pZip->m_pState->m_zip64) {
4764 mz_uint32 zip64_total_num_of_disks =
4765 MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
4766 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
4767 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4768 mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
4769 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4770 mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
4771 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
4772 mz_uint64 zip64_size_of_central_directory =
4773 MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
4774
4775 if (zip64_size_of_end_of_central_dir_record <
4776 (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
4777 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4778
4779 if (zip64_total_num_of_disks != 1U)
4780 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4781
4782 /* Check for miniz's practical limits */
4783 if (zip64_cdir_total_entries > MZ_UINT32_MAX)
4784 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4785
4786 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
4787
4788 if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
4789 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4790
4791 cdir_entries_on_this_disk =
4792 (mz_uint32)zip64_cdir_total_entries_on_this_disk;
4793
4794 /* Check for miniz's current practical limits (sorry, this should be enough
4795 * for millions of files) */
4796 if (zip64_size_of_central_directory > MZ_UINT32_MAX)
4797 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
4798
4799 cdir_size = (mz_uint32)zip64_size_of_central_directory;
4800
4801 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
4802 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
4803
4804 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
4805 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
4806
4807 cdir_ofs =
4808 MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
4809 }
4810
4811 if (pZip->m_total_files != cdir_entries_on_this_disk)
4812 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4813
4814 if (((num_this_disk | cdir_disk_index) != 0) &&
4815 ((num_this_disk != 1) || (cdir_disk_index != 1)))
4816 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4817
4818 if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
4819 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4820
4821 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
4822 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4823
4824 pZip->m_central_directory_file_ofs = cdir_ofs;
4825
4826 if (pZip->m_total_files) {
4827 mz_uint i, n;
4828 /* Read the entire central directory into a heap block, and allocate another
4829 * heap block to hold the unsorted central dir file record offsets, and
4830 * possibly another to hold the sorted indices. */
4831 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
4832 MZ_FALSE)) ||
4833 (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
4834 pZip->m_total_files, MZ_FALSE)))
4835 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4836
4837 if (sort_central_dir) {
4838 if (!mz_zip_array_resize(pZip,
4839 &pZip->m_pState->m_sorted_central_dir_offsets,
4840 pZip->m_total_files, MZ_FALSE))
4841 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4842 }
4843
4844 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
4845 pZip->m_pState->m_central_dir.m_p,
4846 cdir_size) != cdir_size)
4847 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4848
4849 /* Now create an index into the central directory file records, do some
4850 * basic sanity checking on each record */
4851 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
4852 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
4853 mz_uint total_header_size, disk_index, bit_flags, filename_size,
4854 ext_data_size;
4855 mz_uint64 comp_size, decomp_size, local_header_ofs;
4856
4857 if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
4858 (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
4859 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4860
4861 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
4862 i) =
4863 (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
4864
4865 if (sort_central_dir)
4866 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
4867 mz_uint32, i) = i;
4868
4869 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4870 decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4871 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4872 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4873 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4874
4875 if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
4876 (ext_data_size) &&
4877 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
4878 MZ_UINT32_MAX)) {
4879 /* Attempt to find zip64 extended information field in the entry's extra
4880 * data */
4881 mz_uint32 extra_size_remaining = ext_data_size;
4882
4883 if (extra_size_remaining) {
4884 const mz_uint8 *pExtra_data;
4885 void *buf = NULL;
4886
4887 if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
4888 n) {
4889 buf = MZ_MALLOC(ext_data_size);
4890 if (buf == NULL)
4891 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4892
4893 if (pZip->m_pRead(pZip->m_pIO_opaque,
4894 cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4895 filename_size,
4896 buf, ext_data_size) != ext_data_size) {
4897 MZ_FREE(buf);
4898 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4899 }
4900
4901 pExtra_data = (mz_uint8 *)buf;
4902 } else {
4903 pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
4904 }
4905
4906 do {
4907 mz_uint32 field_id;
4908 mz_uint32 field_data_size;
4909
4910 if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
4911 MZ_FREE(buf);
4912 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4913 }
4914
4915 field_id = MZ_READ_LE16(pExtra_data);
4916 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4917
4918 if ((field_data_size + sizeof(mz_uint16) * 2) >
4919 extra_size_remaining) {
4920 MZ_FREE(buf);
4921 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4922 }
4923
4924 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
4925 /* Ok, the archive didn't have any zip64 headers but it uses a
4926 * zip64 extended information field so mark it as zip64 anyway
4927 * (this can occur with infozip's zip util when it reads
4928 * compresses files from stdin). */
4929 pZip->m_pState->m_zip64 = MZ_TRUE;
4930 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
4931 break;
4932 }
4933
4934 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4935 extra_size_remaining =
4936 extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4937 } while (extra_size_remaining);
4938
4939 MZ_FREE(buf);
4940 }
4941 }
4942
4943 /* I've seen archives that aren't marked as zip64 that uses zip64 ext
4944 * data, argh */
4945 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
4946 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
4947 (decomp_size != comp_size)) ||
4948 (decomp_size && !comp_size))
4949 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4950 }
4951
4952 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
4953 if ((disk_index == MZ_UINT16_MAX) ||
4954 ((disk_index != num_this_disk) && (disk_index != 1)))
4955 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4956
4957 if (comp_size != MZ_UINT32_MAX) {
4958 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
4959 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
4960 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4961 }
4962
4963 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4964 if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
4965 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4966
4967 if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4968 MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
4969 MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
4970 MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
4971 n)
4972 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4973
4974 n -= total_header_size;
4975 p += total_header_size;
4976 }
4977 }
4978
4979 if (sort_central_dir)
4980 mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
4981
4982 return MZ_TRUE;
4983}
4984
4985mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
4986 mz_uint32 flags) {
4987 if ((!pZip) || (!pZip->m_pRead))
4988 return MZ_FALSE;
4989 if (!mz_zip_reader_init_internal(pZip, flags))
4990 return MZ_FALSE;
4991 pZip->m_archive_size = size;
4992 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
4993 mz_zip_reader_end(pZip);
4994 return MZ_FALSE;
4995 }
4996 return MZ_TRUE;
4997}
4998
4999static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
5000 void *pBuf, size_t n) {
5001 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5002 size_t s = (file_ofs >= pZip->m_archive_size)
5003 ? 0
5004 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
5005 memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
5006 return s;
5007}
5008
5009mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
5010 size_t size, mz_uint32 flags) {
5011 if (!mz_zip_reader_init_internal(pZip, flags))
5012 return MZ_FALSE;
5013 pZip->m_archive_size = size;
5014 pZip->m_pRead = mz_zip_mem_read_func;
5015 pZip->m_pIO_opaque = pZip;
5016#ifdef __cplusplus
5017 pZip->m_pState->m_pMem = const_cast<void *>(pMem);
5018#else
5019 pZip->m_pState->m_pMem = (void *)pMem;
5020#endif
5021 pZip->m_pState->m_mem_size = size;
5022 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5023 mz_zip_reader_end(pZip);
5024 return MZ_FALSE;
5025 }
5026 return MZ_TRUE;
5027}
5028
5029#ifndef MINIZ_NO_STDIO
5030static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5031 void *pBuf, size_t n) {
5032 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5033 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5034 if (((mz_int64)file_ofs < 0) ||
5035 (((cur_ofs != (mz_int64)file_ofs)) &&
5036 (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5037 return 0;
5038 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5039}
5040
5041mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5042 mz_uint32 flags) {
5043 mz_uint64 file_size;
5044 MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
5045 if (!pFile)
5046 return MZ_FALSE;
5047 if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5048 MZ_FCLOSE(pFile);
5049 return MZ_FALSE;
5050 }
5051 file_size = MZ_FTELL64(pFile);
5052 if (!mz_zip_reader_init_internal(pZip, flags)) {
5053 MZ_FCLOSE(pFile);
5054 return MZ_FALSE;
5055 }
5056 pZip->m_pRead = mz_zip_file_read_func;
5057 pZip->m_pIO_opaque = pZip;
5058 pZip->m_pState->m_pFile = pFile;
5059 pZip->m_archive_size = file_size;
5060 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5061 mz_zip_reader_end(pZip);
5062 return MZ_FALSE;
5063 }
5064 return MZ_TRUE;
5065}
5066#endif // #ifndef MINIZ_NO_STDIO
5067
5068mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5069 return pZip ? pZip->m_total_files : 0;
5070}
5071
5072static MZ_FORCEINLINE const mz_uint8 *
5073mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) {
5074 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) ||
5075 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5076 return NULL;
5077 return &MZ_ZIP_ARRAY_ELEMENT(
5078 &pZip->m_pState->m_central_dir, mz_uint8,
5079 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5080 file_index));
5081}
5082
5083mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
5084 mz_uint file_index) {
5085 mz_uint m_bit_flag;
5086 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5087 if (!p)
5088 return MZ_FALSE;
5089 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5090 return (m_bit_flag & 1);
5091}
5092
5093mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
5094 mz_uint file_index) {
5095 mz_uint filename_len, external_attr;
5096 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5097 if (!p)
5098 return MZ_FALSE;
5099
5100 // First see if the filename ends with a '/' character.
5101 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5102 if (filename_len) {
5103 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
5104 return MZ_TRUE;
5105 }
5106
5107 // Bugfix: This code was also checking if the internal attribute was non-zero,
5108 // which wasn't correct. Most/all zip writers (hopefully) set DOS
5109 // file/directory attributes in the low 16-bits, so check for the DOS
5110 // directory flag and ignore the source OS ID in the created by field.
5111 // FIXME: Remove this check? Is it necessary - we already check the filename.
5112 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5113 if ((external_attr & 0x10) != 0)
5114 return MZ_TRUE;
5115
5116 return MZ_FALSE;
5117}
5118
5119mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
5120 mz_zip_archive_file_stat *pStat) {
5121 mz_uint n;
5122 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5123 if ((!p) || (!pStat))
5124 return MZ_FALSE;
5125
5126 // Unpack the central directory record.
5127 pStat->m_file_index = file_index;
5128 pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
5129 &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
5130 pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
5131 pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
5132 pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5133 pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
5134#ifndef MINIZ_NO_TIME
5135 pStat->m_time =
5136 mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
5137 MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
5138#endif
5139 pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
5140 pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5141 pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5142 pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
5143 pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5144 pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5145
5146 // Copy as much of the filename and comment as possible.
5147 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5148 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
5149 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5150 pStat->m_filename[n] = '\0';
5151
5152 n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5153 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
5154 pStat->m_comment_size = n;
5155 memcpy(pStat->m_comment,
5156 p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5157 MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5158 MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5159 n);
5160 pStat->m_comment[n] = '\0';
5161
5162 return MZ_TRUE;
5163}
5164
5165mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
5166 char *pFilename, mz_uint filename_buf_size) {
5167 mz_uint n;
5168 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5169 if (!p) {
5170 if (filename_buf_size)
5171 pFilename[0] = '\0';
5172 return 0;
5173 }
5174 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5175 if (filename_buf_size) {
5176 n = MZ_MIN(n, filename_buf_size - 1);
5177 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5178 pFilename[n] = '\0';
5179 }
5180 return n + 1;
5181}
5182
5183static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA,
5184 const char *pB,
5185 mz_uint len,
5186 mz_uint flags) {
5187 mz_uint i;
5188 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
5189 return 0 == memcmp(pA, pB, len);
5190 for (i = 0; i < len; ++i)
5191 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
5192 return MZ_FALSE;
5193 return MZ_TRUE;
5194}
5195
5196static MZ_FORCEINLINE int
5197mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array,
5198 const mz_zip_array *pCentral_dir_offsets,
5199 mz_uint l_index, const char *pR, mz_uint r_len) {
5200 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5201 pCentral_dir_array, mz_uint8,
5202 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5203 l_index)),
5204 *pE;
5205 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5206 mz_uint8 l = 0, r = 0;
5207 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5208 pE = pL + MZ_MIN(l_len, r_len);
5209 while (pL < pE) {
5210 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
5211 break;
5212 pL++;
5213 pR++;
5214 }
5215 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
5216}
5217
5218static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip,
5219 const char *pFilename) {
5220 mz_zip_internal_state *pState = pZip->m_pState;
5221 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5222 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5223 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
5224 &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
5225 const int size = pZip->m_total_files;
5226 const mz_uint filename_len = (mz_uint)strlen(pFilename);
5227 int l = 0, h = size - 1;
5228 while (l <= h) {
5229 int m = (l + h) >> 1, file_index = pIndices[m],
5230 comp =
5231 mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets,
5232 file_index, pFilename, filename_len);
5233 if (!comp)
5234 return file_index;
5235 else if (comp < 0)
5236 l = m + 1;
5237 else
5238 h = m - 1;
5239 }
5240 return -1;
5241}
5242
5243int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
5244 const char *pComment, mz_uint flags) {
5245 mz_uint file_index;
5246 size_t name_len, comment_len;
5247 if ((!pZip) || (!pZip->m_pState) || (!pName) ||
5248 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5249 return -1;
5250 if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
5251 (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
5252 return mz_zip_reader_locate_file_binary_search(pZip, pName);
5253 name_len = strlen(pName);
5254 if (name_len > 0xFFFF)
5255 return -1;
5256 comment_len = pComment ? strlen(pComment) : 0;
5257 if (comment_len > 0xFFFF)
5258 return -1;
5259 for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
5260 const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
5261 &pZip->m_pState->m_central_dir, mz_uint8,
5262 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5263 file_index));
5264 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5265 const char *pFilename =
5266 (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5267 if (filename_len < name_len)
5268 continue;
5269 if (comment_len) {
5270 mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5271 file_comment_len =
5272 MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5273 const char *pFile_comment = pFilename + filename_len + file_extra_len;
5274 if ((file_comment_len != comment_len) ||
5275 (!mz_zip_reader_string_equal(pComment, pFile_comment,
5276 file_comment_len, flags)))
5277 continue;
5278 }
5279 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
5280 int ofs = filename_len - 1;
5281 do {
5282 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
5283 (pFilename[ofs] == ':'))
5284 break;
5285 } while (--ofs >= 0);
5286 ofs++;
5287 pFilename += ofs;
5288 filename_len -= ofs;
5289 }
5290 if ((filename_len == name_len) &&
5291 (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
5292 return file_index;
5293 }
5294 return -1;
5295}
5296
5297mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
5298 mz_uint file_index, void *pBuf,
5299 size_t buf_size, mz_uint flags,
5300 void *pUser_read_buf,
5301 size_t user_read_buf_size) {
5302 int status = TINFL_STATUS_DONE;
5303 mz_uint64 needed_size, cur_file_ofs, comp_remaining,
5304 out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
5305 mz_zip_archive_file_stat file_stat;
5306 void *pRead_buf;
5307 mz_uint32
5308 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5309 sizeof(mz_uint32)];
5310 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5311 tinfl_decompressor inflator;
5312
5313 if ((buf_size) && (!pBuf))
5314 return MZ_FALSE;
5315
5316 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5317 return MZ_FALSE;
5318
5319 // Empty file, or a directory (but not always a directory - I've seen odd zips
5320 // with directories that have compressed data which inflates to 0 bytes)
5321 if (!file_stat.m_comp_size)
5322 return MZ_TRUE;
5323
5324 // Entry is a subdirectory (I've seen old zips with dir entries which have
5325 // compressed deflate data which inflates to 0 bytes, but these entries claim
5326 // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5327 // case - should it fail instead?
5328 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5329 return MZ_TRUE;
5330
5331 // Encryption and patch files are not supported.
5332 if (file_stat.m_bit_flag & (1 | 32))
5333 return MZ_FALSE;
5334
5335 // This function only supports stored and deflate.
5336 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5337 (file_stat.m_method != MZ_DEFLATED))
5338 return MZ_FALSE;
5339
5340 // Ensure supplied output buffer is large enough.
5341 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
5342 : file_stat.m_uncomp_size;
5343 if (buf_size < needed_size)
5344 return MZ_FALSE;
5345
5346 // Read and parse the local directory entry.
5347 cur_file_ofs = file_stat.m_local_header_ofs;
5348 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5349 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5350 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5351 return MZ_FALSE;
5352 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5353 return MZ_FALSE;
5354
5355 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5356 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5357 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5358 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5359 return MZ_FALSE;
5360
5361 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5362 // The file is stored or the caller has requested the compressed data.
5363 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5364 (size_t)needed_size) != needed_size)
5365 return MZ_FALSE;
5366 return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) ||
5367 (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5368 (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
5369 }
5370
5371 // Decompress the file either directly from memory or from a file input
5372 // buffer.
5373 tinfl_init(&inflator);
5374
5375 if (pZip->m_pState->m_pMem) {
5376 // Read directly from the archive in memory.
5377 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5378 read_buf_size = read_buf_avail = file_stat.m_comp_size;
5379 comp_remaining = 0;
5380 } else if (pUser_read_buf) {
5381 // Use a user provided read buffer.
5382 if (!user_read_buf_size)
5383 return MZ_FALSE;
5384 pRead_buf = (mz_uint8 *)pUser_read_buf;
5385 read_buf_size = user_read_buf_size;
5386 read_buf_avail = 0;
5387 comp_remaining = file_stat.m_comp_size;
5388 } else {
5389 // Temporarily allocate a read buffer.
5390 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5391#ifdef _MSC_VER
5392 if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5393 (read_buf_size > 0x7FFFFFFF))
5394#else
5395 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
5396#endif
5397 return MZ_FALSE;
5398 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5399 (size_t)read_buf_size)))
5400 return MZ_FALSE;
5401 read_buf_avail = 0;
5402 comp_remaining = file_stat.m_comp_size;
5403 }
5404
5405 do {
5406 size_t in_buf_size,
5407 out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
5408 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5409 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5410 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5411 (size_t)read_buf_avail) != read_buf_avail) {
5412 status = TINFL_STATUS_FAILED;
5413 break;
5414 }
5415 cur_file_ofs += read_buf_avail;
5416 comp_remaining -= read_buf_avail;
5417 read_buf_ofs = 0;
5418 }
5419 in_buf_size = (size_t)read_buf_avail;
5420 status = tinfl_decompress(
5421 &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5422 (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
5423 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
5424 (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
5425 read_buf_avail -= in_buf_size;
5426 read_buf_ofs += in_buf_size;
5427 out_buf_ofs += out_buf_size;
5428 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
5429
5430 if (status == TINFL_STATUS_DONE) {
5431 // Make sure the entire file was decompressed, and check its CRC.
5432 if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5433 (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5434 (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
5435 status = TINFL_STATUS_FAILED;
5436 }
5437
5438 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
5439 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5440
5441 return status == TINFL_STATUS_DONE;
5442}
5443
5444mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
5445 mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
5446 mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
5447 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5448 if (file_index < 0)
5449 return MZ_FALSE;
5450 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5451 flags, pUser_read_buf,
5452 user_read_buf_size);
5453}
5454
5455mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
5456 void *pBuf, size_t buf_size,
5457 mz_uint flags) {
5458 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5459 flags, NULL, 0);
5460}
5461
5462mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
5463 const char *pFilename, void *pBuf,
5464 size_t buf_size, mz_uint flags) {
5465 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
5466 buf_size, flags, NULL, 0);
5467}
5468
5469void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
5470 size_t *pSize, mz_uint flags) {
5471 mz_uint64 comp_size, uncomp_size, alloc_size;
5472 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5473 void *pBuf;
5474
5475 if (pSize)
5476 *pSize = 0;
5477 if (!p)
5478 return NULL;
5479
5480 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5481 uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5482
5483 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
5484#ifdef _MSC_VER
5485 if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5486#else
5487 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5488#endif
5489 return NULL;
5490 if (NULL ==
5491 (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
5492 return NULL;
5493
5494 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
5495 flags)) {
5496 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
5497 return NULL;
5498 }
5499
5500 if (pSize)
5501 *pSize = (size_t)alloc_size;
5502 return pBuf;
5503}
5504
5505void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
5506 const char *pFilename, size_t *pSize,
5507 mz_uint flags) {
5508 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5509 if (file_index < 0) {
5510 if (pSize)
5511 *pSize = 0;
5512 return MZ_FALSE;
5513 }
5514 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
5515}
5516
5517mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
5518 mz_uint file_index,
5519 mz_file_write_func pCallback,
5520 void *pOpaque, mz_uint flags) {
5521 int status = TINFL_STATUS_DONE;
5522 mz_uint file_crc32 = MZ_CRC32_INIT;
5523 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
5524 out_buf_ofs = 0, cur_file_ofs;
5525 mz_zip_archive_file_stat file_stat;
5526 void *pRead_buf = NULL;
5527 void *pWrite_buf = NULL;
5528 mz_uint32
5529 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5530 sizeof(mz_uint32)];
5531 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5532
5533 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5534 return MZ_FALSE;
5535
5536 // Empty file, or a directory (but not always a directory - I've seen odd zips
5537 // with directories that have compressed data which inflates to 0 bytes)
5538 if (!file_stat.m_comp_size)
5539 return MZ_TRUE;
5540
5541 // Entry is a subdirectory (I've seen old zips with dir entries which have
5542 // compressed deflate data which inflates to 0 bytes, but these entries claim
5543 // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5544 // case - should it fail instead?
5545 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5546 return MZ_TRUE;
5547
5548 // Encryption and patch files are not supported.
5549 if (file_stat.m_bit_flag & (1 | 32))
5550 return MZ_FALSE;
5551
5552 // This function only supports stored and deflate.
5553 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5554 (file_stat.m_method != MZ_DEFLATED))
5555 return MZ_FALSE;
5556
5557 // Read and parse the local directory entry.
5558 cur_file_ofs = file_stat.m_local_header_ofs;
5559 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5560 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5561 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5562 return MZ_FALSE;
5563 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5564 return MZ_FALSE;
5565
5566 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5567 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5568 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5569 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5570 return MZ_FALSE;
5571
5572 // Decompress the file either directly from memory or from a file input
5573 // buffer.
5574 if (pZip->m_pState->m_pMem) {
5575 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5576 read_buf_size = read_buf_avail = file_stat.m_comp_size;
5577 comp_remaining = 0;
5578 } else {
5579 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5580 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5581 (size_t)read_buf_size)))
5582 return MZ_FALSE;
5583 read_buf_avail = 0;
5584 comp_remaining = file_stat.m_comp_size;
5585 }
5586
5587 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5588 // The file is stored or the caller has requested the compressed data.
5589 if (pZip->m_pState->m_pMem) {
5590#ifdef _MSC_VER
5591 if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5592 (file_stat.m_comp_size > 0xFFFFFFFF))
5593#else
5594 if (((sizeof(size_t) == sizeof(mz_uint32))) &&
5595 (file_stat.m_comp_size > 0xFFFFFFFF))
5596#endif
5597 return MZ_FALSE;
5598 if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5599 (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
5600 status = TINFL_STATUS_FAILED;
5601 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5602 file_crc32 =
5603 (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
5604 (size_t)file_stat.m_comp_size);
5605 // cur_file_ofs += file_stat.m_comp_size;
5606 out_buf_ofs += file_stat.m_comp_size;
5607 // comp_remaining = 0;
5608 } else {
5609 while (comp_remaining) {
5610 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5611 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5612 (size_t)read_buf_avail) != read_buf_avail) {
5613 status = TINFL_STATUS_FAILED;
5614 break;
5615 }
5616
5617 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5618 file_crc32 = (mz_uint32)mz_crc32(
5619 file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
5620
5621 if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5622 (size_t)read_buf_avail) != read_buf_avail) {
5623 status = TINFL_STATUS_FAILED;
5624 break;
5625 }
5626 cur_file_ofs += read_buf_avail;
5627 out_buf_ofs += read_buf_avail;
5628 comp_remaining -= read_buf_avail;
5629 }
5630 }
5631 } else {
5632 tinfl_decompressor inflator;
5633 tinfl_init(&inflator);
5634
5635 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5636 TINFL_LZ_DICT_SIZE)))
5637 status = TINFL_STATUS_FAILED;
5638 else {
5639 do {
5640 mz_uint8 *pWrite_buf_cur =
5641 (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5642 size_t in_buf_size,
5643 out_buf_size =
5644 TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5645 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5646 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5647 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5648 (size_t)read_buf_avail) != read_buf_avail) {
5649 status = TINFL_STATUS_FAILED;
5650 break;
5651 }
5652 cur_file_ofs += read_buf_avail;
5653 comp_remaining -= read_buf_avail;
5654 read_buf_ofs = 0;
5655 }
5656
5657 in_buf_size = (size_t)read_buf_avail;
5658 status = tinfl_decompress(
5659 &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5660 (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
5661 comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5662 read_buf_avail -= in_buf_size;
5663 read_buf_ofs += in_buf_size;
5664
5665 if (out_buf_size) {
5666 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
5667 out_buf_size) {
5668 status = TINFL_STATUS_FAILED;
5669 break;
5670 }
5671 file_crc32 =
5672 (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
5673 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
5674 status = TINFL_STATUS_FAILED;
5675 break;
5676 }
5677 }
5678 } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
5679 (status == TINFL_STATUS_HAS_MORE_OUTPUT));
5680 }
5681 }
5682
5683 if ((status == TINFL_STATUS_DONE) &&
5684 (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
5685 // Make sure the entire file was decompressed, and check its CRC.
5686 if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5687 (file_crc32 != file_stat.m_crc32))
5688 status = TINFL_STATUS_FAILED;
5689 }
5690
5691 if (!pZip->m_pState->m_pMem)
5692 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5693 if (pWrite_buf)
5694 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
5695
5696 return status == TINFL_STATUS_DONE;
5697}
5698
5699mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
5700 const char *pFilename,
5701 mz_file_write_func pCallback,
5702 void *pOpaque, mz_uint flags) {
5703 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5704 if (file_index < 0)
5705 return MZ_FALSE;
5706 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
5707 flags);
5708}
5709
5710#ifndef MINIZ_NO_STDIO
5711static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
5712 const void *pBuf, size_t n) {
5713 (void)ofs;
5714 return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5715}
5716
5717mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
5718 const char *pDst_filename,
5719 mz_uint flags) {
5720 mz_bool status;
5721 mz_zip_archive_file_stat file_stat;
5722 MZ_FILE *pFile;
5723 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5724 return MZ_FALSE;
5725
5726 pFile = MZ_FOPEN(pDst_filename, "wb");
5727 if (!pFile)
5728 return MZ_FALSE;
5729 status = mz_zip_reader_extract_to_callback(
5730 pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5731 if (MZ_FCLOSE(pFile) == EOF)
5732 return MZ_FALSE;
5733#ifndef MINIZ_NO_TIME
5734 if (status) {
5735 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5736 }
5737#endif
5738
5739 return status;
5740}
5741#endif // #ifndef MINIZ_NO_STDIO
5742
5743mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5744 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5745 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5746 return MZ_FALSE;
5747
5748 mz_zip_internal_state *pState = pZip->m_pState;
5749 pZip->m_pState = NULL;
5750 mz_zip_array_clear(pZip, &pState->m_central_dir);
5751 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5752 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5753
5754#ifndef MINIZ_NO_STDIO
5755 if (pState->m_pFile) {
5756 MZ_FCLOSE(pState->m_pFile);
5757 pState->m_pFile = NULL;
5758 }
5759#endif // #ifndef MINIZ_NO_STDIO
5760
5761 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5762
5763 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5764
5765 return MZ_TRUE;
5766}
5767
5768#ifndef MINIZ_NO_STDIO
5769mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
5770 const char *pArchive_filename,
5771 const char *pDst_filename,
5772 mz_uint flags) {
5773 int file_index =
5774 mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
5775 if (file_index < 0)
5776 return MZ_FALSE;
5777 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5778}
5779#endif
5780
5781// ------------------- .ZIP archive writing
5782
5783#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5784
5785static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5786 p[0] = (mz_uint8)v;
5787 p[1] = (mz_uint8)(v >> 8);
5788}
5789static void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
5790 p[0] = (mz_uint8)v;
5791 p[1] = (mz_uint8)(v >> 8);
5792 p[2] = (mz_uint8)(v >> 16);
5793 p[3] = (mz_uint8)(v >> 24);
5794}
5795#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5796#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5797
5798mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
5799 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
5800 (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5801 return MZ_FALSE;
5802
5803 if (pZip->m_file_offset_alignment) {
5804 // Ensure user specified file offset alignment is a power of 2.
5805 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5806 return MZ_FALSE;
5807 }
5808
5809 if (!pZip->m_pAlloc)
5810 pZip->m_pAlloc = def_alloc_func;
5811 if (!pZip->m_pFree)
5812 pZip->m_pFree = def_free_func;
5813 if (!pZip->m_pRealloc)
5814 pZip->m_pRealloc = def_realloc_func;
5815
5816 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5817 pZip->m_archive_size = existing_size;
5818 pZip->m_central_directory_file_ofs = 0;
5819 pZip->m_total_files = 0;
5820
5821 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5822 pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5823 return MZ_FALSE;
5824 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5825 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5826 sizeof(mz_uint8));
5827 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5828 sizeof(mz_uint32));
5829 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5830 sizeof(mz_uint32));
5831 return MZ_TRUE;
5832}
5833
5834static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
5835 const void *pBuf, size_t n) {
5836 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5837 mz_zip_internal_state *pState = pZip->m_pState;
5838 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5839
5840 if ((!n) ||
5841 ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5842 return 0;
5843
5844 if (new_size > pState->m_mem_capacity) {
5845 void *pNew_block;
5846 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5847 while (new_capacity < new_size)
5848 new_capacity *= 2;
5849 if (NULL == (pNew_block = pZip->m_pRealloc(
5850 pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5851 return 0;
5852 pState->m_pMem = pNew_block;
5853 pState->m_mem_capacity = new_capacity;
5854 }
5855 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5856 pState->m_mem_size = (size_t)new_size;
5857 return n;
5858}
5859
5860mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
5861 size_t size_to_reserve_at_beginning,
5862 size_t initial_allocation_size) {
5863 pZip->m_pWrite = mz_zip_heap_write_func;
5864 pZip->m_pIO_opaque = pZip;
5865 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5866 return MZ_FALSE;
5867 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
5868 size_to_reserve_at_beginning))) {
5869 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
5870 pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
5871 mz_zip_writer_end(pZip);
5872 return MZ_FALSE;
5873 }
5874 pZip->m_pState->m_mem_capacity = initial_allocation_size;
5875 }
5876 return MZ_TRUE;
5877}
5878
5879#ifndef MINIZ_NO_STDIO
5880static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
5881 const void *pBuf, size_t n) {
5882 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5883 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5884 if (((mz_int64)file_ofs < 0) ||
5885 (((cur_ofs != (mz_int64)file_ofs)) &&
5886 (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5887 return 0;
5888 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5889}
5890
5891mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
5892 mz_uint64 size_to_reserve_at_beginning) {
5893 MZ_FILE *pFile;
5894 pZip->m_pWrite = mz_zip_file_write_func;
5895 pZip->m_pIO_opaque = pZip;
5896 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5897 return MZ_FALSE;
5898 if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) {
5899 mz_zip_writer_end(pZip);
5900 return MZ_FALSE;
5901 }
5902 pZip->m_pState->m_pFile = pFile;
5903 if (size_to_reserve_at_beginning) {
5904 mz_uint64 cur_ofs = 0;
5905 char buf[4096];
5906 MZ_CLEAR_OBJ(buf);
5907 do {
5908 size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5909 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
5910 mz_zip_writer_end(pZip);
5911 return MZ_FALSE;
5912 }
5913 cur_ofs += n;
5914 size_to_reserve_at_beginning -= n;
5915 } while (size_to_reserve_at_beginning);
5916 }
5917 return MZ_TRUE;
5918}
5919#endif // #ifndef MINIZ_NO_STDIO
5920
5921mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
5922 const char *pFilename) {
5923 mz_zip_internal_state *pState;
5924 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5925 return MZ_FALSE;
5926 // No sense in trying to write to an archive that's already at the support max
5927 // size
5928 if ((pZip->m_total_files == 0xFFFF) ||
5929 ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5930 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
5931 return MZ_FALSE;
5932
5933 pState = pZip->m_pState;
5934
5935 if (pState->m_pFile) {
5936#ifdef MINIZ_NO_STDIO
5937 pFilename;
5938 return MZ_FALSE;
5939#else
5940 // Archive is being read from stdio - try to reopen as writable.
5941 if (pZip->m_pIO_opaque != pZip)
5942 return MZ_FALSE;
5943 if (!pFilename)
5944 return MZ_FALSE;
5945 pZip->m_pWrite = mz_zip_file_write_func;
5946 if (NULL ==
5947 (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
5948 // The mz_zip_archive is now in a bogus state because pState->m_pFile is
5949 // NULL, so just close it.
5950 mz_zip_reader_end(pZip);
5951 return MZ_FALSE;
5952 }
5953#endif // #ifdef MINIZ_NO_STDIO
5954 } else if (pState->m_pMem) {
5955 // Archive lives in a memory block. Assume it's from the heap that we can
5956 // resize using the realloc callback.
5957 if (pZip->m_pIO_opaque != pZip)
5958 return MZ_FALSE;
5959 pState->m_mem_capacity = pState->m_mem_size;
5960 pZip->m_pWrite = mz_zip_heap_write_func;
5961 }
5962 // Archive is being read via a user provided read function - make sure the
5963 // user has specified a write function too.
5964 else if (!pZip->m_pWrite)
5965 return MZ_FALSE;
5966
5967 // Start writing new files at the archive's current central directory
5968 // location.
5969 pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5970 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5971 pZip->m_central_directory_file_ofs = 0;
5972
5973 return MZ_TRUE;
5974}
5975
5976mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
5977 const void *pBuf, size_t buf_size,
5978 mz_uint level_and_flags) {
5979 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
5980 level_and_flags, 0, 0);
5981}
5982
5983typedef struct {
5984 mz_zip_archive *m_pZip;
5985 mz_uint64 m_cur_archive_file_ofs;
5986 mz_uint64 m_comp_size;
5987} mz_zip_writer_add_state;
5988
5989static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
5990 void *pUser) {
5991 mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
5992 if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
5993 pState->m_cur_archive_file_ofs, pBuf,
5994 len) != len)
5995 return MZ_FALSE;
5996 pState->m_cur_archive_file_ofs += len;
5997 pState->m_comp_size += len;
5998 return MZ_TRUE;
5999}
6000
6001static mz_bool mz_zip_writer_create_local_dir_header(
6002 mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6003 mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6004 mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6005 mz_uint16 dos_time, mz_uint16 dos_date) {
6006 (void)pZip;
6007 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6008 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
6009 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6010 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6011 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6012 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6013 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6014 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6015 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
6016 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6017 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6018 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6019 return MZ_TRUE;
6020}
6021
6022static mz_bool mz_zip_writer_create_central_dir_header(
6023 mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6024 mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
6025 mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
6026 mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6027 mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
6028 (void)pZip;
6029 mz_uint16 version_made_by = 10 * MZ_VER_MAJOR + MZ_VER_MINOR;
6030 version_made_by |= (MZ_PLATFORM << 8);
6031
6032 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6033 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6034 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, version_made_by);
6035 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6036 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6037 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6038 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6039 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6040 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6041 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
6042 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6043 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6044 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6045 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6046 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6047 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
6048 return MZ_TRUE;
6049}
6050
6051static mz_bool mz_zip_writer_add_to_central_dir(
6052 mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6053 const void *pExtra, mz_uint16 extra_size, const void *pComment,
6054 mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6055 mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6056 mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
6057 mz_uint32 ext_attributes) {
6058 mz_zip_internal_state *pState = pZip->m_pState;
6059 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6060 size_t orig_central_dir_size = pState->m_central_dir.m_size;
6061 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6062
6063 // No zip64 support yet
6064 if ((local_header_ofs > 0xFFFFFFFF) ||
6065 (((mz_uint64)pState->m_central_dir.m_size +
6066 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
6067 comment_size) > 0xFFFFFFFF))
6068 return MZ_FALSE;
6069
6070 if (!mz_zip_writer_create_central_dir_header(
6071 pZip, central_dir_header, filename_size, extra_size, comment_size,
6072 uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
6073 dos_date, local_header_ofs, ext_attributes))
6074 return MZ_FALSE;
6075
6076 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
6077 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6078 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
6079 filename_size)) ||
6080 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
6081 extra_size)) ||
6082 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
6083 comment_size)) ||
6084 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
6085 &central_dir_ofs, 1))) {
6086 // Try to push the central directory array back into its original state.
6087 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6088 MZ_FALSE);
6089 return MZ_FALSE;
6090 }
6091
6092 return MZ_TRUE;
6093}
6094
6095static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
6096 // Basic ZIP archive filename validity checks: Valid filenames cannot start
6097 // with a forward slash, cannot contain a drive letter, and cannot use
6098 // DOS-style backward slashes.
6099 if (*pArchive_name == '/')
6100 return MZ_FALSE;
6101 while (*pArchive_name) {
6102 if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
6103 return MZ_FALSE;
6104 pArchive_name++;
6105 }
6106 return MZ_TRUE;
6107}
6108
6109static mz_uint
6110mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
6111 mz_uint32 n;
6112 if (!pZip->m_file_offset_alignment)
6113 return 0;
6114 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6115 return (pZip->m_file_offset_alignment - n) &
6116 (pZip->m_file_offset_alignment - 1);
6117}
6118
6119static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
6120 mz_uint64 cur_file_ofs, mz_uint32 n) {
6121 char buf[4096];
6122 memset(buf, 0, MZ_MIN(sizeof(buf), n));
6123 while (n) {
6124 mz_uint32 s = MZ_MIN(sizeof(buf), n);
6125 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6126 return MZ_FALSE;
6127 cur_file_ofs += s;
6128 n -= s;
6129 }
6130 return MZ_TRUE;
6131}
6132
6133mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
6134 const char *pArchive_name, const void *pBuf,
6135 size_t buf_size, const void *pComment,
6136 mz_uint16 comment_size,
6137 mz_uint level_and_flags, mz_uint64 uncomp_size,
6138 mz_uint32 uncomp_crc32) {
6139 mz_uint32 ext_attributes = 0;
6140 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6141 mz_uint level, num_alignment_padding_bytes;
6142 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0;
6143 size_t archive_name_size;
6144 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6145 tdefl_compressor *pComp = NULL;
6146 mz_bool store_data_uncompressed;
6147 mz_zip_internal_state *pState;
6148
6149 if ((int)level_and_flags < 0)
6150 level_and_flags = MZ_DEFAULT_LEVEL;
6151 level = level_and_flags & 0xF;
6152 store_data_uncompressed =
6153 ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6154
6155 if ((!pZip) || (!pZip->m_pState) ||
6156 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
6157 (!pArchive_name) || ((comment_size) && (!pComment)) ||
6158 (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
6159 return MZ_FALSE;
6160
6161 local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6162 pState = pZip->m_pState;
6163
6164 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6165 return MZ_FALSE;
6166 // No zip64 support yet
6167 if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6168 return MZ_FALSE;
6169 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6170 return MZ_FALSE;
6171
6172#ifndef MINIZ_NO_TIME
6173 {
6174 time_t cur_time;
6175 time(&cur_time);
6176 mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6177 }
6178#endif // #ifndef MINIZ_NO_TIME
6179
6180 archive_name_size = strlen(pArchive_name);
6181 if (archive_name_size > 0xFFFF)
6182 return MZ_FALSE;
6183
6184 num_alignment_padding_bytes =
6185 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6186
6187 // no zip64 support yet
6188 if ((pZip->m_total_files == 0xFFFF) ||
6189 ((pZip->m_archive_size + num_alignment_padding_bytes +
6190 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6191 comment_size + archive_name_size) > 0xFFFFFFFF))
6192 return MZ_FALSE;
6193
6194 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
6195 // Set DOS Subdirectory attribute bit.
6196 ext_attributes |= 0x10;
6197 // Subdirectories cannot contain data.
6198 if ((buf_size) || (uncomp_size))
6199 return MZ_FALSE;
6200 }
6201
6202 // Try to do any allocations before writing to the archive, so if an
6203 // allocation fails the file remains unmodified. (A good idea if we're doing
6204 // an in-place modification.)
6205 if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir,
6206 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6207 archive_name_size + comment_size)) ||
6208 (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6209 return MZ_FALSE;
6210
6211 if ((!store_data_uncompressed) && (buf_size)) {
6212 if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
6213 pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6214 return MZ_FALSE;
6215 }
6216
6217 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6218 num_alignment_padding_bytes +
6219 sizeof(local_dir_header))) {
6220 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6221 return MZ_FALSE;
6222 }
6223 local_dir_header_ofs += num_alignment_padding_bytes;
6224 if (pZip->m_file_offset_alignment) {
6225 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6226 0);
6227 }
6228 cur_archive_file_ofs +=
6229 num_alignment_padding_bytes + sizeof(local_dir_header);
6230
6231 MZ_CLEAR_OBJ(local_dir_header);
6232 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6233 archive_name_size) != archive_name_size) {
6234 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6235 return MZ_FALSE;
6236 }
6237 cur_archive_file_ofs += archive_name_size;
6238
6239 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6240 uncomp_crc32 =
6241 (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6242 uncomp_size = buf_size;
6243 if (uncomp_size <= 3) {
6244 level = 0;
6245 store_data_uncompressed = MZ_TRUE;
6246 }
6247 }
6248
6249 if (store_data_uncompressed) {
6250 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
6251 buf_size) != buf_size) {
6252 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6253 return MZ_FALSE;
6254 }
6255
6256 cur_archive_file_ofs += buf_size;
6257 comp_size = buf_size;
6258
6259 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6260 method = MZ_DEFLATED;
6261 } else if (buf_size) {
6262 mz_zip_writer_add_state state;
6263
6264 state.m_pZip = pZip;
6265 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6266 state.m_comp_size = 0;
6267
6268 if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6269 tdefl_create_comp_flags_from_zip_params(
6270 level, -15, MZ_DEFAULT_STRATEGY)) !=
6271 TDEFL_STATUS_OKAY) ||
6272 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
6273 TDEFL_STATUS_DONE)) {
6274 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6275 return MZ_FALSE;
6276 }
6277
6278 comp_size = state.m_comp_size;
6279 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6280
6281 method = MZ_DEFLATED;
6282 }
6283
6284 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6285 pComp = NULL;
6286
6287 // no zip64 support yet
6288 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6289 return MZ_FALSE;
6290
6291 if (!mz_zip_writer_create_local_dir_header(
6292 pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6293 comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6294 return MZ_FALSE;
6295
6296 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6297 sizeof(local_dir_header)) != sizeof(local_dir_header))
6298 return MZ_FALSE;
6299
6300 if (!mz_zip_writer_add_to_central_dir(
6301 pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6302 comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6303 dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6304 return MZ_FALSE;
6305
6306 pZip->m_total_files++;
6307 pZip->m_archive_size = cur_archive_file_ofs;
6308
6309 return MZ_TRUE;
6310}
6311
6312#ifndef MINIZ_NO_STDIO
6313mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
6314 const char *pSrc_filename, const void *pComment,
6315 mz_uint16 comment_size, mz_uint level_and_flags,
6316 mz_uint32 ext_attributes) {
6317 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6318 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6319#ifndef MINIZ_NO_TIME
6320 time_t file_modified_time;
6321#endif
6322
6323 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
6324 comp_size = 0;
6325 size_t archive_name_size;
6326 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6327 MZ_FILE *pSrc_file = NULL;
6328
6329 if ((int)level_and_flags < 0)
6330 level_and_flags = MZ_DEFAULT_LEVEL;
6331 level = level_and_flags & 0xF;
6332
6333 if ((!pZip) || (!pZip->m_pState) ||
6334 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
6335 ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6336 return MZ_FALSE;
6337
6338 local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6339
6340 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6341 return MZ_FALSE;
6342 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6343 return MZ_FALSE;
6344
6345 archive_name_size = strlen(pArchive_name);
6346 if (archive_name_size > 0xFFFF)
6347 return MZ_FALSE;
6348
6349 num_alignment_padding_bytes =
6350 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6351
6352 // no zip64 support yet
6353 if ((pZip->m_total_files == 0xFFFF) ||
6354 ((pZip->m_archive_size + num_alignment_padding_bytes +
6355 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6356 comment_size + archive_name_size) > 0xFFFFFFFF))
6357 return MZ_FALSE;
6358
6359#ifndef MINIZ_NO_TIME
6360 memset(&file_modified_time, 0, sizeof(file_modified_time));
6361 if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6362 return MZ_FALSE;
6363 mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
6364#endif
6365
6366 pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6367 if (!pSrc_file)
6368 return MZ_FALSE;
6369 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6370 uncomp_size = MZ_FTELL64(pSrc_file);
6371 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6372
6373 if (uncomp_size > 0xFFFFFFFF) {
6374 // No zip64 support yet
6375 MZ_FCLOSE(pSrc_file);
6376 return MZ_FALSE;
6377 }
6378 if (uncomp_size <= 3)
6379 level = 0;
6380
6381 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6382 num_alignment_padding_bytes +
6383 sizeof(local_dir_header))) {
6384 MZ_FCLOSE(pSrc_file);
6385 return MZ_FALSE;
6386 }
6387 local_dir_header_ofs += num_alignment_padding_bytes;
6388 if (pZip->m_file_offset_alignment) {
6389 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6390 0);
6391 }
6392 cur_archive_file_ofs +=
6393 num_alignment_padding_bytes + sizeof(local_dir_header);
6394
6395 MZ_CLEAR_OBJ(local_dir_header);
6396 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6397 archive_name_size) != archive_name_size) {
6398 MZ_FCLOSE(pSrc_file);
6399 return MZ_FALSE;
6400 }
6401 cur_archive_file_ofs += archive_name_size;
6402
6403 if (uncomp_size) {
6404 mz_uint64 uncomp_remaining = uncomp_size;
6405 void *pRead_buf =
6406 pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6407 if (!pRead_buf) {
6408 MZ_FCLOSE(pSrc_file);
6409 return MZ_FALSE;
6410 }
6411
6412 if (!level) {
6413 while (uncomp_remaining) {
6414 mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6415 if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) ||
6416 (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
6417 n) != n)) {
6418 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6419 MZ_FCLOSE(pSrc_file);
6420 return MZ_FALSE;
6421 }
6422 uncomp_crc32 =
6423 (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6424 uncomp_remaining -= n;
6425 cur_archive_file_ofs += n;
6426 }
6427 comp_size = uncomp_size;
6428 } else {
6429 mz_bool result = MZ_FALSE;
6430 mz_zip_writer_add_state state;
6431 tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
6432 pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6433 if (!pComp) {
6434 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6435 MZ_FCLOSE(pSrc_file);
6436 return MZ_FALSE;
6437 }
6438
6439 state.m_pZip = pZip;
6440 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6441 state.m_comp_size = 0;
6442
6443 if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6444 tdefl_create_comp_flags_from_zip_params(
6445 level, -15, MZ_DEFAULT_STRATEGY)) !=
6446 TDEFL_STATUS_OKAY) {
6447 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6448 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6449 MZ_FCLOSE(pSrc_file);
6450 return MZ_FALSE;
6451 }
6452
6453 for (;;) {
6454 size_t in_buf_size =
6455 (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
6456 tdefl_status status;
6457
6458 if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6459 break;
6460
6461 uncomp_crc32 = (mz_uint32)mz_crc32(
6462 uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6463 uncomp_remaining -= in_buf_size;
6464
6465 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size,
6466 uncomp_remaining ? TDEFL_NO_FLUSH
6467 : TDEFL_FINISH);
6468 if (status == TDEFL_STATUS_DONE) {
6469 result = MZ_TRUE;
6470 break;
6471 } else if (status != TDEFL_STATUS_OKAY)
6472 break;
6473 }
6474
6475 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6476
6477 if (!result) {
6478 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6479 MZ_FCLOSE(pSrc_file);
6480 return MZ_FALSE;
6481 }
6482
6483 comp_size = state.m_comp_size;
6484 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6485
6486 method = MZ_DEFLATED;
6487 }
6488
6489 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6490 }
6491
6492 MZ_FCLOSE(pSrc_file);
6493 pSrc_file = NULL;
6494
6495 // no zip64 support yet
6496 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6497 return MZ_FALSE;
6498
6499 if (!mz_zip_writer_create_local_dir_header(
6500 pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6501 comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6502 return MZ_FALSE;
6503
6504 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6505 sizeof(local_dir_header)) != sizeof(local_dir_header))
6506 return MZ_FALSE;
6507
6508 if (!mz_zip_writer_add_to_central_dir(
6509 pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6510 comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6511 dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6512 return MZ_FALSE;
6513
6514 pZip->m_total_files++;
6515 pZip->m_archive_size = cur_archive_file_ofs;
6516
6517 return MZ_TRUE;
6518}
6519#endif // #ifndef MINIZ_NO_STDIO
6520
6521mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
6522 mz_zip_archive *pSource_zip,
6523 mz_uint file_index) {
6524 mz_uint n, bit_flags, num_alignment_padding_bytes;
6525 mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
6526 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6527 mz_uint32
6528 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6529 sizeof(mz_uint32)];
6530 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6531 mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6532 size_t orig_central_dir_size;
6533 mz_zip_internal_state *pState;
6534 void *pBuf;
6535 const mz_uint8 *pSrc_central_header;
6536
6537 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6538 return MZ_FALSE;
6539 if (NULL ==
6540 (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
6541 return MZ_FALSE;
6542 pState = pZip->m_pState;
6543
6544 num_alignment_padding_bytes =
6545 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6546
6547 // no zip64 support yet
6548 if ((pZip->m_total_files == 0xFFFF) ||
6549 ((pZip->m_archive_size + num_alignment_padding_bytes +
6550 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) >
6551 0xFFFFFFFF))
6552 return MZ_FALSE;
6553
6554 cur_src_file_ofs =
6555 MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6556 cur_dst_file_ofs = pZip->m_archive_size;
6557
6558 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
6559 pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6560 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6561 return MZ_FALSE;
6562 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6563 return MZ_FALSE;
6564 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6565
6566 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
6567 num_alignment_padding_bytes))
6568 return MZ_FALSE;
6569 cur_dst_file_ofs += num_alignment_padding_bytes;
6570 local_dir_header_ofs = cur_dst_file_ofs;
6571 if (pZip->m_file_offset_alignment) {
6572 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6573 0);
6574 }
6575
6576 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
6577 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6578 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6579 return MZ_FALSE;
6580 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6581
6582 n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6583 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6584 comp_bytes_remaining =
6585 n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6586
6587 if (NULL ==
6588 (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6589 (size_t)MZ_MAX(sizeof(mz_uint32) * 4,
6590 MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE,
6591 comp_bytes_remaining)))))
6592 return MZ_FALSE;
6593
6594 while (comp_bytes_remaining) {
6595 n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
6596 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6597 n) != n) {
6598 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6599 return MZ_FALSE;
6600 }
6601 cur_src_file_ofs += n;
6602
6603 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6604 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6605 return MZ_FALSE;
6606 }
6607 cur_dst_file_ofs += n;
6608
6609 comp_bytes_remaining -= n;
6610 }
6611
6612 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6613 if (bit_flags & 8) {
6614 // Copy data descriptor
6615 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6616 sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) {
6617 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6618 return MZ_FALSE;
6619 }
6620
6621 n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
6622 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6623 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6624 return MZ_FALSE;
6625 }
6626
6627 // cur_src_file_ofs += n;
6628 cur_dst_file_ofs += n;
6629 }
6630 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6631
6632 // no zip64 support yet
6633 if (cur_dst_file_ofs > 0xFFFFFFFF)
6634 return MZ_FALSE;
6635
6636 orig_central_dir_size = pState->m_central_dir.m_size;
6637
6638 memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6639 MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
6640 local_dir_header_ofs);
6641 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header,
6642 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6643 return MZ_FALSE;
6644
6645 n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6646 MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
6647 MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6648 if (!mz_zip_array_push_back(
6649 pZip, &pState->m_central_dir,
6650 pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) {
6651 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6652 MZ_FALSE);
6653 return MZ_FALSE;
6654 }
6655
6656 if (pState->m_central_dir.m_size > 0xFFFFFFFF)
6657 return MZ_FALSE;
6658 n = (mz_uint32)orig_central_dir_size;
6659 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
6660 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6661 MZ_FALSE);
6662 return MZ_FALSE;
6663 }
6664
6665 pZip->m_total_files++;
6666 pZip->m_archive_size = cur_dst_file_ofs;
6667
6668 return MZ_TRUE;
6669}
6670
6671mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
6672 mz_zip_internal_state *pState;
6673 mz_uint64 central_dir_ofs, central_dir_size;
6674 mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
6675
6676 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6677 return MZ_FALSE;
6678
6679 pState = pZip->m_pState;
6680
6681 // no zip64 support yet
6682 if ((pZip->m_total_files > 0xFFFF) ||
6683 ((pZip->m_archive_size + pState->m_central_dir.m_size +
6684 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6685 return MZ_FALSE;
6686
6687 central_dir_ofs = 0;
6688 central_dir_size = 0;
6689 if (pZip->m_total_files) {
6690 // Write central directory
6691 central_dir_ofs = pZip->m_archive_size;
6692 central_dir_size = pState->m_central_dir.m_size;
6693 pZip->m_central_directory_file_ofs = central_dir_ofs;
6694 if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
6695 pState->m_central_dir.m_p,
6696 (size_t)central_dir_size) != central_dir_size)
6697 return MZ_FALSE;
6698 pZip->m_archive_size += central_dir_size;
6699 }
6700
6701 // Write end of central directory record
6702 MZ_CLEAR_OBJ(hdr);
6703 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
6704 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
6705 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
6706 pZip->m_total_files);
6707 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
6708 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
6709 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6710
6711 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
6712 sizeof(hdr)) != sizeof(hdr))
6713 return MZ_FALSE;
6714#ifndef MINIZ_NO_STDIO
6715 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
6716 return MZ_FALSE;
6717#endif // #ifndef MINIZ_NO_STDIO
6718
6719 pZip->m_archive_size += sizeof(hdr);
6720
6721 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
6722 return MZ_TRUE;
6723}
6724
6725mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
6726 size_t *pSize) {
6727 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
6728 return MZ_FALSE;
6729 if (pZip->m_pWrite != mz_zip_heap_write_func)
6730 return MZ_FALSE;
6731 if (!mz_zip_writer_finalize_archive(pZip))
6732 return MZ_FALSE;
6733
6734 *pBuf = pZip->m_pState->m_pMem;
6735 *pSize = pZip->m_pState->m_mem_size;
6736 pZip->m_pState->m_pMem = NULL;
6737 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6738 return MZ_TRUE;
6739}
6740
6741mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
6742 mz_zip_internal_state *pState;
6743 mz_bool status = MZ_TRUE;
6744 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
6745 ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
6746 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
6747 return MZ_FALSE;
6748
6749 pState = pZip->m_pState;
6750 pZip->m_pState = NULL;
6751 mz_zip_array_clear(pZip, &pState->m_central_dir);
6752 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
6753 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
6754
6755#ifndef MINIZ_NO_STDIO
6756 if (pState->m_pFile) {
6757 MZ_FCLOSE(pState->m_pFile);
6758 pState->m_pFile = NULL;
6759 }
6760#endif // #ifndef MINIZ_NO_STDIO
6761
6762 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
6763 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
6764 pState->m_pMem = NULL;
6765 }
6766
6767 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6768 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
6769 return status;
6770}
6771
6772#ifndef MINIZ_NO_STDIO
6773mz_bool mz_zip_add_mem_to_archive_file_in_place(
6774 const char *pZip_filename, const char *pArchive_name, const void *pBuf,
6775 size_t buf_size, const void *pComment, mz_uint16 comment_size,
6776 mz_uint level_and_flags) {
6777 mz_bool status, created_new_archive = MZ_FALSE;
6778 mz_zip_archive zip_archive;
6779 struct MZ_FILE_STAT_STRUCT file_stat;
6780 MZ_CLEAR_OBJ(zip_archive);
6781 if ((int)level_and_flags < 0)
6782 level_and_flags = MZ_DEFAULT_LEVEL;
6783 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
6784 ((comment_size) && (!pComment)) ||
6785 ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6786 return MZ_FALSE;
6787 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6788 return MZ_FALSE;
6789 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
6790 // Create a new archive.
6791 if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
6792 return MZ_FALSE;
6793 created_new_archive = MZ_TRUE;
6794 } else {
6795 // Append to an existing archive.
6796 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6797 level_and_flags |
6798 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6799 return MZ_FALSE;
6800 if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) {
6801 mz_zip_reader_end(&zip_archive);
6802 return MZ_FALSE;
6803 }
6804 }
6805 status =
6806 mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
6807 pComment, comment_size, level_and_flags, 0, 0);
6808 // Always finalize, even if adding failed for some reason, so we have a valid
6809 // central directory. (This may not always succeed, but we can try.)
6810 if (!mz_zip_writer_finalize_archive(&zip_archive))
6811 status = MZ_FALSE;
6812 if (!mz_zip_writer_end(&zip_archive))
6813 status = MZ_FALSE;
6814 if ((!status) && (created_new_archive)) {
6815 // It's a new archive and something went wrong, so just delete it.
6816 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6817 (void)ignoredStatus;
6818 }
6819 return status;
6820}
6821
6822void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
6823 const char *pArchive_name,
6824 size_t *pSize, mz_uint flags) {
6825 int file_index;
6826 mz_zip_archive zip_archive;
6827 void *p = NULL;
6828
6829 if (pSize)
6830 *pSize = 0;
6831
6832 if ((!pZip_filename) || (!pArchive_name))
6833 return NULL;
6834
6835 MZ_CLEAR_OBJ(zip_archive);
6836 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6837 flags |
6838 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6839 return NULL;
6840
6841 if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL,
6842 flags)) >= 0)
6843 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6844
6845 mz_zip_reader_end(&zip_archive);
6846 return p;
6847}
6848
6849#endif // #ifndef MINIZ_NO_STDIO
6850
6851#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
6852
6853#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
6854
6855#ifdef __cplusplus
6856}
6857#endif
6858
6859#endif // MINIZ_HEADER_FILE_ONLY
6860
6861/*
6862 This is free and unencumbered software released into the public domain.
6863
6864 Anyone is free to copy, modify, publish, use, compile, sell, or
6865 distribute this software, either in source code form or as a compiled
6866 binary, for any purpose, commercial or non-commercial, and by any
6867 means.
6868
6869 In jurisdictions that recognize copyright laws, the author or authors
6870 of this software dedicate any and all copyright interest in the
6871 software to the public domain. We make this dedication for the benefit
6872 of the public at large and to the detriment of our heirs and
6873 successors. We intend this dedication to be an overt act of
6874 relinquishment in perpetuity of all present and future rights to this
6875 software under copyright law.
6876
6877 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6878 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6879 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6880 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6881 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6882 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6883 OTHER DEALINGS IN THE SOFTWARE.
6884
6885 For more information, please refer to <http://unlicense.org/>
6886*/
6887