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