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