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