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