1 /*
2 miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
3 reading/writing/appending, PNG writing See "unlicense" statement at the end
4 of this file. Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13,
5 2013 Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951:
6 http://www.ietf.org/rfc/rfc1951.txt
7
8 Most API's defined in miniz.c are optional. For example, to disable the
9 archive related functions just define MINIZ_NO_ARCHIVE_APIS, or to get rid of
10 all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
11
12 * Change History
13 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major
14 release with Zip64 support (almost there!):
15 - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug
16 (thanks kahmyong.moon@hp.com) which could cause locate files to not find
17 files. This bug would only have occured in earlier versions if you explicitly
18 used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or
19 mz_zip_add_mem_to_archive_file_in_place() (which used this flag). If you
20 can't switch to v1.15 but want to fix this bug, just remove the uses of this
21 flag from both helper funcs (and of course don't use the flag).
22 - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when
23 pUser_read_buf is not NULL and compressed size is > uncompressed size
24 - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract
25 compressed data from directory entries, to account for weird zipfiles which
26 contain zero-size compressed data on dir entries. Hopefully this fix won't
27 cause any issues on weird zip archives, because it assumes the low 16-bits of
28 zip external attributes are DOS attributes (which I believe they always are
29 in practice).
30 - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the
31 internal attributes, just the filename and external attributes
32 - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
33 - Added cmake support for Linux builds which builds all the examples,
34 tested with clang v3.3 and gcc v4.6.
35 - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
36 - Merged MZ_FORCEINLINE fix from hdeanclark
37 - Fix <time.h> include before config #ifdef, thanks emil.brink
38 - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping
39 (super useful for OpenGL apps), and explicit control over the compression
40 level (so you can set it to 1 for real-time compression).
41 - Merged in some compiler fixes from paulharris's github repro.
42 - Retested this build under Windows (VS 2010, including static analysis),
43 tcc 0.9.26, gcc v4.6 and clang v3.3.
44 - Added example6.c, which dumps an image of the mandelbrot set to a PNG
45 file.
46 - Modified example2 to help test the
47 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
48 - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix
49 possible src file fclose() leak if alignment bytes+local header file write
50 faiiled
51 - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the
52 wrong central dir header offset, appears harmless in this release, but it
53 became a problem in the zip64 branch 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1
54 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
55 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix
56 mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
57 - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and
58 re-ran a randomized regression test on ~500k files.
59 - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
60 - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze
61 (static analysis) option and fixed all warnings (except for the silly "Use of
62 the comma-operator in a tested expression.." analysis warning, which I
63 purposely use to work around a MSVC compiler warning).
64 - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and
65 tested Linux executables. The codeblocks workspace is compatible with
66 Linux+Win32/x64.
67 - Added miniz_tester solution/project, which is a useful little app
68 derived from LZHAM's tester app that I use as part of the regression test.
69 - Ran miniz.c and tinfl.c through another series of regression testing on
70 ~500,000 files and archives.
71 - Modified example5.c so it purposely disables a bunch of high-level
72 functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the
73 MINIZ_NO_STDIO bug report.)
74 - Fix ftell() usage in examples so they exit with an error on files which
75 are too large (a limitation of the examples, not miniz itself). 4/12/12 v1.12
76 - More comments, added low-level example5.c, fixed a couple minor
77 level_and_flags issues in the archive API's. level_and_flags can now be set
78 to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com>
79 for the feedback/bug report. 5/28/11 v1.11 - Added statement from
80 unlicense.org 5/27/11 v1.10 - Substantial compressor optimizations:
81 - Level 1 is now ~4x faster than before. The L1 compressor's throughput
82 now varies between 70-110MB/sec. on a
83 - Core i7 (actual throughput varies depending on the type of data, and x64
84 vs. x86).
85 - Improved baseline L2-L9 compression perf. Also, greatly improved
86 compression perf. issues on some file types.
87 - Refactored the compression code for better readability and
88 maintainability.
89 - Added level 10 compression level (L10 has slightly better ratio than
90 level 9, but could have a potentially large drop in throughput on some
91 files). 5/15/11 v1.09 - Initial stable release.
92
93 * Low-level Deflate/Inflate implementation notes:
94
95 Compression: Use the "tdefl" API's. The compressor supports raw, static,
96 and dynamic blocks, lazy or greedy parsing, match length filtering, RLE-only,
97 and Huffman-only streams. It performs and compresses approximately as well as
98 zlib.
99
100 Decompression: Use the "tinfl" API's. The entire decompressor is
101 implemented as a single function coroutine: see tinfl_decompress(). It
102 supports decompression into a 32KB (or larger power of 2) wrapping buffer, or
103 into a memory block large enough to hold the entire file.
104
105 The low-level tdefl/tinfl API's do not make any use of dynamic memory
106 allocation.
107
108 * zlib-style API notes:
109
110 miniz.c implements a fairly large subset of zlib. There's enough
111 functionality present for it to be a drop-in zlib replacement in many apps:
112 The z_stream struct, optional memory allocation callbacks
113 deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
114 inflateInit/inflateInit2/inflate/inflateEnd
115 compress, compress2, compressBound, uncompress
116 CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly
117 routines. Supports raw deflate streams or standard zlib streams with adler-32
118 checking.
119
120 Limitations:
121 The callback API's are not implemented yet. No support for gzip headers or
122 zlib static dictionaries. I've tried to closely emulate zlib's various
123 flavors of stream flushing and return status codes, but there are no
124 guarantees that miniz.c pulls this off perfectly.
125
126 * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function,
127 originally written by Alex Evans. Supports 1-4 bytes/pixel images.
128
129 * ZIP archive API notes:
130
131 The ZIP archive API's where designed with simplicity and efficiency in
132 mind, with just enough abstraction to get the job done with minimal fuss.
133 There are simple API's to retrieve file information, read files from existing
134 archives, create new archives, append new files to existing archives, or
135 clone archive data from one archive to another. It supports archives located
136 in memory or the heap, on disk (using stdio.h), or you can specify custom
137 file read/write callbacks.
138
139 - Archive reading: Just call this function to read a single file from a
140 disk archive:
141
142 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const
143 char *pArchive_name, size_t *pSize, mz_uint zip_flags);
144
145 For more complex cases, use the "mz_zip_reader" functions. Upon opening an
146 archive, the entire central directory is located and read as-is into memory,
147 and subsequent file access only occurs when reading individual files.
148
149 - Archives file scanning: The simple way is to use this function to scan a
150 loaded archive for a specific file:
151
152 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
153 const char *pComment, mz_uint flags);
154
155 The locate operation can optionally check file comments too, which (as one
156 example) can be used to identify multiple versions of the same file in an
157 archive. This function uses a simple linear search through the central
158 directory, so it's not very fast.
159
160 Alternately, you can iterate through all the files in an archive (using
161 mz_zip_reader_get_num_files()) and retrieve detailed info on each file by
162 calling mz_zip_reader_file_stat().
163
164 - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer
165 immediately writes compressed file data to disk and builds an exact image of
166 the central directory in memory. The central directory image is written all
167 at once at the end of the archive file when the archive is finalized.
168
169 The archive writer can optionally align each file's local header and file
170 data to any power of 2 alignment, which can be useful when the archive will
171 be read from optical media. Also, the writer supports placing arbitrary data
172 blobs at the very beginning of ZIP archives. Archives written using either
173 feature are still readable by any ZIP tool.
174
175 - Archive appending: The simple way to add a single file to an archive is
176 to call this function:
177
178 mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename,
179 const char *pArchive_name, const void *pBuf, size_t buf_size, const void
180 *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
181
182 The archive will be created if it doesn't already exist, otherwise it'll be
183 appended to. Note the appending is done in-place and is not an atomic
184 operation, so if something goes wrong during the operation it's possible the
185 archive could be left without a central directory (although the local file
186 headers and file data will be fine, so the archive will be recoverable).
187
188 For more complex archive modification scenarios:
189 1. The safest way is to use a mz_zip_reader to read the existing archive,
190 cloning only those bits you want to preserve into a new archive using using
191 the mz_zip_writer_add_from_zip_reader() function (which compiles the
192 compressed file data as-is). When you're done, delete the old archive and
193 rename the newly written archive, and you're done. This is safe but requires
194 a bunch of temporary disk space or heap memory.
195
196 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using
197 mz_zip_writer_init_from_reader(), append new files as needed, then finalize
198 the archive which will write an updated central directory to the original
199 archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place()
200 does.) There's a possibility that the archive's central directory could be
201 lost with this method if anything goes wrong, though.
202
203 - ZIP archive support limitations:
204 No zip64 or spanning support. Extraction functions can only handle
205 unencrypted, stored or deflated files. Requires streams capable of seeking.
206
207 * This is a header file library, like stb_image.c. To get only a header file,
208 either cut and paste the below header, or create miniz.h, #define
209 MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
210
211 * Important: For best perf. be sure to customize the below macros for your
212 target platform: #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define
213 MINIZ_LITTLE_ENDIAN 1 #define MINIZ_HAS_64BIT_REGISTERS 1
214
215 * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before
216 including miniz.c to ensure miniz uses the 64-bit variants: fopen64(),
217 stat64(), etc. Otherwise you won't be able to process large files (i.e.
218 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
219 */
220
221 #ifndef MINIZ_HEADER_INCLUDED
222 #define MINIZ_HEADER_INCLUDED
223
224 #include <stdint.h>
225 #include <stdlib.h>
226
227 // Defines to completely disable specific portions of miniz.c:
228 // If all macros here are defined the only functionality remaining will be
229 // CRC-32, adler-32, tinfl, and tdefl.
230
231 // Define MINIZ_NO_STDIO to disable all usage and any functions which rely on
232 // stdio for file I/O.
233 //#define MINIZ_NO_STDIO
234
235 // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able
236 // to get the current time, or get/set file times, and the C run-time funcs that
237 // get/set times won't be called. The current downside is the times written to
238 // your archives will be from 1979.
239 //#define MINIZ_NO_TIME
240
241 // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
242 //#define MINIZ_NO_ARCHIVE_APIS
243
244 // Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive
245 // API's.
246 //#define MINIZ_NO_ARCHIVE_WRITING_APIS
247
248 // Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression
249 // API's.
250 //#define MINIZ_NO_ZLIB_APIS
251
252 // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent
253 // conflicts against stock zlib.
254 //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
255
256 // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
257 // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom
258 // user alloc/free/realloc callbacks to the zlib and archive API's, and a few
259 // stand-alone helper API's which don't provide custom user functions (such as
260 // tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
261 //#define MINIZ_NO_MALLOC
262
263 #if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
264 // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc
265 // on Linux
266 #define MINIZ_NO_TIME
267 #endif
268
269 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
270 #include <time.h>
271 #endif
272
273 #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
274 defined(__i386) || defined(__i486__) || defined(__i486) || \
275 defined(i386) || defined(__ia64__) || defined(__x86_64__)
276 // MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
277 #define MINIZ_X86_OR_X64_CPU 1
278 #endif
279
280 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
281 // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
282 #define MINIZ_LITTLE_ENDIAN 1
283 #endif
284
285 /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */
286 #if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES)
287 #if MINIZ_X86_OR_X64_CPU
288 /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
289 * integer loads and stores from unaligned addresses. */
290 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
291 #define MINIZ_UNALIGNED_USE_MEMCPY
292 #else
293 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
294 #endif
295 #endif
296
297 #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || \
298 defined(_LP64) || defined(__LP64__) || defined(__ia64__) || \
299 defined(__x86_64__)
300 // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are
301 // reasonably fast (and don't involve compiler generated calls to helper
302 // functions).
303 #define MINIZ_HAS_64BIT_REGISTERS 1
304 #endif
305
306 #ifdef __APPLE__
307 #define ftello64 ftello
308 #define fseeko64 fseeko
309 #define fopen64 fopen
310 #define freopen64 freopen
311
312 // Darwin OSX
313 #define MZ_PLATFORM 19
314 #endif
315
316 #ifndef MZ_PLATFORM
317 #if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
318 #define MZ_PLATFORM 0
319 #else
320 // UNIX
321 #define MZ_PLATFORM 3
322 #endif
323 #endif
324
325 #ifdef __cplusplus
326 extern "C" {
327 #endif
328
329 // ------------------- zlib-style API Definitions.
330
331 // For more compatibility with zlib, miniz.c uses unsigned long for some
332 // parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
333 typedef unsigned long mz_ulong;
334
335 // mz_free() internally uses the MZ_FREE() macro (which by default calls free()
336 // unless you've modified the MZ_MALLOC macro) to release a block allocated from
337 // the heap.
338 void mz_free(void *p);
339
340 #define MZ_ADLER32_INIT (1)
341 // mz_adler32() returns the initial adler-32 value to use when called with
342 // ptr==NULL.
343 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
344
345 #define MZ_CRC32_INIT (0)
346 // mz_crc32() returns the initial CRC-32 value to use when called with
347 // ptr==NULL.
348 mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
349
350 // Compression strategies.
351 enum {
352 MZ_DEFAULT_STRATEGY = 0,
353 MZ_FILTERED = 1,
354 MZ_HUFFMAN_ONLY = 2,
355 MZ_RLE = 3,
356 MZ_FIXED = 4
357 };
358
359 /* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or
360 * modify this enum. */
361 typedef enum {
362 MZ_ZIP_NO_ERROR = 0,
363 MZ_ZIP_UNDEFINED_ERROR,
364 MZ_ZIP_TOO_MANY_FILES,
365 MZ_ZIP_FILE_TOO_LARGE,
366 MZ_ZIP_UNSUPPORTED_METHOD,
367 MZ_ZIP_UNSUPPORTED_ENCRYPTION,
368 MZ_ZIP_UNSUPPORTED_FEATURE,
369 MZ_ZIP_FAILED_FINDING_CENTRAL_DIR,
370 MZ_ZIP_NOT_AN_ARCHIVE,
371 MZ_ZIP_INVALID_HEADER_OR_CORRUPTED,
372 MZ_ZIP_UNSUPPORTED_MULTIDISK,
373 MZ_ZIP_DECOMPRESSION_FAILED,
374 MZ_ZIP_COMPRESSION_FAILED,
375 MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE,
376 MZ_ZIP_CRC_CHECK_FAILED,
377 MZ_ZIP_UNSUPPORTED_CDIR_SIZE,
378 MZ_ZIP_ALLOC_FAILED,
379 MZ_ZIP_FILE_OPEN_FAILED,
380 MZ_ZIP_FILE_CREATE_FAILED,
381 MZ_ZIP_FILE_WRITE_FAILED,
382 MZ_ZIP_FILE_READ_FAILED,
383 MZ_ZIP_FILE_CLOSE_FAILED,
384 MZ_ZIP_FILE_SEEK_FAILED,
385 MZ_ZIP_FILE_STAT_FAILED,
386 MZ_ZIP_INVALID_PARAMETER,
387 MZ_ZIP_INVALID_FILENAME,
388 MZ_ZIP_BUF_TOO_SMALL,
389 MZ_ZIP_INTERNAL_ERROR,
390 MZ_ZIP_FILE_NOT_FOUND,
391 MZ_ZIP_ARCHIVE_TOO_LARGE,
392 MZ_ZIP_VALIDATION_FAILED,
393 MZ_ZIP_WRITE_CALLBACK_FAILED,
394 MZ_ZIP_TOTAL_ERRORS
395 } mz_zip_error;
396
397 // Method
398 #define MZ_DEFLATED 8
399
400 #ifndef MINIZ_NO_ZLIB_APIS
401
402 // Heap allocation callbacks.
403 // Note that mz_alloc_func parameter types purpsosely differ from zlib's:
404 // items/size is size_t, not unsigned long.
405 typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
406 typedef void (*mz_free_func)(void *opaque, void *address);
407 typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items,
408 size_t size);
409
410 #define MZ_VERSION "9.1.15"
411 #define MZ_VERNUM 0x91F0
412 #define MZ_VER_MAJOR 9
413 #define MZ_VER_MINOR 1
414 #define MZ_VER_REVISION 15
415 #define MZ_VER_SUBREVISION 0
416
417 // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The
418 // other values are for advanced use (refer to the zlib docs).
419 enum {
420 MZ_NO_FLUSH = 0,
421 MZ_PARTIAL_FLUSH = 1,
422 MZ_SYNC_FLUSH = 2,
423 MZ_FULL_FLUSH = 3,
424 MZ_FINISH = 4,
425 MZ_BLOCK = 5
426 };
427
428 // Return status codes. MZ_PARAM_ERROR is non-standard.
429 enum {
430 MZ_OK = 0,
431 MZ_STREAM_END = 1,
432 MZ_NEED_DICT = 2,
433 MZ_ERRNO = -1,
434 MZ_STREAM_ERROR = -2,
435 MZ_DATA_ERROR = -3,
436 MZ_MEM_ERROR = -4,
437 MZ_BUF_ERROR = -5,
438 MZ_VERSION_ERROR = -6,
439 MZ_PARAM_ERROR = -10000
440 };
441
442 // Compression levels: 0-9 are the standard zlib-style levels, 10 is best
443 // possible compression (not zlib compatible, and may be very slow),
444 // MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
445 enum {
446 MZ_NO_COMPRESSION = 0,
447 MZ_BEST_SPEED = 1,
448 MZ_BEST_COMPRESSION = 9,
449 MZ_UBER_COMPRESSION = 10,
450 MZ_DEFAULT_LEVEL = 6,
451 MZ_DEFAULT_COMPRESSION = -1
452 };
453
454 // Window bits
455 #define MZ_DEFAULT_WINDOW_BITS 15
456
457 struct mz_internal_state;
458
459 // Compression/decompression stream struct.
460 typedef struct mz_stream_s {
461 const unsigned char *next_in; // pointer to next byte to read
462 unsigned int avail_in; // number of bytes available at next_in
463 mz_ulong total_in; // total number of bytes consumed so far
464
465 unsigned char *next_out; // pointer to next byte to write
466 unsigned int avail_out; // number of bytes that can be written to next_out
467 mz_ulong total_out; // total number of bytes produced so far
468
469 char *msg; // error msg (unused)
470 struct mz_internal_state *state; // internal state, allocated by zalloc/zfree
471
472 mz_alloc_func
473 zalloc; // optional heap allocation function (defaults to malloc)
474 mz_free_func zfree; // optional heap free function (defaults to free)
475 void *opaque; // heap alloc function user pointer
476
477 int data_type; // data_type (unused)
478 mz_ulong adler; // adler32 of the source or uncompressed data
479 mz_ulong reserved; // not used
480 } mz_stream;
481
482 typedef mz_stream *mz_streamp;
483
484 // Returns the version string of miniz.c.
485 const char *mz_version(void);
486
487 // mz_deflateInit() initializes a compressor with default options:
488 // Parameters:
489 // pStream must point to an initialized mz_stream struct.
490 // level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
491 // level 1 enables a specially optimized compression function that's been
492 // optimized purely for performance, not ratio. (This special func. is
493 // currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and
494 // MINIZ_LITTLE_ENDIAN are defined.)
495 // Return values:
496 // MZ_OK on success.
497 // MZ_STREAM_ERROR if the stream is bogus.
498 // MZ_PARAM_ERROR if the input parameters are bogus.
499 // MZ_MEM_ERROR on out of memory.
500 int mz_deflateInit(mz_streamp pStream, int level);
501
502 // mz_deflateInit2() is like mz_deflate(), except with more control:
503 // Additional parameters:
504 // method must be MZ_DEFLATED
505 // window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with
506 // zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no
507 // header or footer) mem_level must be between [1, 9] (it's checked but
508 // ignored by miniz.c)
509 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
510 int mem_level, int strategy);
511
512 // Quickly resets a compressor without having to reallocate anything. Same as
513 // calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
514 int mz_deflateReset(mz_streamp pStream);
515
516 // mz_deflate() compresses the input to output, consuming as much of the input
517 // and producing as much output as possible. Parameters:
518 // pStream is the stream to read from and write to. You must initialize/update
519 // the next_in, avail_in, next_out, and avail_out members. flush may be
520 // MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
521 // Return values:
522 // MZ_OK on success (when flushing, or if more input is needed but not
523 // available, and/or there's more output to be written but the output buffer
524 // is full). MZ_STREAM_END if all input has been consumed and all output bytes
525 // have been written. Don't call mz_deflate() on the stream anymore.
526 // MZ_STREAM_ERROR if the stream is bogus.
527 // MZ_PARAM_ERROR if one of the parameters is invalid.
528 // MZ_BUF_ERROR if no forward progress is possible because the input and/or
529 // output buffers are empty. (Fill up the input buffer or free up some output
530 // space and try again.)
531 int mz_deflate(mz_streamp pStream, int flush);
532
533 // mz_deflateEnd() deinitializes a compressor:
534 // Return values:
535 // MZ_OK on success.
536 // MZ_STREAM_ERROR if the stream is bogus.
537 int mz_deflateEnd(mz_streamp pStream);
538
539 // mz_deflateBound() returns a (very) conservative upper bound on the amount of
540 // data that could be generated by deflate(), assuming flush is set to only
541 // MZ_NO_FLUSH or MZ_FINISH.
542 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
543
544 // Single-call compression functions mz_compress() and mz_compress2():
545 // Returns MZ_OK on success, or one of the error codes from mz_deflate() on
546 // failure.
547 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
548 const unsigned char *pSource, mz_ulong source_len);
549 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
550 const unsigned char *pSource, mz_ulong source_len, int level);
551
552 // mz_compressBound() returns a (very) conservative upper bound on the amount of
553 // data that could be generated by calling mz_compress().
554 mz_ulong mz_compressBound(mz_ulong source_len);
555
556 // Initializes a decompressor.
557 int mz_inflateInit(mz_streamp pStream);
558
559 // mz_inflateInit2() is like mz_inflateInit() with an additional option that
560 // controls the window size and whether or not the stream has been wrapped with
561 // a zlib header/footer: window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse
562 // zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
563 int mz_inflateInit2(mz_streamp pStream, int window_bits);
564
565 // Decompresses the input stream to the output, consuming only as much of the
566 // input as needed, and writing as much to the output as possible. Parameters:
567 // pStream is the stream to read from and write to. You must initialize/update
568 // the next_in, avail_in, next_out, and avail_out members. flush may be
569 // MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. On the first call, if flush is
570 // MZ_FINISH it's assumed the input and output buffers are both sized large
571 // enough to decompress the entire stream in a single call (this is slightly
572 // faster). MZ_FINISH implies that there are no more source bytes available
573 // beside what's already in the input buffer, and that the output buffer is
574 // large enough to hold the rest of the decompressed data.
575 // Return values:
576 // MZ_OK on success. Either more input is needed but not available, and/or
577 // there's more output to be written but the output buffer is full.
578 // MZ_STREAM_END if all needed input has been consumed and all output bytes
579 // have been written. For zlib streams, the adler-32 of the decompressed data
580 // has also been verified. MZ_STREAM_ERROR if the stream is bogus.
581 // MZ_DATA_ERROR if the deflate stream is invalid.
582 // MZ_PARAM_ERROR if one of the parameters is invalid.
583 // MZ_BUF_ERROR if no forward progress is possible because the input buffer is
584 // empty but the inflater needs more input to continue, or if the output
585 // buffer is not large enough. Call mz_inflate() again with more input data,
586 // or with more room in the output buffer (except when using single call
587 // decompression, described above).
588 int mz_inflate(mz_streamp pStream, int flush);
589
590 // Deinitializes a decompressor.
591 int mz_inflateEnd(mz_streamp pStream);
592
593 // Single-call decompression.
594 // Returns MZ_OK on success, or one of the error codes from mz_inflate() on
595 // failure.
596 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
597 const unsigned char *pSource, mz_ulong source_len);
598
599 // Returns a string description of the specified error code, or NULL if the
600 // error code is invalid.
601 const char *mz_error(int err);
602
603 // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used
604 // as a drop-in replacement for the subset of zlib that miniz.c supports. Define
605 // MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib
606 // in the same project.
607 #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
608 typedef unsigned char Byte;
609 typedef unsigned int uInt;
610 typedef mz_ulong uLong;
611 typedef Byte Bytef;
612 typedef uInt uIntf;
613 typedef char charf;
614 typedef int intf;
615 typedef void *voidpf;
616 typedef uLong uLongf;
617 typedef void *voidp;
618 typedef void *const voidpc;
619 #define Z_NULL 0
620 #define Z_NO_FLUSH MZ_NO_FLUSH
621 #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
622 #define Z_SYNC_FLUSH MZ_SYNC_FLUSH
623 #define Z_FULL_FLUSH MZ_FULL_FLUSH
624 #define Z_FINISH MZ_FINISH
625 #define Z_BLOCK MZ_BLOCK
626 #define Z_OK MZ_OK
627 #define Z_STREAM_END MZ_STREAM_END
628 #define Z_NEED_DICT MZ_NEED_DICT
629 #define Z_ERRNO MZ_ERRNO
630 #define Z_STREAM_ERROR MZ_STREAM_ERROR
631 #define Z_DATA_ERROR MZ_DATA_ERROR
632 #define Z_MEM_ERROR MZ_MEM_ERROR
633 #define Z_BUF_ERROR MZ_BUF_ERROR
634 #define Z_VERSION_ERROR MZ_VERSION_ERROR
635 #define Z_PARAM_ERROR MZ_PARAM_ERROR
636 #define Z_NO_COMPRESSION MZ_NO_COMPRESSION
637 #define Z_BEST_SPEED MZ_BEST_SPEED
638 #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
639 #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
640 #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
641 #define Z_FILTERED MZ_FILTERED
642 #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
643 #define Z_RLE MZ_RLE
644 #define Z_FIXED MZ_FIXED
645 #define Z_DEFLATED MZ_DEFLATED
646 #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
647 #define alloc_func mz_alloc_func
648 #define free_func mz_free_func
649 #define internal_state mz_internal_state
650 #define z_stream mz_stream
651 #define deflateInit mz_deflateInit
652 #define deflateInit2 mz_deflateInit2
653 #define deflateReset mz_deflateReset
654 #define deflate mz_deflate
655 #define deflateEnd mz_deflateEnd
656 #define deflateBound mz_deflateBound
657 #define compress mz_compress
658 #define compress2 mz_compress2
659 #define compressBound mz_compressBound
660 #define inflateInit mz_inflateInit
661 #define inflateInit2 mz_inflateInit2
662 #define inflate mz_inflate
663 #define inflateEnd mz_inflateEnd
664 #define uncompress mz_uncompress
665 #define crc32 mz_crc32
666 #define adler32 mz_adler32
667 #define MAX_WBITS 15
668 #define MAX_MEM_LEVEL 9
669 #define zError mz_error
670 #define ZLIB_VERSION MZ_VERSION
671 #define ZLIB_VERNUM MZ_VERNUM
672 #define ZLIB_VER_MAJOR MZ_VER_MAJOR
673 #define ZLIB_VER_MINOR MZ_VER_MINOR
674 #define ZLIB_VER_REVISION MZ_VER_REVISION
675 #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
676 #define zlibVersion mz_version
677 #define zlib_version mz_version()
678 #endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
679
680 #endif // MINIZ_NO_ZLIB_APIS
681
682 // ------------------- Types and macros
683
684 typedef unsigned char mz_uint8;
685 typedef signed short mz_int16;
686 typedef unsigned short mz_uint16;
687 typedef unsigned int mz_uint32;
688 typedef unsigned int mz_uint;
689 typedef long long mz_int64;
690 typedef unsigned long long mz_uint64;
691 typedef int mz_bool;
692
693 #define MZ_FALSE (0)
694 #define MZ_TRUE (1)
695
696 // An attempt to work around MSVC's spammy "warning C4127: conditional
697 // expression is constant" message.
698 #ifdef _MSC_VER
699 #define MZ_MACRO_END while (0, 0)
700 #else
701 #define MZ_MACRO_END while (0)
702 #endif
703
704 // ------------------- ZIP archive reading/writing
705
706 #ifndef MINIZ_NO_ARCHIVE_APIS
707
708 enum {
709 MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,
710 MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
711 MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
712 };
713
714 typedef struct {
715 mz_uint32 m_file_index;
716 mz_uint32 m_central_dir_ofs;
717 mz_uint16 m_version_made_by;
718 mz_uint16 m_version_needed;
719 mz_uint16 m_bit_flag;
720 mz_uint16 m_method;
721 #ifndef MINIZ_NO_TIME
722 time_t m_time;
723 #endif
724 mz_uint32 m_crc32;
725 mz_uint64 m_comp_size;
726 mz_uint64 m_uncomp_size;
727 mz_uint16 m_internal_attr;
728 mz_uint32 m_external_attr;
729 mz_uint64 m_local_header_ofs;
730 mz_uint32 m_comment_size;
731 char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
732 char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
733 } mz_zip_archive_file_stat;
734
735 typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
736 void *pBuf, size_t n);
737 typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
738 const void *pBuf, size_t n);
739 typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
740
741 struct mz_zip_internal_state_tag;
742 typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
743
744 typedef enum {
745 MZ_ZIP_MODE_INVALID = 0,
746 MZ_ZIP_MODE_READING = 1,
747 MZ_ZIP_MODE_WRITING = 2,
748 MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
749 } mz_zip_mode;
750
751 typedef enum {
752 MZ_ZIP_TYPE_INVALID = 0,
753 MZ_ZIP_TYPE_USER,
754 MZ_ZIP_TYPE_MEMORY,
755 MZ_ZIP_TYPE_HEAP,
756 MZ_ZIP_TYPE_FILE,
757 MZ_ZIP_TYPE_CFILE,
758 MZ_ZIP_TOTAL_TYPES
759 } mz_zip_type;
760
761 typedef struct {
762 mz_uint64 m_archive_size;
763 mz_uint64 m_central_directory_file_ofs;
764
765 /* We only support up to UINT32_MAX files in zip64 mode. */
766 mz_uint32 m_total_files;
767 mz_zip_mode m_zip_mode;
768 mz_zip_type m_zip_type;
769 mz_zip_error m_last_error;
770
771 mz_uint64 m_file_offset_alignment;
772
773 mz_alloc_func m_pAlloc;
774 mz_free_func m_pFree;
775 mz_realloc_func m_pRealloc;
776 void *m_pAlloc_opaque;
777
778 mz_file_read_func m_pRead;
779 mz_file_write_func m_pWrite;
780 mz_file_needs_keepalive m_pNeeds_keepalive;
781 void *m_pIO_opaque;
782
783 mz_zip_internal_state *m_pState;
784
785 } mz_zip_archive;
786
787 typedef enum {
788 MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
789 MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
790 MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
791 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
792 } mz_zip_flags;
793
794 // ZIP archive reading
795
796 // Inits a ZIP archive reader.
797 // These functions read and validate the archive's central directory.
798 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
799 mz_uint32 flags);
800 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
801 size_t size, mz_uint32 flags);
802
803 #ifndef MINIZ_NO_STDIO
804 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
805 mz_uint32 flags);
806 #endif
807
808 // Returns the total number of files in the archive.
809 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
810
811 // Returns detailed information about an archive file entry.
812 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
813 mz_zip_archive_file_stat *pStat);
814
815 // Determines if an archive file entry is a directory entry.
816 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
817 mz_uint file_index);
818 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
819 mz_uint file_index);
820
821 // Retrieves the filename of an archive file entry.
822 // Returns the number of bytes written to pFilename, or if filename_buf_size is
823 // 0 this function returns the number of bytes needed to fully store the
824 // filename.
825 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
826 char *pFilename, mz_uint filename_buf_size);
827
828 // Attempts to locates a file in the archive's central directory.
829 // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
830 // Returns -1 if the file cannot be found.
831 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
832 const char *pComment, mz_uint flags);
833
834 // Extracts a archive file to a memory buffer using no memory allocation.
835 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
836 mz_uint file_index, void *pBuf,
837 size_t buf_size, mz_uint flags,
838 void *pUser_read_buf,
839 size_t user_read_buf_size);
840 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
841 mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
842 mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
843
844 // Extracts a archive file to a memory buffer.
845 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
846 void *pBuf, size_t buf_size,
847 mz_uint flags);
848 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
849 const char *pFilename, void *pBuf,
850 size_t buf_size, mz_uint flags);
851
852 // Extracts a archive file to a dynamically allocated heap buffer.
853 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
854 size_t *pSize, mz_uint flags);
855 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
856 const char *pFilename, size_t *pSize,
857 mz_uint flags);
858
859 // Extracts a archive file using a callback function to output the file's data.
860 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
861 mz_uint file_index,
862 mz_file_write_func pCallback,
863 void *pOpaque, mz_uint flags);
864 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
865 const char *pFilename,
866 mz_file_write_func pCallback,
867 void *pOpaque, mz_uint flags);
868
869 #ifndef MINIZ_NO_STDIO
870 // Extracts a archive file to a disk file and sets its last accessed and
871 // modified times. This function only extracts files, not archive directory
872 // records.
873 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
874 const char *pDst_filename, mz_uint flags);
875 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
876 const char *pArchive_filename,
877 const char *pDst_filename,
878 mz_uint flags);
879 #endif
880
881 // Ends archive reading, freeing all allocations, and closing the input archive
882 // file if mz_zip_reader_init_file() was used.
883 mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
884
885 // ZIP archive writing
886
887 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
888
889 // Inits a ZIP archive writer.
890 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
891 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
892 size_t size_to_reserve_at_beginning,
893 size_t initial_allocation_size);
894
895 #ifndef MINIZ_NO_STDIO
896 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
897 mz_uint64 size_to_reserve_at_beginning);
898 #endif
899
900 // Converts a ZIP archive reader object into a writer object, to allow efficient
901 // in-place file appends to occur on an existing archive. For archives opened
902 // using mz_zip_reader_init_file, pFilename must be the archive's filename so it
903 // can be reopened for writing. If the file can't be reopened,
904 // mz_zip_reader_end() will be called. For archives opened using
905 // mz_zip_reader_init_mem, the memory block must be growable using the realloc
906 // callback (which defaults to realloc unless you've overridden it). Finally,
907 // for archives opened using mz_zip_reader_init, the mz_zip_archive's user
908 // provided m_pWrite function cannot be NULL. Note: In-place archive
909 // modification is not recommended unless you know what you're doing, because if
910 // execution stops or something goes wrong before the archive is finalized the
911 // file's central directory will be hosed.
912 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
913 const char *pFilename);
914
915 // Adds the contents of a memory buffer to an archive. These functions record
916 // the current local time into the archive. To add a directory entry, call this
917 // method with an archive name ending in a forwardslash with empty buffer.
918 // level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
919 // MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
920 // just set to MZ_DEFAULT_COMPRESSION.
921 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
922 const void *pBuf, size_t buf_size,
923 mz_uint level_and_flags);
924 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
925 const char *pArchive_name, const void *pBuf,
926 size_t buf_size, const void *pComment,
927 mz_uint16 comment_size,
928 mz_uint level_and_flags, mz_uint64 uncomp_size,
929 mz_uint32 uncomp_crc32);
930
931 #ifndef MINIZ_NO_STDIO
932 // Adds the contents of a disk file to an archive. This function also records
933 // the disk file's modified time into the archive. level_and_flags - compression
934 // level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd
935 // with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
936 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
937 const char *pSrc_filename, const void *pComment,
938 mz_uint16 comment_size, mz_uint level_and_flags,
939 mz_uint32 ext_attributes);
940 #endif
941
942 // Adds a file to an archive by fully cloning the data from another archive.
943 // This function fully clones the source file's compressed data (no
944 // recompression), along with its full filename, extra data, and comment fields.
945 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
946 mz_zip_archive *pSource_zip,
947 mz_uint file_index);
948
949 // Finalizes the archive by writing the central directory records followed by
950 // the end of central directory record. After an archive is finalized, the only
951 // valid call on the mz_zip_archive struct is mz_zip_writer_end(). An archive
952 // must be manually finalized by calling this function for it to be valid.
953 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
954 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
955 size_t *pSize);
956
957 // Ends archive writing, freeing all allocations, and closing the output file if
958 // mz_zip_writer_init_file() was used. Note for the archive to be valid, it must
959 // have been finalized before ending.
960 mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
961
962 // Misc. high-level helper functions:
963
964 // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically)
965 // appends a memory blob to a ZIP archive. level_and_flags - compression level
966 // (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero
967 // or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
968 mz_bool mz_zip_add_mem_to_archive_file_in_place(
969 const char *pZip_filename, const char *pArchive_name, const void *pBuf,
970 size_t buf_size, const void *pComment, mz_uint16 comment_size,
971 mz_uint level_and_flags);
972
973 // Reads a single file from an archive into a heap block.
974 // Returns NULL on failure.
975 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
976 const char *pArchive_name,
977 size_t *pSize, mz_uint zip_flags);
978
979 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
980
981 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
982
983 // ------------------- Low-level Decompression API Definitions
984
985 // Decompression flags used by tinfl_decompress().
986 // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and
987 // ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the
988 // input is a raw deflate stream. TINFL_FLAG_HAS_MORE_INPUT: If set, there are
989 // more input bytes available beyond the end of the supplied input buffer. If
990 // clear, the input buffer contains all remaining input.
991 // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large
992 // enough to hold the entire decompressed stream. If clear, the output buffer is
993 // at least the size of the dictionary (typically 32KB).
994 // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the
995 // decompressed bytes.
996 enum {
997 TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
998 TINFL_FLAG_HAS_MORE_INPUT = 2,
999 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
1000 TINFL_FLAG_COMPUTE_ADLER32 = 8
1001 };
1002
1003 // High level decompression functions:
1004 // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block
1005 // allocated via malloc(). On entry:
1006 // pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data
1007 // to decompress.
1008 // On return:
1009 // Function returns a pointer to the decompressed data, or NULL on failure.
1010 // *pOut_len will be set to the decompressed data's size, which could be larger
1011 // than src_buf_len on uncompressible data. The caller must call mz_free() on
1012 // the returned block when it's no longer needed.
1013 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1014 size_t *pOut_len, int flags);
1015
1016 // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block
1017 // in memory. Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the
1018 // number of bytes written on success.
1019 #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
1020 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1021 const void *pSrc_buf, size_t src_buf_len,
1022 int flags);
1023
1024 // tinfl_decompress_mem_to_callback() decompresses a block in memory to an
1025 // internal 32KB buffer, and a user provided callback function will be called to
1026 // flush the buffer. Returns 1 on success or 0 on failure.
1027 typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1028 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
1029 tinfl_put_buf_func_ptr pPut_buf_func,
1030 void *pPut_buf_user, int flags);
1031
1032 struct tinfl_decompressor_tag;
1033 typedef struct tinfl_decompressor_tag tinfl_decompressor;
1034
1035 // Max size of LZ dictionary.
1036 #define TINFL_LZ_DICT_SIZE 32768
1037
1038 // Return status.
1039 typedef enum {
1040 TINFL_STATUS_BAD_PARAM = -3,
1041 TINFL_STATUS_ADLER32_MISMATCH = -2,
1042 TINFL_STATUS_FAILED = -1,
1043 TINFL_STATUS_DONE = 0,
1044 TINFL_STATUS_NEEDS_MORE_INPUT = 1,
1045 TINFL_STATUS_HAS_MORE_OUTPUT = 2
1046 } tinfl_status;
1047
1048 // Initializes the decompressor to its initial state.
1049 #define tinfl_init(r) \
1050 do { \
1051 (r)->m_state = 0; \
1052 } \
1053 MZ_MACRO_END
1054 #define tinfl_get_adler32(r) (r)->m_check_adler32
1055
1056 // Main low-level decompressor coroutine function. This is the only function
1057 // actually needed for decompression. All the other functions are just
1058 // high-level helpers for improved usability. This is a universal API, i.e. it
1059 // can be used as a building block to build any desired higher level
1060 // decompression API. In the limit case, it can be called once per every byte
1061 // input or output.
1062 tinfl_status tinfl_decompress(tinfl_decompressor *r,
1063 const mz_uint8 *pIn_buf_next,
1064 size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
1065 mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
1066 const mz_uint32 decomp_flags);
1067
1068 // Internal/private bits follow.
1069 enum {
1070 TINFL_MAX_HUFF_TABLES = 3,
1071 TINFL_MAX_HUFF_SYMBOLS_0 = 288,
1072 TINFL_MAX_HUFF_SYMBOLS_1 = 32,
1073 TINFL_MAX_HUFF_SYMBOLS_2 = 19,
1074 TINFL_FAST_LOOKUP_BITS = 10,
1075 TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
1076 };
1077
1078 typedef struct {
1079 mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
1080 mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE],
1081 m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
1082 } tinfl_huff_table;
1083
1084 #if MINIZ_HAS_64BIT_REGISTERS
1085 #define TINFL_USE_64BIT_BITBUF 1
1086 #endif
1087
1088 #if TINFL_USE_64BIT_BITBUF
1089 typedef mz_uint64 tinfl_bit_buf_t;
1090 #define TINFL_BITBUF_SIZE (64)
1091 #else
1092 typedef mz_uint32 tinfl_bit_buf_t;
1093 #define TINFL_BITBUF_SIZE (32)
1094 #endif
1095
1096 struct tinfl_decompressor_tag {
1097 mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type,
1098 m_check_adler32, m_dist, m_counter, m_num_extra,
1099 m_table_sizes[TINFL_MAX_HUFF_TABLES];
1100 tinfl_bit_buf_t m_bit_buf;
1101 size_t m_dist_from_out_buf_start;
1102 tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
1103 mz_uint8 m_raw_header[4],
1104 m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
1105 };
1106
1107 // ------------------- Low-level Compression API Definitions
1108
1109 // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly
1110 // slower, and raw/dynamic blocks will be output more frequently).
1111 #define TDEFL_LESS_MEMORY 0
1112
1113 // tdefl_init() compression flags logically OR'd together (low 12 bits contain
1114 // the max. number of probes per dictionary search): TDEFL_DEFAULT_MAX_PROBES:
1115 // The compressor defaults to 128 dictionary probes per dictionary search.
1116 // 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ
1117 // (slowest/best compression).
1118 enum {
1119 TDEFL_HUFFMAN_ONLY = 0,
1120 TDEFL_DEFAULT_MAX_PROBES = 128,
1121 TDEFL_MAX_PROBES_MASK = 0xFFF
1122 };
1123
1124 // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before
1125 // the deflate data, and the Adler-32 of the source data at the end. Otherwise,
1126 // you'll get raw deflate data. TDEFL_COMPUTE_ADLER32: Always compute the
1127 // adler-32 of the input data (even when not writing zlib headers).
1128 // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more
1129 // efficient lazy parsing. TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to
1130 // decrease the compressor's initialization time to the minimum, but the output
1131 // may vary from run to run given the same input (depending on the contents of
1132 // memory). TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a
1133 // distance of 1) TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
1134 // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
1135 // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
1136 // The low 12 bits are reserved to control the max # of hash probes per
1137 // dictionary lookup (see TDEFL_MAX_PROBES_MASK).
1138 enum {
1139 TDEFL_WRITE_ZLIB_HEADER = 0x01000,
1140 TDEFL_COMPUTE_ADLER32 = 0x02000,
1141 TDEFL_GREEDY_PARSING_FLAG = 0x04000,
1142 TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
1143 TDEFL_RLE_MATCHES = 0x10000,
1144 TDEFL_FILTER_MATCHES = 0x20000,
1145 TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
1146 TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
1147 };
1148
1149 // High level compression functions:
1150 // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block
1151 // allocated via malloc(). On entry:
1152 // pSrc_buf, src_buf_len: Pointer and size of source block to compress.
1153 // flags: The max match finder probes (default is 128) logically OR'd against
1154 // the above flags. Higher probes are slower but improve compression.
1155 // On return:
1156 // Function returns a pointer to the compressed data, or NULL on failure.
1157 // *pOut_len will be set to the compressed data's size, which could be larger
1158 // than src_buf_len on uncompressible data. The caller must free() the returned
1159 // block when it's no longer needed.
1160 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
1161 size_t *pOut_len, int flags);
1162
1163 // tdefl_compress_mem_to_mem() compresses a block in memory to another block in
1164 // memory. Returns 0 on failure.
1165 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
1166 const void *pSrc_buf, size_t src_buf_len,
1167 int flags);
1168
1169 // Compresses an image to a compressed PNG file in memory.
1170 // On entry:
1171 // pImage, w, h, and num_chans describe the image to compress. num_chans may be
1172 // 1, 2, 3, or 4. The image pitch in bytes per scanline will be w*num_chans.
1173 // The leftmost pixel on the top scanline is stored first in memory. level may
1174 // range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED,
1175 // MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL If flip is
1176 // true, the image will be flipped on the Y axis (useful for OpenGL apps).
1177 // On return:
1178 // Function returns a pointer to the compressed data, or NULL on failure.
1179 // *pLen_out will be set to the size of the PNG image file.
1180 // The caller must mz_free() the returned heap block (which will typically be
1181 // larger than *pLen_out) when it's no longer needed.
1182 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
1183 int h, int num_chans,
1184 size_t *pLen_out,
1185 mz_uint level, mz_bool flip);
1186 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
1187 int num_chans, size_t *pLen_out);
1188
1189 // Output stream interface. The compressor uses this interface to write
1190 // compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
1191 typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len,
1192 void *pUser);
1193
1194 // tdefl_compress_mem_to_output() compresses a block to an output stream. The
1195 // above helpers use this function internally.
1196 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
1197 tdefl_put_buf_func_ptr pPut_buf_func,
1198 void *pPut_buf_user, int flags);
1199
1200 enum {
1201 TDEFL_MAX_HUFF_TABLES = 3,
1202 TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
1203 TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
1204 TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
1205 TDEFL_LZ_DICT_SIZE = 32768,
1206 TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,
1207 TDEFL_MIN_MATCH_LEN = 3,
1208 TDEFL_MAX_MATCH_LEN = 258
1209 };
1210
1211 // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed
1212 // output block (using static/fixed Huffman codes).
1213 #if TDEFL_LESS_MEMORY
1214 enum {
1215 TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,
1216 TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1217 TDEFL_MAX_HUFF_SYMBOLS = 288,
1218 TDEFL_LZ_HASH_BITS = 12,
1219 TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1220 TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1221 TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1222 };
1223 #else
1224 enum {
1225 TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,
1226 TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
1227 TDEFL_MAX_HUFF_SYMBOLS = 288,
1228 TDEFL_LZ_HASH_BITS = 15,
1229 TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
1230 TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
1231 TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
1232 };
1233 #endif
1234
1235 // The low-level tdefl functions below may be used directly if the above helper
1236 // functions aren't flexible enough. The low-level functions don't make any heap
1237 // allocations, unlike the above helper functions.
1238 typedef enum {
1239 TDEFL_STATUS_BAD_PARAM = -2,
1240 TDEFL_STATUS_PUT_BUF_FAILED = -1,
1241 TDEFL_STATUS_OKAY = 0,
1242 TDEFL_STATUS_DONE = 1,
1243 } tdefl_status;
1244
1245 // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
1246 typedef enum {
1247 TDEFL_NO_FLUSH = 0,
1248 TDEFL_SYNC_FLUSH = 2,
1249 TDEFL_FULL_FLUSH = 3,
1250 TDEFL_FINISH = 4
1251 } tdefl_flush;
1252
1253 // tdefl's compression state structure.
1254 typedef struct {
1255 tdefl_put_buf_func_ptr m_pPut_buf_func;
1256 void *m_pPut_buf_user;
1257 mz_uint m_flags, m_max_probes[2];
1258 int m_greedy_parsing;
1259 mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
1260 mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
1261 mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in,
1262 m_bit_buffer;
1263 mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit,
1264 m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index,
1265 m_wants_to_finish;
1266 tdefl_status m_prev_return_status;
1267 const void *m_pIn_buf;
1268 void *m_pOut_buf;
1269 size_t *m_pIn_buf_size, *m_pOut_buf_size;
1270 tdefl_flush m_flush;
1271 const mz_uint8 *m_pSrc;
1272 size_t m_src_buf_left, m_out_buf_ofs;
1273 mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
1274 mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1275 mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1276 mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
1277 mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
1278 mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
1279 mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
1280 mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
1281 } tdefl_compressor;
1282
1283 // Initializes the compressor.
1284 // There is no corresponding deinit() function because the tdefl API's do not
1285 // dynamically allocate memory. pBut_buf_func: If NULL, output data will be
1286 // supplied to the specified callback. In this case, the user should call the
1287 // tdefl_compress_buffer() API for compression. If pBut_buf_func is NULL the
1288 // user should always call the tdefl_compress() API. flags: See the above enums
1289 // (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
1290 tdefl_status tdefl_init(tdefl_compressor *d,
1291 tdefl_put_buf_func_ptr pPut_buf_func,
1292 void *pPut_buf_user, int flags);
1293
1294 // Compresses a block of data, consuming as much of the specified input buffer
1295 // as possible, and writing as much compressed data to the specified output
1296 // buffer as possible.
1297 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
1298 size_t *pIn_buf_size, void *pOut_buf,
1299 size_t *pOut_buf_size, tdefl_flush flush);
1300
1301 // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a
1302 // non-NULL tdefl_put_buf_func_ptr. tdefl_compress_buffer() always consumes the
1303 // entire input buffer.
1304 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1305 size_t in_buf_size, tdefl_flush flush);
1306
1307 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1308 mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
1309
1310 // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't
1311 // defined, because it uses some of its macros.
1312 #ifndef MINIZ_NO_ZLIB_APIS
1313 // Create tdefl_compress() flags given zlib-style compression parameters.
1314 // level may range from [0,10] (where 10 is absolute max compression, but may be
1315 // much slower on some files) window_bits may be -15 (raw deflate) or 15 (zlib)
1316 // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY,
1317 // MZ_RLE, or MZ_FIXED
1318 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
1319 int strategy);
1320 #endif // #ifndef MINIZ_NO_ZLIB_APIS
1321
1322 #define MZ_UINT16_MAX (0xFFFFU)
1323 #define MZ_UINT32_MAX (0xFFFFFFFFU)
1324
1325 #ifdef __cplusplus
1326 }
1327 #endif
1328
1329 #endif // MINIZ_HEADER_INCLUDED
1330
1331 // ------------------- End of Header: Implementation follows. (If you only want
1332 // the header, define MINIZ_HEADER_FILE_ONLY.)
1333
1334 #ifndef MINIZ_HEADER_FILE_ONLY
1335
1336 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1337 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1338 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
1339
1340 #include <assert.h>
1341 #include <string.h>
1342
1343 #define MZ_ASSERT(x) assert(x)
1344
1345 #ifdef MINIZ_NO_MALLOC
1346 #define MZ_MALLOC(x) NULL
1347 #define MZ_FREE(x) (void)x, ((void)0)
1348 #define MZ_REALLOC(p, x) NULL
1349 #else
1350 #define MZ_MALLOC(x) malloc(x)
1351 #define MZ_FREE(x) free(x)
1352 #define MZ_REALLOC(p, x) realloc(p, x)
1353 #endif
1354
1355 #define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
1356 #define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))
1357 #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
1358
1359 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1360 #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
1361 #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
1362 #else
1363 #define MZ_READ_LE16(p) \
1364 ((mz_uint32)(((const mz_uint8 *)(p))[0]) | \
1365 ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
1366 #define MZ_READ_LE32(p) \
1367 ((mz_uint32)(((const mz_uint8 *)(p))[0]) | \
1368 ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | \
1369 ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | \
1370 ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
1371 #endif
1372
1373 #define MZ_READ_LE64(p) \
1374 (((mz_uint64)MZ_READ_LE32(p)) | \
1375 (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) \
1376 << 32U))
1377
1378 #ifdef _MSC_VER
1379 #define MZ_FORCEINLINE __forceinline
1380 #elif defined(__GNUC__)
1381 #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
1382 #else
1383 #define MZ_FORCEINLINE inline
1384 #endif
1385
1386 #ifdef __cplusplus
1387 extern "C" {
1388 #endif
1389
1390 // ------------------- zlib-style API's
1391
mz_adler32(mz_ulong adler,const unsigned char * ptr,size_t buf_len)1392 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) {
1393 mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
1394 size_t block_len = buf_len % 5552;
1395 if (!ptr)
1396 return MZ_ADLER32_INIT;
1397 while (buf_len) {
1398 for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
1399 s1 += ptr[0], s2 += s1;
1400 s1 += ptr[1], s2 += s1;
1401 s1 += ptr[2], s2 += s1;
1402 s1 += ptr[3], s2 += s1;
1403 s1 += ptr[4], s2 += s1;
1404 s1 += ptr[5], s2 += s1;
1405 s1 += ptr[6], s2 += s1;
1406 s1 += ptr[7], s2 += s1;
1407 }
1408 for (; i < block_len; ++i)
1409 s1 += *ptr++, s2 += s1;
1410 s1 %= 65521U, s2 %= 65521U;
1411 buf_len -= block_len;
1412 block_len = 5552;
1413 }
1414 return (s2 << 16) + s1;
1415 }
1416
1417 // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C
1418 // implementation that balances processor cache usage against speed":
1419 // http://www.geocities.com/malbrain/
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)1420 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) {
1421 static const mz_uint32 s_crc32[16] = {
1422 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
1423 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1424 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
1425 mz_uint32 crcu32 = (mz_uint32)crc;
1426 if (!ptr)
1427 return MZ_CRC32_INIT;
1428 crcu32 = ~crcu32;
1429 while (buf_len--) {
1430 mz_uint8 b = *ptr++;
1431 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
1432 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
1433 }
1434 return ~crcu32;
1435 }
1436
mz_free(void * p)1437 void mz_free(void *p) { MZ_FREE(p); }
1438
1439 #ifndef MINIZ_NO_ZLIB_APIS
1440
def_alloc_func(void * opaque,size_t items,size_t size)1441 static void *def_alloc_func(void *opaque, size_t items, size_t size) {
1442 (void)opaque, (void)items, (void)size;
1443 return MZ_MALLOC(items * size);
1444 }
def_free_func(void * opaque,void * address)1445 static void def_free_func(void *opaque, void *address) {
1446 (void)opaque, (void)address;
1447 MZ_FREE(address);
1448 }
def_realloc_func(void * opaque,void * address,size_t items,size_t size)1449 static void *def_realloc_func(void *opaque, void *address, size_t items,
1450 size_t size) {
1451 (void)opaque, (void)address, (void)items, (void)size;
1452 return MZ_REALLOC(address, items * size);
1453 }
1454
mz_version(void)1455 const char *mz_version(void) { return MZ_VERSION; }
1456
mz_deflateInit(mz_streamp pStream,int level)1457 int mz_deflateInit(mz_streamp pStream, int level) {
1458 return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9,
1459 MZ_DEFAULT_STRATEGY);
1460 }
1461
mz_deflateInit2(mz_streamp pStream,int level,int method,int window_bits,int mem_level,int strategy)1462 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
1463 int mem_level, int strategy) {
1464 tdefl_compressor *pComp;
1465 mz_uint comp_flags =
1466 TDEFL_COMPUTE_ADLER32 |
1467 tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
1468
1469 if (!pStream)
1470 return MZ_STREAM_ERROR;
1471 if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) ||
1472 ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
1473 (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
1474 return MZ_PARAM_ERROR;
1475
1476 pStream->data_type = 0;
1477 pStream->adler = MZ_ADLER32_INIT;
1478 pStream->msg = NULL;
1479 pStream->reserved = 0;
1480 pStream->total_in = 0;
1481 pStream->total_out = 0;
1482 if (!pStream->zalloc)
1483 pStream->zalloc = def_alloc_func;
1484 if (!pStream->zfree)
1485 pStream->zfree = def_free_func;
1486
1487 pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1,
1488 sizeof(tdefl_compressor));
1489 if (!pComp)
1490 return MZ_MEM_ERROR;
1491
1492 pStream->state = (struct mz_internal_state *)pComp;
1493
1494 if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) {
1495 mz_deflateEnd(pStream);
1496 return MZ_PARAM_ERROR;
1497 }
1498
1499 return MZ_OK;
1500 }
1501
mz_deflateReset(mz_streamp pStream)1502 int mz_deflateReset(mz_streamp pStream) {
1503 if ((!pStream) || (!pStream->state) || (!pStream->zalloc) ||
1504 (!pStream->zfree))
1505 return MZ_STREAM_ERROR;
1506 pStream->total_in = pStream->total_out = 0;
1507 tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL,
1508 ((tdefl_compressor *)pStream->state)->m_flags);
1509 return MZ_OK;
1510 }
1511
mz_deflate(mz_streamp pStream,int flush)1512 int mz_deflate(mz_streamp pStream, int flush) {
1513 size_t in_bytes, out_bytes;
1514 mz_ulong orig_total_in, orig_total_out;
1515 int mz_status = MZ_OK;
1516
1517 if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) ||
1518 (!pStream->next_out))
1519 return MZ_STREAM_ERROR;
1520 if (!pStream->avail_out)
1521 return MZ_BUF_ERROR;
1522
1523 if (flush == MZ_PARTIAL_FLUSH)
1524 flush = MZ_SYNC_FLUSH;
1525
1526 if (((tdefl_compressor *)pStream->state)->m_prev_return_status ==
1527 TDEFL_STATUS_DONE)
1528 return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
1529
1530 orig_total_in = pStream->total_in;
1531 orig_total_out = pStream->total_out;
1532 for (;;) {
1533 tdefl_status defl_status;
1534 in_bytes = pStream->avail_in;
1535 out_bytes = pStream->avail_out;
1536
1537 defl_status = tdefl_compress((tdefl_compressor *)pStream->state,
1538 pStream->next_in, &in_bytes, pStream->next_out,
1539 &out_bytes, (tdefl_flush)flush);
1540 pStream->next_in += (mz_uint)in_bytes;
1541 pStream->avail_in -= (mz_uint)in_bytes;
1542 pStream->total_in += (mz_uint)in_bytes;
1543 pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
1544
1545 pStream->next_out += (mz_uint)out_bytes;
1546 pStream->avail_out -= (mz_uint)out_bytes;
1547 pStream->total_out += (mz_uint)out_bytes;
1548
1549 if (defl_status < 0) {
1550 mz_status = MZ_STREAM_ERROR;
1551 break;
1552 } else if (defl_status == TDEFL_STATUS_DONE) {
1553 mz_status = MZ_STREAM_END;
1554 break;
1555 } else if (!pStream->avail_out)
1556 break;
1557 else if ((!pStream->avail_in) && (flush != MZ_FINISH)) {
1558 if ((flush) || (pStream->total_in != orig_total_in) ||
1559 (pStream->total_out != orig_total_out))
1560 break;
1561 return MZ_BUF_ERROR; // Can't make forward progress without some input.
1562 }
1563 }
1564 return mz_status;
1565 }
1566
mz_deflateEnd(mz_streamp pStream)1567 int mz_deflateEnd(mz_streamp pStream) {
1568 if (!pStream)
1569 return MZ_STREAM_ERROR;
1570 if (pStream->state) {
1571 pStream->zfree(pStream->opaque, pStream->state);
1572 pStream->state = NULL;
1573 }
1574 return MZ_OK;
1575 }
1576
mz_deflateBound(mz_streamp pStream,mz_ulong source_len)1577 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) {
1578 (void)pStream;
1579 // This is really over conservative. (And lame, but it's actually pretty
1580 // tricky to compute a true upper bound given the way tdefl's blocking works.)
1581 return MZ_MAX(128 + (source_len * 110) / 100,
1582 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
1583 }
1584
mz_compress2(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len,int level)1585 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
1586 const unsigned char *pSource, mz_ulong source_len, int level) {
1587 int status;
1588 mz_stream stream;
1589 memset(&stream, 0, sizeof(stream));
1590
1591 // In case mz_ulong is 64-bits (argh I hate longs).
1592 if ((source_len | *pDest_len) > 0xFFFFFFFFU)
1593 return MZ_PARAM_ERROR;
1594
1595 stream.next_in = pSource;
1596 stream.avail_in = (mz_uint32)source_len;
1597 stream.next_out = pDest;
1598 stream.avail_out = (mz_uint32)*pDest_len;
1599
1600 status = mz_deflateInit(&stream, level);
1601 if (status != MZ_OK)
1602 return status;
1603
1604 status = mz_deflate(&stream, MZ_FINISH);
1605 if (status != MZ_STREAM_END) {
1606 mz_deflateEnd(&stream);
1607 return (status == MZ_OK) ? MZ_BUF_ERROR : status;
1608 }
1609
1610 *pDest_len = stream.total_out;
1611 return mz_deflateEnd(&stream);
1612 }
1613
mz_compress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)1614 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
1615 const unsigned char *pSource, mz_ulong source_len) {
1616 return mz_compress2(pDest, pDest_len, pSource, source_len,
1617 MZ_DEFAULT_COMPRESSION);
1618 }
1619
mz_compressBound(mz_ulong source_len)1620 mz_ulong mz_compressBound(mz_ulong source_len) {
1621 return mz_deflateBound(NULL, source_len);
1622 }
1623
1624 typedef struct {
1625 tinfl_decompressor m_decomp;
1626 mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
1627 int m_window_bits;
1628 mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
1629 tinfl_status m_last_status;
1630 } inflate_state;
1631
mz_inflateInit2(mz_streamp pStream,int window_bits)1632 int mz_inflateInit2(mz_streamp pStream, int window_bits) {
1633 inflate_state *pDecomp;
1634 if (!pStream)
1635 return MZ_STREAM_ERROR;
1636 if ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
1637 (-window_bits != MZ_DEFAULT_WINDOW_BITS))
1638 return MZ_PARAM_ERROR;
1639
1640 pStream->data_type = 0;
1641 pStream->adler = 0;
1642 pStream->msg = NULL;
1643 pStream->total_in = 0;
1644 pStream->total_out = 0;
1645 pStream->reserved = 0;
1646 if (!pStream->zalloc)
1647 pStream->zalloc = def_alloc_func;
1648 if (!pStream->zfree)
1649 pStream->zfree = def_free_func;
1650
1651 pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1,
1652 sizeof(inflate_state));
1653 if (!pDecomp)
1654 return MZ_MEM_ERROR;
1655
1656 pStream->state = (struct mz_internal_state *)pDecomp;
1657
1658 tinfl_init(&pDecomp->m_decomp);
1659 pDecomp->m_dict_ofs = 0;
1660 pDecomp->m_dict_avail = 0;
1661 pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
1662 pDecomp->m_first_call = 1;
1663 pDecomp->m_has_flushed = 0;
1664 pDecomp->m_window_bits = window_bits;
1665
1666 return MZ_OK;
1667 }
1668
mz_inflateInit(mz_streamp pStream)1669 int mz_inflateInit(mz_streamp pStream) {
1670 return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
1671 }
1672
mz_inflate(mz_streamp pStream,int flush)1673 int mz_inflate(mz_streamp pStream, int flush) {
1674 inflate_state *pState;
1675 mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
1676 size_t in_bytes, out_bytes, orig_avail_in;
1677 tinfl_status status;
1678
1679 if ((!pStream) || (!pStream->state))
1680 return MZ_STREAM_ERROR;
1681 if (flush == MZ_PARTIAL_FLUSH)
1682 flush = MZ_SYNC_FLUSH;
1683 if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
1684 return MZ_STREAM_ERROR;
1685
1686 pState = (inflate_state *)pStream->state;
1687 if (pState->m_window_bits > 0)
1688 decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
1689 orig_avail_in = pStream->avail_in;
1690
1691 first_call = pState->m_first_call;
1692 pState->m_first_call = 0;
1693 if (pState->m_last_status < 0)
1694 return MZ_DATA_ERROR;
1695
1696 if (pState->m_has_flushed && (flush != MZ_FINISH))
1697 return MZ_STREAM_ERROR;
1698 pState->m_has_flushed |= (flush == MZ_FINISH);
1699
1700 if ((flush == MZ_FINISH) && (first_call)) {
1701 // MZ_FINISH on the first call implies that the input and output buffers are
1702 // large enough to hold the entire compressed/decompressed file.
1703 decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1704 in_bytes = pStream->avail_in;
1705 out_bytes = pStream->avail_out;
1706 status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes,
1707 pStream->next_out, pStream->next_out, &out_bytes,
1708 decomp_flags);
1709 pState->m_last_status = status;
1710 pStream->next_in += (mz_uint)in_bytes;
1711 pStream->avail_in -= (mz_uint)in_bytes;
1712 pStream->total_in += (mz_uint)in_bytes;
1713 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1714 pStream->next_out += (mz_uint)out_bytes;
1715 pStream->avail_out -= (mz_uint)out_bytes;
1716 pStream->total_out += (mz_uint)out_bytes;
1717
1718 if (status < 0)
1719 return MZ_DATA_ERROR;
1720 else if (status != TINFL_STATUS_DONE) {
1721 pState->m_last_status = TINFL_STATUS_FAILED;
1722 return MZ_BUF_ERROR;
1723 }
1724 return MZ_STREAM_END;
1725 }
1726 // flush != MZ_FINISH then we must assume there's more input.
1727 if (flush != MZ_FINISH)
1728 decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
1729
1730 if (pState->m_dict_avail) {
1731 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1732 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1733 pStream->next_out += n;
1734 pStream->avail_out -= n;
1735 pStream->total_out += n;
1736 pState->m_dict_avail -= n;
1737 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1738 return ((pState->m_last_status == TINFL_STATUS_DONE) &&
1739 (!pState->m_dict_avail))
1740 ? MZ_STREAM_END
1741 : MZ_OK;
1742 }
1743
1744 for (;;) {
1745 in_bytes = pStream->avail_in;
1746 out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
1747
1748 status = tinfl_decompress(
1749 &pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict,
1750 pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
1751 pState->m_last_status = status;
1752
1753 pStream->next_in += (mz_uint)in_bytes;
1754 pStream->avail_in -= (mz_uint)in_bytes;
1755 pStream->total_in += (mz_uint)in_bytes;
1756 pStream->adler = tinfl_get_adler32(&pState->m_decomp);
1757
1758 pState->m_dict_avail = (mz_uint)out_bytes;
1759
1760 n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
1761 memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
1762 pStream->next_out += n;
1763 pStream->avail_out -= n;
1764 pStream->total_out += n;
1765 pState->m_dict_avail -= n;
1766 pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
1767
1768 if (status < 0)
1769 return MZ_DATA_ERROR; // Stream is corrupted (there could be some
1770 // uncompressed data left in the output dictionary -
1771 // oh well).
1772 else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
1773 return MZ_BUF_ERROR; // Signal caller that we can't make forward progress
1774 // without supplying more input or by setting flush
1775 // to MZ_FINISH.
1776 else if (flush == MZ_FINISH) {
1777 // The output buffer MUST be large to hold the remaining uncompressed data
1778 // when flush==MZ_FINISH.
1779 if (status == TINFL_STATUS_DONE)
1780 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
1781 // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's
1782 // at least 1 more byte on the way. If there's no more room left in the
1783 // output buffer then something is wrong.
1784 else if (!pStream->avail_out)
1785 return MZ_BUF_ERROR;
1786 } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) ||
1787 (!pStream->avail_out) || (pState->m_dict_avail))
1788 break;
1789 }
1790
1791 return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail))
1792 ? MZ_STREAM_END
1793 : MZ_OK;
1794 }
1795
mz_inflateEnd(mz_streamp pStream)1796 int mz_inflateEnd(mz_streamp pStream) {
1797 if (!pStream)
1798 return MZ_STREAM_ERROR;
1799 if (pStream->state) {
1800 pStream->zfree(pStream->opaque, pStream->state);
1801 pStream->state = NULL;
1802 }
1803 return MZ_OK;
1804 }
1805
mz_uncompress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)1806 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
1807 const unsigned char *pSource, mz_ulong source_len) {
1808 mz_stream stream;
1809 int status;
1810 memset(&stream, 0, sizeof(stream));
1811
1812 // In case mz_ulong is 64-bits (argh I hate longs).
1813 if ((source_len | *pDest_len) > 0xFFFFFFFFU)
1814 return MZ_PARAM_ERROR;
1815
1816 stream.next_in = pSource;
1817 stream.avail_in = (mz_uint32)source_len;
1818 stream.next_out = pDest;
1819 stream.avail_out = (mz_uint32)*pDest_len;
1820
1821 status = mz_inflateInit(&stream);
1822 if (status != MZ_OK)
1823 return status;
1824
1825 status = mz_inflate(&stream, MZ_FINISH);
1826 if (status != MZ_STREAM_END) {
1827 mz_inflateEnd(&stream);
1828 return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR
1829 : status;
1830 }
1831 *pDest_len = stream.total_out;
1832
1833 return mz_inflateEnd(&stream);
1834 }
1835
mz_error(int err)1836 const char *mz_error(int err) {
1837 static struct {
1838 int m_err;
1839 const char *m_pDesc;
1840 } s_error_descs[] = {{MZ_OK, ""},
1841 {MZ_STREAM_END, "stream end"},
1842 {MZ_NEED_DICT, "need dictionary"},
1843 {MZ_ERRNO, "file error"},
1844 {MZ_STREAM_ERROR, "stream error"},
1845 {MZ_DATA_ERROR, "data error"},
1846 {MZ_MEM_ERROR, "out of memory"},
1847 {MZ_BUF_ERROR, "buf error"},
1848 {MZ_VERSION_ERROR, "version error"},
1849 {MZ_PARAM_ERROR, "parameter error"}};
1850 mz_uint i;
1851 for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
1852 if (s_error_descs[i].m_err == err)
1853 return s_error_descs[i].m_pDesc;
1854 return NULL;
1855 }
1856
1857 #endif // MINIZ_NO_ZLIB_APIS
1858
1859 // ------------------- Low-level Decompression (completely independent from all
1860 // compression API's)
1861
1862 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
1863 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
1864
1865 #define TINFL_CR_BEGIN \
1866 switch (r->m_state) { \
1867 case 0:
1868 #define TINFL_CR_RETURN(state_index, result) \
1869 do { \
1870 status = result; \
1871 r->m_state = state_index; \
1872 goto common_exit; \
1873 case state_index:; \
1874 } \
1875 MZ_MACRO_END
1876 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
1877 do { \
1878 for (;;) { \
1879 TINFL_CR_RETURN(state_index, result); \
1880 } \
1881 } \
1882 MZ_MACRO_END
1883 #define TINFL_CR_FINISH }
1884
1885 // TODO: If the caller has indicated that there's no more input, and we attempt
1886 // to read beyond the input buf, then something is wrong with the input because
1887 // the inflator never reads ahead more than it needs to. Currently
1888 // TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
1889 #define TINFL_GET_BYTE(state_index, c) \
1890 do { \
1891 if (pIn_buf_cur >= pIn_buf_end) { \
1892 for (;;) { \
1893 if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
1894 TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
1895 if (pIn_buf_cur < pIn_buf_end) { \
1896 c = *pIn_buf_cur++; \
1897 break; \
1898 } \
1899 } else { \
1900 c = 0; \
1901 break; \
1902 } \
1903 } \
1904 } else \
1905 c = *pIn_buf_cur++; \
1906 } \
1907 MZ_MACRO_END
1908
1909 #define TINFL_NEED_BITS(state_index, n) \
1910 do { \
1911 mz_uint c; \
1912 TINFL_GET_BYTE(state_index, c); \
1913 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
1914 num_bits += 8; \
1915 } while (num_bits < (mz_uint)(n))
1916 #define TINFL_SKIP_BITS(state_index, n) \
1917 do { \
1918 if (num_bits < (mz_uint)(n)) { \
1919 TINFL_NEED_BITS(state_index, n); \
1920 } \
1921 bit_buf >>= (n); \
1922 num_bits -= (n); \
1923 } \
1924 MZ_MACRO_END
1925 #define TINFL_GET_BITS(state_index, b, n) \
1926 do { \
1927 if (num_bits < (mz_uint)(n)) { \
1928 TINFL_NEED_BITS(state_index, n); \
1929 } \
1930 b = bit_buf & ((1 << (n)) - 1); \
1931 bit_buf >>= (n); \
1932 num_bits -= (n); \
1933 } \
1934 MZ_MACRO_END
1935
1936 // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
1937 // remaining in the input buffer falls below 2. It reads just enough bytes from
1938 // the input stream that are needed to decode the next Huffman code (and
1939 // absolutely no more). It works by trying to fully decode a Huffman code by
1940 // using whatever bits are currently present in the bit buffer. If this fails,
1941 // it reads another byte, and tries again until it succeeds or until the bit
1942 // buffer contains >=15 bits (deflate's max. Huffman code size).
1943 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
1944 do { \
1945 temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
1946 if (temp >= 0) { \
1947 code_len = temp >> 9; \
1948 if ((code_len) && (num_bits >= code_len)) \
1949 break; \
1950 } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
1951 code_len = TINFL_FAST_LOOKUP_BITS; \
1952 do { \
1953 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
1954 } while ((temp < 0) && (num_bits >= (code_len + 1))); \
1955 if (temp >= 0) \
1956 break; \
1957 } \
1958 TINFL_GET_BYTE(state_index, c); \
1959 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
1960 num_bits += 8; \
1961 } while (num_bits < 15);
1962
1963 // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex
1964 // than you would initially expect because the zlib API expects the decompressor
1965 // to never read beyond the final byte of the deflate stream. (In other words,
1966 // when this macro wants to read another byte from the input, it REALLY needs
1967 // another byte in order to fully decode the next Huffman code.) Handling this
1968 // properly is particularly important on raw deflate (non-zlib) streams, which
1969 // aren't followed by a byte aligned adler-32. The slow path is only executed at
1970 // the very end of the input buffer.
1971 #define TINFL_HUFF_DECODE(state_index, sym, pHuff) \
1972 do { \
1973 int temp; \
1974 mz_uint code_len, c; \
1975 if (num_bits < 15) { \
1976 if ((pIn_buf_end - pIn_buf_cur) < 2) { \
1977 TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
1978 } else { \
1979 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | \
1980 (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
1981 pIn_buf_cur += 2; \
1982 num_bits += 16; \
1983 } \
1984 } \
1985 if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \
1986 0) \
1987 code_len = temp >> 9, temp &= 511; \
1988 else { \
1989 code_len = TINFL_FAST_LOOKUP_BITS; \
1990 do { \
1991 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
1992 } while (temp < 0); \
1993 } \
1994 sym = temp; \
1995 bit_buf >>= code_len; \
1996 num_bits -= code_len; \
1997 } \
1998 MZ_MACRO_END
1999
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)2000 tinfl_status tinfl_decompress(tinfl_decompressor *r,
2001 const mz_uint8 *pIn_buf_next,
2002 size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
2003 mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
2004 const mz_uint32 decomp_flags) {
2005 static const int s_length_base[31] = {
2006 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
2007 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
2008 static const int s_length_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
2009 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
2010 4, 4, 5, 5, 5, 5, 0, 0, 0};
2011 static const int s_dist_base[32] = {
2012 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33,
2013 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
2014 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0};
2015 static const int s_dist_extra[32] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
2016 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
2017 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
2018 static const mz_uint8 s_length_dezigzag[19] = {
2019 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2020 static const int s_min_table_sizes[3] = {257, 1, 4};
2021
2022 tinfl_status status = TINFL_STATUS_FAILED;
2023 mz_uint32 num_bits, dist, counter, num_extra;
2024 tinfl_bit_buf_t bit_buf;
2025 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
2026 pIn_buf_next + *pIn_buf_size;
2027 mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
2028 pOut_buf_next + *pOut_buf_size;
2029 size_t out_buf_size_mask =
2030 (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
2031 ? (size_t)-1
2032 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1,
2033 dist_from_out_buf_start;
2034
2035 // Ensure the output buffer's size is a power of 2, unless the output buffer
2036 // is large enough to hold the entire output file (in which case it doesn't
2037 // matter).
2038 if (((out_buf_size_mask + 1) & out_buf_size_mask) ||
2039 (pOut_buf_next < pOut_buf_start)) {
2040 *pIn_buf_size = *pOut_buf_size = 0;
2041 return TINFL_STATUS_BAD_PARAM;
2042 }
2043
2044 num_bits = r->m_num_bits;
2045 bit_buf = r->m_bit_buf;
2046 dist = r->m_dist;
2047 counter = r->m_counter;
2048 num_extra = r->m_num_extra;
2049 dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2050 TINFL_CR_BEGIN
2051
2052 bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2053 r->m_z_adler32 = r->m_check_adler32 = 1;
2054 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2055 TINFL_GET_BYTE(1, r->m_zhdr0);
2056 TINFL_GET_BYTE(2, r->m_zhdr1);
2057 counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) ||
2058 (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2059 if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2060 counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) ||
2061 ((out_buf_size_mask + 1) <
2062 (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2063 if (counter) {
2064 TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2065 }
2066 }
2067
2068 do {
2069 TINFL_GET_BITS(3, r->m_final, 3);
2070 r->m_type = r->m_final >> 1;
2071 if (r->m_type == 0) {
2072 TINFL_SKIP_BITS(5, num_bits & 7);
2073 for (counter = 0; counter < 4; ++counter) {
2074 if (num_bits)
2075 TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2076 else
2077 TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2078 }
2079 if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) !=
2080 (mz_uint)(0xFFFF ^
2081 (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) {
2082 TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2083 }
2084 while ((counter) && (num_bits)) {
2085 TINFL_GET_BITS(51, dist, 8);
2086 while (pOut_buf_cur >= pOut_buf_end) {
2087 TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2088 }
2089 *pOut_buf_cur++ = (mz_uint8)dist;
2090 counter--;
2091 }
2092 while (counter) {
2093 size_t n;
2094 while (pOut_buf_cur >= pOut_buf_end) {
2095 TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2096 }
2097 while (pIn_buf_cur >= pIn_buf_end) {
2098 if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) {
2099 TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
2100 } else {
2101 TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
2102 }
2103 }
2104 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur),
2105 (size_t)(pIn_buf_end - pIn_buf_cur)),
2106 counter);
2107 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2108 pIn_buf_cur += n;
2109 pOut_buf_cur += n;
2110 counter -= (mz_uint)n;
2111 }
2112 } else if (r->m_type == 3) {
2113 TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2114 } else {
2115 if (r->m_type == 1) {
2116 mz_uint8 *p = r->m_tables[0].m_code_size;
2117 mz_uint i;
2118 r->m_table_sizes[0] = 288;
2119 r->m_table_sizes[1] = 32;
2120 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2121 for (i = 0; i <= 143; ++i)
2122 *p++ = 8;
2123 for (; i <= 255; ++i)
2124 *p++ = 9;
2125 for (; i <= 279; ++i)
2126 *p++ = 7;
2127 for (; i <= 287; ++i)
2128 *p++ = 8;
2129 } else {
2130 for (counter = 0; counter < 3; counter++) {
2131 TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2132 r->m_table_sizes[counter] += s_min_table_sizes[counter];
2133 }
2134 MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2135 for (counter = 0; counter < r->m_table_sizes[2]; counter++) {
2136 mz_uint s;
2137 TINFL_GET_BITS(14, s, 3);
2138 r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2139 }
2140 r->m_table_sizes[2] = 19;
2141 }
2142 for (; (int)r->m_type >= 0; r->m_type--) {
2143 int tree_next, tree_cur;
2144 tinfl_huff_table *pTable;
2145 mz_uint i, j, used_syms, total, sym_index, next_code[17],
2146 total_syms[16];
2147 pTable = &r->m_tables[r->m_type];
2148 MZ_CLEAR_OBJ(total_syms);
2149 MZ_CLEAR_OBJ(pTable->m_look_up);
2150 MZ_CLEAR_OBJ(pTable->m_tree);
2151 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2152 total_syms[pTable->m_code_size[i]]++;
2153 used_syms = 0, total = 0;
2154 next_code[0] = next_code[1] = 0;
2155 for (i = 1; i <= 15; ++i) {
2156 used_syms += total_syms[i];
2157 next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2158 }
2159 if ((65536 != total) && (used_syms > 1)) {
2160 TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2161 }
2162 for (tree_next = -1, sym_index = 0;
2163 sym_index < r->m_table_sizes[r->m_type]; ++sym_index) {
2164 mz_uint rev_code = 0, l, cur_code,
2165 code_size = pTable->m_code_size[sym_index];
2166 if (!code_size)
2167 continue;
2168 cur_code = next_code[code_size]++;
2169 for (l = code_size; l > 0; l--, cur_code >>= 1)
2170 rev_code = (rev_code << 1) | (cur_code & 1);
2171 if (code_size <= TINFL_FAST_LOOKUP_BITS) {
2172 mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2173 while (rev_code < TINFL_FAST_LOOKUP_SIZE) {
2174 pTable->m_look_up[rev_code] = k;
2175 rev_code += (1 << code_size);
2176 }
2177 continue;
2178 }
2179 if (0 ==
2180 (tree_cur = pTable->m_look_up[rev_code &
2181 (TINFL_FAST_LOOKUP_SIZE - 1)])) {
2182 pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] =
2183 (mz_int16)tree_next;
2184 tree_cur = tree_next;
2185 tree_next -= 2;
2186 }
2187 rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2188 for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) {
2189 tree_cur -= ((rev_code >>= 1) & 1);
2190 if (!pTable->m_tree[-tree_cur - 1]) {
2191 pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2192 tree_cur = tree_next;
2193 tree_next -= 2;
2194 } else
2195 tree_cur = pTable->m_tree[-tree_cur - 1];
2196 }
2197 tree_cur -= ((rev_code >>= 1) & 1);
2198 pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2199 }
2200 if (r->m_type == 2) {
2201 for (counter = 0;
2202 counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) {
2203 mz_uint s;
2204 TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2205 if (dist < 16) {
2206 r->m_len_codes[counter++] = (mz_uint8)dist;
2207 continue;
2208 }
2209 if ((dist == 16) && (!counter)) {
2210 TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2211 }
2212 num_extra = "\02\03\07"[dist - 16];
2213 TINFL_GET_BITS(18, s, num_extra);
2214 s += "\03\03\013"[dist - 16];
2215 TINFL_MEMSET(r->m_len_codes + counter,
2216 (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2217 counter += s;
2218 }
2219 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) {
2220 TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2221 }
2222 TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes,
2223 r->m_table_sizes[0]);
2224 TINFL_MEMCPY(r->m_tables[1].m_code_size,
2225 r->m_len_codes + r->m_table_sizes[0],
2226 r->m_table_sizes[1]);
2227 }
2228 }
2229 for (;;) {
2230 mz_uint8 *pSrc;
2231 for (;;) {
2232 if (((pIn_buf_end - pIn_buf_cur) < 4) ||
2233 ((pOut_buf_end - pOut_buf_cur) < 2)) {
2234 TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2235 if (counter >= 256)
2236 break;
2237 while (pOut_buf_cur >= pOut_buf_end) {
2238 TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2239 }
2240 *pOut_buf_cur++ = (mz_uint8)counter;
2241 } else {
2242 int sym2;
2243 mz_uint code_len;
2244 #if TINFL_USE_64BIT_BITBUF
2245 if (num_bits < 30) {
2246 bit_buf |=
2247 (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2248 pIn_buf_cur += 4;
2249 num_bits += 32;
2250 }
2251 #else
2252 if (num_bits < 15) {
2253 bit_buf |=
2254 (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2255 pIn_buf_cur += 2;
2256 num_bits += 16;
2257 }
2258 #endif
2259 if ((sym2 =
2260 r->m_tables[0]
2261 .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2262 0)
2263 code_len = sym2 >> 9;
2264 else {
2265 code_len = TINFL_FAST_LOOKUP_BITS;
2266 do {
2267 sym2 = r->m_tables[0]
2268 .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2269 } while (sym2 < 0);
2270 }
2271 counter = sym2;
2272 bit_buf >>= code_len;
2273 num_bits -= code_len;
2274 if (counter & 256)
2275 break;
2276
2277 #if !TINFL_USE_64BIT_BITBUF
2278 if (num_bits < 15) {
2279 bit_buf |=
2280 (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2281 pIn_buf_cur += 2;
2282 num_bits += 16;
2283 }
2284 #endif
2285 if ((sym2 =
2286 r->m_tables[0]
2287 .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2288 0)
2289 code_len = sym2 >> 9;
2290 else {
2291 code_len = TINFL_FAST_LOOKUP_BITS;
2292 do {
2293 sym2 = r->m_tables[0]
2294 .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2295 } while (sym2 < 0);
2296 }
2297 bit_buf >>= code_len;
2298 num_bits -= code_len;
2299
2300 pOut_buf_cur[0] = (mz_uint8)counter;
2301 if (sym2 & 256) {
2302 pOut_buf_cur++;
2303 counter = sym2;
2304 break;
2305 }
2306 pOut_buf_cur[1] = (mz_uint8)sym2;
2307 pOut_buf_cur += 2;
2308 }
2309 }
2310 if ((counter &= 511) == 256)
2311 break;
2312
2313 num_extra = s_length_extra[counter - 257];
2314 counter = s_length_base[counter - 257];
2315 if (num_extra) {
2316 mz_uint extra_bits;
2317 TINFL_GET_BITS(25, extra_bits, num_extra);
2318 counter += extra_bits;
2319 }
2320
2321 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2322 num_extra = s_dist_extra[dist];
2323 dist = s_dist_base[dist];
2324 if (num_extra) {
2325 mz_uint extra_bits;
2326 TINFL_GET_BITS(27, extra_bits, num_extra);
2327 dist += extra_bits;
2328 }
2329
2330 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2331 if ((dist > dist_from_out_buf_start) &&
2332 (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) {
2333 TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2334 }
2335
2336 pSrc = pOut_buf_start +
2337 ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2338
2339 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
2340 while (counter--) {
2341 while (pOut_buf_cur >= pOut_buf_end) {
2342 TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2343 }
2344 *pOut_buf_cur++ =
2345 pOut_buf_start[(dist_from_out_buf_start++ - dist) &
2346 out_buf_size_mask];
2347 }
2348 continue;
2349 }
2350 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2351 else if ((counter >= 9) && (counter <= dist)) {
2352 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2353 do {
2354 ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2355 ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2356 pOut_buf_cur += 8;
2357 } while ((pSrc += 8) < pSrc_end);
2358 if ((counter &= 7) < 3) {
2359 if (counter) {
2360 pOut_buf_cur[0] = pSrc[0];
2361 if (counter > 1)
2362 pOut_buf_cur[1] = pSrc[1];
2363 pOut_buf_cur += counter;
2364 }
2365 continue;
2366 }
2367 }
2368 #endif
2369 do {
2370 pOut_buf_cur[0] = pSrc[0];
2371 pOut_buf_cur[1] = pSrc[1];
2372 pOut_buf_cur[2] = pSrc[2];
2373 pOut_buf_cur += 3;
2374 pSrc += 3;
2375 } while ((int)(counter -= 3) > 2);
2376 if ((int)counter > 0) {
2377 pOut_buf_cur[0] = pSrc[0];
2378 if ((int)counter > 1)
2379 pOut_buf_cur[1] = pSrc[1];
2380 pOut_buf_cur += counter;
2381 }
2382 }
2383 }
2384 } while (!(r->m_final & 1));
2385 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2386 TINFL_SKIP_BITS(32, num_bits & 7);
2387 for (counter = 0; counter < 4; ++counter) {
2388 mz_uint s;
2389 if (num_bits)
2390 TINFL_GET_BITS(41, s, 8);
2391 else
2392 TINFL_GET_BYTE(42, s);
2393 r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2394 }
2395 }
2396 TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2397 TINFL_CR_FINISH
2398
2399 common_exit:
2400 r->m_num_bits = num_bits;
2401 r->m_bit_buf = bit_buf;
2402 r->m_dist = dist;
2403 r->m_counter = counter;
2404 r->m_num_extra = num_extra;
2405 r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2406 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2407 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2408 if ((decomp_flags &
2409 (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) &&
2410 (status >= 0)) {
2411 const mz_uint8 *ptr = pOut_buf_next;
2412 size_t buf_len = *pOut_buf_size;
2413 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff,
2414 s2 = r->m_check_adler32 >> 16;
2415 size_t block_len = buf_len % 5552;
2416 while (buf_len) {
2417 for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
2418 s1 += ptr[0], s2 += s1;
2419 s1 += ptr[1], s2 += s1;
2420 s1 += ptr[2], s2 += s1;
2421 s1 += ptr[3], s2 += s1;
2422 s1 += ptr[4], s2 += s1;
2423 s1 += ptr[5], s2 += s1;
2424 s1 += ptr[6], s2 += s1;
2425 s1 += ptr[7], s2 += s1;
2426 }
2427 for (; i < block_len; ++i)
2428 s1 += *ptr++, s2 += s1;
2429 s1 %= 65521U, s2 %= 65521U;
2430 buf_len -= block_len;
2431 block_len = 5552;
2432 }
2433 r->m_check_adler32 = (s2 << 16) + s1;
2434 if ((status == TINFL_STATUS_DONE) &&
2435 (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) &&
2436 (r->m_check_adler32 != r->m_z_adler32))
2437 status = TINFL_STATUS_ADLER32_MISMATCH;
2438 }
2439 return status;
2440 }
2441
2442 // Higher level helper functions.
tinfl_decompress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2443 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
2444 size_t *pOut_len, int flags) {
2445 tinfl_decompressor decomp;
2446 void *pBuf = NULL, *pNew_buf;
2447 size_t src_buf_ofs = 0, out_buf_capacity = 0;
2448 *pOut_len = 0;
2449 tinfl_init(&decomp);
2450 for (;;) {
2451 size_t src_buf_size = src_buf_len - src_buf_ofs,
2452 dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2453 tinfl_status status = tinfl_decompress(
2454 &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
2455 (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
2456 &dst_buf_size,
2457 (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2458 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2459 if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
2460 MZ_FREE(pBuf);
2461 *pOut_len = 0;
2462 return NULL;
2463 }
2464 src_buf_ofs += src_buf_size;
2465 *pOut_len += dst_buf_size;
2466 if (status == TINFL_STATUS_DONE)
2467 break;
2468 new_out_buf_capacity = out_buf_capacity * 2;
2469 if (new_out_buf_capacity < 128)
2470 new_out_buf_capacity = 128;
2471 pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2472 if (!pNew_buf) {
2473 MZ_FREE(pBuf);
2474 *pOut_len = 0;
2475 return NULL;
2476 }
2477 pBuf = pNew_buf;
2478 out_buf_capacity = new_out_buf_capacity;
2479 }
2480 return pBuf;
2481 }
2482
tinfl_decompress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2483 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
2484 const void *pSrc_buf, size_t src_buf_len,
2485 int flags) {
2486 tinfl_decompressor decomp;
2487 tinfl_status status;
2488 tinfl_init(&decomp);
2489 status =
2490 tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len,
2491 (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
2492 (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2493 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2494 return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
2495 : out_buf_len;
2496 }
2497
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)2498 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
2499 tinfl_put_buf_func_ptr pPut_buf_func,
2500 void *pPut_buf_user, int flags) {
2501 int result = 0;
2502 tinfl_decompressor decomp;
2503 mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2504 size_t in_buf_ofs = 0, dict_ofs = 0;
2505 if (!pDict)
2506 return TINFL_STATUS_FAILED;
2507 tinfl_init(&decomp);
2508 for (;;) {
2509 size_t in_buf_size = *pIn_buf_size - in_buf_ofs,
2510 dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2511 tinfl_status status =
2512 tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
2513 &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2514 (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
2515 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2516 in_buf_ofs += in_buf_size;
2517 if ((dst_buf_size) &&
2518 (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2519 break;
2520 if (status != TINFL_STATUS_HAS_MORE_OUTPUT) {
2521 result = (status == TINFL_STATUS_DONE);
2522 break;
2523 }
2524 dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2525 }
2526 MZ_FREE(pDict);
2527 *pIn_buf_size = in_buf_ofs;
2528 return result;
2529 }
2530
2531 // ------------------- Low-level Compression (independent from all decompression
2532 // API's)
2533
2534 // Purposely making these tables static for faster init and thread safety.
2535 static const mz_uint16 s_tdefl_len_sym[256] = {
2536 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268,
2537 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272,
2538 272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274,
2539 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276,
2540 276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
2541 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
2542 278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279,
2543 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
2544 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281,
2545 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
2546 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282,
2547 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
2548 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283,
2549 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
2550 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
2551 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2552 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2553 285};
2554
2555 static const mz_uint8 s_tdefl_len_extra[256] = {
2556 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2557 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2558 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
2559 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2560 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2561 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2562 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2563 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2564 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2565 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2566 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0};
2567
2568 static const mz_uint8 s_tdefl_small_dist_sym[512] = {
2569 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8,
2570 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
2571 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
2572 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2573 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2574 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2575 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
2576 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2577 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2578 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2579 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2580 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2581 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2582 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2583 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2584 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2585 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2586 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2587 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2588 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2589 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2590 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2591 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2592 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2593 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2594 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2595 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17};
2596
2597 static const mz_uint8 s_tdefl_small_dist_extra[512] = {
2598 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,
2599 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,
2600 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2601 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2602 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2603 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2604 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2605 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2606 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2607 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2608 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2609 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2610 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2611 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2612 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2613 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2614 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2615 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2616 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2617 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2618 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
2619
2620 static const mz_uint8 s_tdefl_large_dist_sym[128] = {
2621 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24,
2622 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
2623 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
2624 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2625 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2626 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2627 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
2628
2629 static const mz_uint8 s_tdefl_large_dist_extra[128] = {
2630 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
2631 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
2632 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2633 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2634 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2635 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2636 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
2637
2638 // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
2639 // values.
2640 typedef struct {
2641 mz_uint16 m_key, m_sym_index;
2642 } tdefl_sym_freq;
tdefl_radix_sort_syms(mz_uint num_syms,tdefl_sym_freq * pSyms0,tdefl_sym_freq * pSyms1)2643 static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
2644 tdefl_sym_freq *pSyms0,
2645 tdefl_sym_freq *pSyms1) {
2646 mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
2647 tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
2648 MZ_CLEAR_OBJ(hist);
2649 for (i = 0; i < num_syms; i++) {
2650 mz_uint freq = pSyms0[i].m_key;
2651 hist[freq & 0xFF]++;
2652 hist[256 + ((freq >> 8) & 0xFF)]++;
2653 }
2654 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
2655 total_passes--;
2656 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
2657 const mz_uint32 *pHist = &hist[pass << 8];
2658 mz_uint offsets[256], cur_ofs = 0;
2659 for (i = 0; i < 256; i++) {
2660 offsets[i] = cur_ofs;
2661 cur_ofs += pHist[i];
2662 }
2663 for (i = 0; i < num_syms; i++)
2664 pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] =
2665 pCur_syms[i];
2666 {
2667 tdefl_sym_freq *t = pCur_syms;
2668 pCur_syms = pNew_syms;
2669 pNew_syms = t;
2670 }
2671 }
2672 return pCur_syms;
2673 }
2674
2675 // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat,
2676 // alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
tdefl_calculate_minimum_redundancy(tdefl_sym_freq * A,int n)2677 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
2678 int root, leaf, next, avbl, used, dpth;
2679 if (n == 0)
2680 return;
2681 else if (n == 1) {
2682 A[0].m_key = 1;
2683 return;
2684 }
2685 A[0].m_key += A[1].m_key;
2686 root = 0;
2687 leaf = 2;
2688 for (next = 1; next < n - 1; next++) {
2689 if (leaf >= n || A[root].m_key < A[leaf].m_key) {
2690 A[next].m_key = A[root].m_key;
2691 A[root++].m_key = (mz_uint16)next;
2692 } else
2693 A[next].m_key = A[leaf++].m_key;
2694 if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) {
2695 A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
2696 A[root++].m_key = (mz_uint16)next;
2697 } else
2698 A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
2699 }
2700 A[n - 2].m_key = 0;
2701 for (next = n - 3; next >= 0; next--)
2702 A[next].m_key = A[A[next].m_key].m_key + 1;
2703 avbl = 1;
2704 used = dpth = 0;
2705 root = n - 2;
2706 next = n - 1;
2707 while (avbl > 0) {
2708 while (root >= 0 && (int)A[root].m_key == dpth) {
2709 used++;
2710 root--;
2711 }
2712 while (avbl > used) {
2713 A[next--].m_key = (mz_uint16)(dpth);
2714 avbl--;
2715 }
2716 avbl = 2 * used;
2717 dpth++;
2718 used = 0;
2719 }
2720 }
2721
2722 // Limits canonical Huffman code table's max code size.
2723 enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
tdefl_huffman_enforce_max_code_size(int * pNum_codes,int code_list_len,int max_code_size)2724 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes,
2725 int code_list_len,
2726 int max_code_size) {
2727 int i;
2728 mz_uint32 total = 0;
2729 if (code_list_len <= 1)
2730 return;
2731 for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
2732 pNum_codes[max_code_size] += pNum_codes[i];
2733 for (i = max_code_size; i > 0; i--)
2734 total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
2735 while (total != (1UL << max_code_size)) {
2736 pNum_codes[max_code_size]--;
2737 for (i = max_code_size - 1; i > 0; i--)
2738 if (pNum_codes[i]) {
2739 pNum_codes[i]--;
2740 pNum_codes[i + 1] += 2;
2741 break;
2742 }
2743 total--;
2744 }
2745 }
2746
tdefl_optimize_huffman_table(tdefl_compressor * d,int table_num,int table_len,int code_size_limit,int static_table)2747 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num,
2748 int table_len, int code_size_limit,
2749 int static_table) {
2750 int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
2751 mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
2752 MZ_CLEAR_OBJ(num_codes);
2753 if (static_table) {
2754 for (i = 0; i < table_len; i++)
2755 num_codes[d->m_huff_code_sizes[table_num][i]]++;
2756 } else {
2757 tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS],
2758 *pSyms;
2759 int num_used_syms = 0;
2760 const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
2761 for (i = 0; i < table_len; i++)
2762 if (pSym_count[i]) {
2763 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
2764 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
2765 }
2766
2767 pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
2768 tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
2769
2770 for (i = 0; i < num_used_syms; i++)
2771 num_codes[pSyms[i].m_key]++;
2772
2773 tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms,
2774 code_size_limit);
2775
2776 MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
2777 MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
2778 for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
2779 for (l = num_codes[i]; l > 0; l--)
2780 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
2781 }
2782
2783 next_code[1] = 0;
2784 for (j = 0, i = 2; i <= code_size_limit; i++)
2785 next_code[i] = j = ((j + num_codes[i - 1]) << 1);
2786
2787 for (i = 0; i < table_len; i++) {
2788 mz_uint rev_code = 0, code, code_size;
2789 if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
2790 continue;
2791 code = next_code[code_size]++;
2792 for (l = code_size; l > 0; l--, code >>= 1)
2793 rev_code = (rev_code << 1) | (code & 1);
2794 d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
2795 }
2796 }
2797
2798 #define TDEFL_PUT_BITS(b, l) \
2799 do { \
2800 mz_uint bits = b; \
2801 mz_uint len = l; \
2802 MZ_ASSERT(bits <= ((1U << len) - 1U)); \
2803 d->m_bit_buffer |= (bits << d->m_bits_in); \
2804 d->m_bits_in += len; \
2805 while (d->m_bits_in >= 8) { \
2806 if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
2807 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
2808 d->m_bit_buffer >>= 8; \
2809 d->m_bits_in -= 8; \
2810 } \
2811 } \
2812 MZ_MACRO_END
2813
2814 #define TDEFL_RLE_PREV_CODE_SIZE() \
2815 { \
2816 if (rle_repeat_count) { \
2817 if (rle_repeat_count < 3) { \
2818 d->m_huff_count[2][prev_code_size] = (mz_uint16)( \
2819 d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
2820 while (rle_repeat_count--) \
2821 packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
2822 } else { \
2823 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
2824 packed_code_sizes[num_packed_code_sizes++] = 16; \
2825 packed_code_sizes[num_packed_code_sizes++] = \
2826 (mz_uint8)(rle_repeat_count - 3); \
2827 } \
2828 rle_repeat_count = 0; \
2829 } \
2830 }
2831
2832 #define TDEFL_RLE_ZERO_CODE_SIZE() \
2833 { \
2834 if (rle_z_count) { \
2835 if (rle_z_count < 3) { \
2836 d->m_huff_count[2][0] = \
2837 (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \
2838 while (rle_z_count--) \
2839 packed_code_sizes[num_packed_code_sizes++] = 0; \
2840 } else if (rle_z_count <= 10) { \
2841 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \
2842 packed_code_sizes[num_packed_code_sizes++] = 17; \
2843 packed_code_sizes[num_packed_code_sizes++] = \
2844 (mz_uint8)(rle_z_count - 3); \
2845 } else { \
2846 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \
2847 packed_code_sizes[num_packed_code_sizes++] = 18; \
2848 packed_code_sizes[num_packed_code_sizes++] = \
2849 (mz_uint8)(rle_z_count - 11); \
2850 } \
2851 rle_z_count = 0; \
2852 } \
2853 }
2854
2855 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {
2856 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2857
tdefl_start_dynamic_block(tdefl_compressor * d)2858 static void tdefl_start_dynamic_block(tdefl_compressor *d) {
2859 int num_lit_codes, num_dist_codes, num_bit_lengths;
2860 mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count,
2861 rle_repeat_count, packed_code_sizes_index;
2862 mz_uint8
2863 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2864 packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2865 prev_code_size = 0xFF;
2866
2867 d->m_huff_count[0][256] = 1;
2868
2869 tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
2870 tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
2871
2872 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
2873 if (d->m_huff_code_sizes[0][num_lit_codes - 1])
2874 break;
2875 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
2876 if (d->m_huff_code_sizes[1][num_dist_codes - 1])
2877 break;
2878
2879 memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0],
2880 sizeof(mz_uint8) * num_lit_codes);
2881 memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0],
2882 sizeof(mz_uint8) * num_dist_codes);
2883 total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
2884 num_packed_code_sizes = 0;
2885 rle_z_count = 0;
2886 rle_repeat_count = 0;
2887
2888 memset(&d->m_huff_count[2][0], 0,
2889 sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
2890 for (i = 0; i < total_code_sizes_to_pack; i++) {
2891 mz_uint8 code_size = code_sizes_to_pack[i];
2892 if (!code_size) {
2893 TDEFL_RLE_PREV_CODE_SIZE();
2894 if (++rle_z_count == 138) {
2895 TDEFL_RLE_ZERO_CODE_SIZE();
2896 }
2897 } else {
2898 TDEFL_RLE_ZERO_CODE_SIZE();
2899 if (code_size != prev_code_size) {
2900 TDEFL_RLE_PREV_CODE_SIZE();
2901 d->m_huff_count[2][code_size] =
2902 (mz_uint16)(d->m_huff_count[2][code_size] + 1);
2903 packed_code_sizes[num_packed_code_sizes++] = code_size;
2904 } else if (++rle_repeat_count == 6) {
2905 TDEFL_RLE_PREV_CODE_SIZE();
2906 }
2907 }
2908 prev_code_size = code_size;
2909 }
2910 if (rle_repeat_count) {
2911 TDEFL_RLE_PREV_CODE_SIZE();
2912 } else {
2913 TDEFL_RLE_ZERO_CODE_SIZE();
2914 }
2915
2916 tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
2917
2918 TDEFL_PUT_BITS(2, 2);
2919
2920 TDEFL_PUT_BITS(num_lit_codes - 257, 5);
2921 TDEFL_PUT_BITS(num_dist_codes - 1, 5);
2922
2923 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
2924 if (d->m_huff_code_sizes
2925 [2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
2926 break;
2927 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
2928 TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
2929 for (i = 0; (int)i < num_bit_lengths; i++)
2930 TDEFL_PUT_BITS(
2931 d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
2932
2933 for (packed_code_sizes_index = 0;
2934 packed_code_sizes_index < num_packed_code_sizes;) {
2935 mz_uint code = packed_code_sizes[packed_code_sizes_index++];
2936 MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
2937 TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
2938 if (code >= 16)
2939 TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
2940 "\02\03\07"[code - 16]);
2941 }
2942 }
2943
tdefl_start_static_block(tdefl_compressor * d)2944 static void tdefl_start_static_block(tdefl_compressor *d) {
2945 mz_uint i;
2946 mz_uint8 *p = &d->m_huff_code_sizes[0][0];
2947
2948 for (i = 0; i <= 143; ++i)
2949 *p++ = 8;
2950 for (; i <= 255; ++i)
2951 *p++ = 9;
2952 for (; i <= 279; ++i)
2953 *p++ = 7;
2954 for (; i <= 287; ++i)
2955 *p++ = 8;
2956
2957 memset(d->m_huff_code_sizes[1], 5, 32);
2958
2959 tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
2960 tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
2961
2962 TDEFL_PUT_BITS(1, 2);
2963 }
2964
2965 static const mz_uint mz_bitmasks[17] = {
2966 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
2967 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
2968
2969 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && \
2970 MINIZ_HAS_64BIT_REGISTERS
tdefl_compress_lz_codes(tdefl_compressor * d)2971 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
2972 mz_uint flags;
2973 mz_uint8 *pLZ_codes;
2974 mz_uint8 *pOutput_buf = d->m_pOutput_buf;
2975 mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
2976 mz_uint64 bit_buffer = d->m_bit_buffer;
2977 mz_uint bits_in = d->m_bits_in;
2978
2979 #define TDEFL_PUT_BITS_FAST(b, l) \
2980 { \
2981 bit_buffer |= (((mz_uint64)(b)) << bits_in); \
2982 bits_in += (l); \
2983 }
2984
2985 flags = 1;
2986 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end;
2987 flags >>= 1) {
2988 if (flags == 1)
2989 flags = *pLZ_codes++ | 0x100;
2990
2991 if (flags & 1) {
2992 mz_uint s0, s1, n0, n1, sym, num_extra_bits;
2993 mz_uint match_len = pLZ_codes[0],
2994 match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
2995 pLZ_codes += 3;
2996
2997 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2998 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
2999 d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3000 TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3001 s_tdefl_len_extra[match_len]);
3002
3003 // This sequence coaxes MSVC into using cmov's vs. jmp's.
3004 s0 = s_tdefl_small_dist_sym[match_dist & 511];
3005 n0 = s_tdefl_small_dist_extra[match_dist & 511];
3006 s1 = s_tdefl_large_dist_sym[match_dist >> 8];
3007 n1 = s_tdefl_large_dist_extra[match_dist >> 8];
3008 sym = (match_dist < 512) ? s0 : s1;
3009 num_extra_bits = (match_dist < 512) ? n0 : n1;
3010
3011 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3012 TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym],
3013 d->m_huff_code_sizes[1][sym]);
3014 TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits],
3015 num_extra_bits);
3016 } else {
3017 mz_uint lit = *pLZ_codes++;
3018 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3019 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3020 d->m_huff_code_sizes[0][lit]);
3021
3022 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3023 flags >>= 1;
3024 lit = *pLZ_codes++;
3025 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3026 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3027 d->m_huff_code_sizes[0][lit]);
3028
3029 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3030 flags >>= 1;
3031 lit = *pLZ_codes++;
3032 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3033 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3034 d->m_huff_code_sizes[0][lit]);
3035 }
3036 }
3037 }
3038
3039 if (pOutput_buf >= d->m_pOutput_buf_end)
3040 return MZ_FALSE;
3041
3042 *(mz_uint64 *)pOutput_buf = bit_buffer;
3043 pOutput_buf += (bits_in >> 3);
3044 bit_buffer >>= (bits_in & ~7);
3045 bits_in &= 7;
3046 }
3047
3048 #undef TDEFL_PUT_BITS_FAST
3049
3050 d->m_pOutput_buf = pOutput_buf;
3051 d->m_bits_in = 0;
3052 d->m_bit_buffer = 0;
3053
3054 while (bits_in) {
3055 mz_uint32 n = MZ_MIN(bits_in, 16);
3056 TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
3057 bit_buffer >>= n;
3058 bits_in -= n;
3059 }
3060
3061 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3062
3063 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3064 }
3065 #else
tdefl_compress_lz_codes(tdefl_compressor * d)3066 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3067 mz_uint flags;
3068 mz_uint8 *pLZ_codes;
3069
3070 flags = 1;
3071 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf;
3072 flags >>= 1) {
3073 if (flags == 1)
3074 flags = *pLZ_codes++ | 0x100;
3075 if (flags & 1) {
3076 mz_uint sym, num_extra_bits;
3077 mz_uint match_len = pLZ_codes[0],
3078 match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
3079 pLZ_codes += 3;
3080
3081 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3082 TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3083 d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3084 TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3085 s_tdefl_len_extra[match_len]);
3086
3087 if (match_dist < 512) {
3088 sym = s_tdefl_small_dist_sym[match_dist];
3089 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
3090 } else {
3091 sym = s_tdefl_large_dist_sym[match_dist >> 8];
3092 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
3093 }
3094 TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
3095 TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
3096 } else {
3097 mz_uint lit = *pLZ_codes++;
3098 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3099 TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
3100 }
3101 }
3102
3103 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3104
3105 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3106 }
3107 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&
3108 // MINIZ_HAS_64BIT_REGISTERS
3109
tdefl_compress_block(tdefl_compressor * d,mz_bool static_block)3110 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) {
3111 if (static_block)
3112 tdefl_start_static_block(d);
3113 else
3114 tdefl_start_dynamic_block(d);
3115 return tdefl_compress_lz_codes(d);
3116 }
3117
tdefl_flush_block(tdefl_compressor * d,int flush)3118 static int tdefl_flush_block(tdefl_compressor *d, int flush) {
3119 mz_uint saved_bit_buf, saved_bits_in;
3120 mz_uint8 *pSaved_output_buf;
3121 mz_bool comp_block_succeeded = MZ_FALSE;
3122 int n, use_raw_block =
3123 ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
3124 (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
3125 mz_uint8 *pOutput_buf_start =
3126 ((d->m_pPut_buf_func == NULL) &&
3127 ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
3128 ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs)
3129 : d->m_output_buf;
3130
3131 d->m_pOutput_buf = pOutput_buf_start;
3132 d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
3133
3134 MZ_ASSERT(!d->m_output_flush_remaining);
3135 d->m_output_flush_ofs = 0;
3136 d->m_output_flush_remaining = 0;
3137
3138 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
3139 d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
3140
3141 if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) {
3142 TDEFL_PUT_BITS(0x78, 8);
3143 TDEFL_PUT_BITS(0x01, 8);
3144 }
3145
3146 TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
3147
3148 pSaved_output_buf = d->m_pOutput_buf;
3149 saved_bit_buf = d->m_bit_buffer;
3150 saved_bits_in = d->m_bits_in;
3151
3152 if (!use_raw_block)
3153 comp_block_succeeded =
3154 tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
3155 (d->m_total_lz_bytes < 48));
3156
3157 // If the block gets expanded, forget the current contents of the output
3158 // buffer and send a raw block instead.
3159 if (((use_raw_block) ||
3160 ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >=
3161 d->m_total_lz_bytes))) &&
3162 ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) {
3163 mz_uint i;
3164 d->m_pOutput_buf = pSaved_output_buf;
3165 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3166 TDEFL_PUT_BITS(0, 2);
3167 if (d->m_bits_in) {
3168 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3169 }
3170 for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) {
3171 TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
3172 }
3173 for (i = 0; i < d->m_total_lz_bytes; ++i) {
3174 TDEFL_PUT_BITS(
3175 d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK],
3176 8);
3177 }
3178 }
3179 // Check for the extremely unlikely (if not impossible) case of the compressed
3180 // block not fitting into the output buffer when using dynamic codes.
3181 else if (!comp_block_succeeded) {
3182 d->m_pOutput_buf = pSaved_output_buf;
3183 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3184 tdefl_compress_block(d, MZ_TRUE);
3185 }
3186
3187 if (flush) {
3188 if (flush == TDEFL_FINISH) {
3189 if (d->m_bits_in) {
3190 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3191 }
3192 if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) {
3193 mz_uint i, a = d->m_adler32;
3194 for (i = 0; i < 4; i++) {
3195 TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
3196 a <<= 8;
3197 }
3198 }
3199 } else {
3200 mz_uint i, z = 0;
3201 TDEFL_PUT_BITS(0, 3);
3202 if (d->m_bits_in) {
3203 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3204 }
3205 for (i = 2; i; --i, z ^= 0xFFFF) {
3206 TDEFL_PUT_BITS(z & 0xFFFF, 16);
3207 }
3208 }
3209 }
3210
3211 MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
3212
3213 memset(&d->m_huff_count[0][0], 0,
3214 sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3215 memset(&d->m_huff_count[1][0], 0,
3216 sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3217
3218 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3219 d->m_pLZ_flags = d->m_lz_code_buf;
3220 d->m_num_flags_left = 8;
3221 d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
3222 d->m_total_lz_bytes = 0;
3223 d->m_block_index++;
3224
3225 if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) {
3226 if (d->m_pPut_buf_func) {
3227 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3228 if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
3229 return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
3230 } else if (pOutput_buf_start == d->m_output_buf) {
3231 int bytes_to_copy = (int)MZ_MIN(
3232 (size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
3233 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf,
3234 bytes_to_copy);
3235 d->m_out_buf_ofs += bytes_to_copy;
3236 if ((n -= bytes_to_copy) != 0) {
3237 d->m_output_flush_ofs = bytes_to_copy;
3238 d->m_output_flush_remaining = n;
3239 }
3240 } else {
3241 d->m_out_buf_ofs += n;
3242 }
3243 }
3244
3245 return d->m_output_flush_remaining;
3246 }
3247
3248 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3249 #define TDEFL_READ_UNALIGNED_WORD(p) ((p)[0] | (p)[1] << 8)
3250 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)3251 tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3252 mz_uint max_match_len, mz_uint *pMatch_dist,
3253 mz_uint *pMatch_len) {
3254 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3255 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3256 probe_len;
3257 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3258 const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
3259 mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]),
3260 s01 = *s;
3261 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3262 if (max_match_len <= match_len)
3263 return;
3264 for (;;) {
3265 for (;;) {
3266 if (--num_probes_left == 0)
3267 return;
3268 #define TDEFL_PROBE \
3269 next_probe_pos = d->m_next[probe_pos]; \
3270 if ((!next_probe_pos) || \
3271 ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
3272 return; \
3273 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
3274 if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
3275 break;
3276 TDEFL_PROBE;
3277 TDEFL_PROBE;
3278 TDEFL_PROBE;
3279 }
3280 if (!dist)
3281 break;
3282 q = (const mz_uint16 *)(d->m_dict + probe_pos);
3283 if (*q != s01)
3284 continue;
3285 p = s;
3286 probe_len = 32;
3287 do {
3288 } while ((*(++p) == *(++q)) && (*(++p) == *(++q)) && (*(++p) == *(++q)) &&
3289 (*(++p) == *(++q)) && (--probe_len > 0));
3290 if (!probe_len) {
3291 *pMatch_dist = dist;
3292 *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN);
3293 break;
3294 } else if ((probe_len = ((mz_uint)(p - s) * 2) +
3295 (mz_uint)(*(const mz_uint8 *)p ==
3296 *(const mz_uint8 *)q)) > match_len) {
3297 *pMatch_dist = dist;
3298 if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) ==
3299 max_match_len)
3300 break;
3301 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
3302 }
3303 }
3304 }
3305 #else
3306 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)3307 tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3308 mz_uint max_match_len, mz_uint *pMatch_dist,
3309 mz_uint *pMatch_len) {
3310 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3311 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3312 probe_len;
3313 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3314 const mz_uint8 *s = d->m_dict + pos, *p, *q;
3315 mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
3316 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3317 if (max_match_len <= match_len)
3318 return;
3319 for (;;) {
3320 for (;;) {
3321 if (--num_probes_left == 0)
3322 return;
3323 #define TDEFL_PROBE \
3324 next_probe_pos = d->m_next[probe_pos]; \
3325 if ((!next_probe_pos) || \
3326 ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
3327 return; \
3328 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
3329 if ((d->m_dict[probe_pos + match_len] == c0) && \
3330 (d->m_dict[probe_pos + match_len - 1] == c1)) \
3331 break;
3332 TDEFL_PROBE;
3333 TDEFL_PROBE;
3334 TDEFL_PROBE;
3335 }
3336 if (!dist)
3337 break;
3338 p = s;
3339 q = d->m_dict + probe_pos;
3340 for (probe_len = 0; probe_len < max_match_len; probe_len++)
3341 if (*p++ != *q++)
3342 break;
3343 if (probe_len > match_len) {
3344 *pMatch_dist = dist;
3345 if ((*pMatch_len = match_len = probe_len) == max_match_len)
3346 return;
3347 c0 = d->m_dict[pos + match_len];
3348 c1 = d->m_dict[pos + match_len - 1];
3349 }
3350 }
3351 }
3352 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3353
3354 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
tdefl_compress_fast(tdefl_compressor * d)3355 static mz_bool tdefl_compress_fast(tdefl_compressor *d) {
3356 // Faster, minimally featured LZRW1-style match+parse loop with better
3357 // register utilization. Intended for applications where raw throughput is
3358 // valued more highly than ratio.
3359 mz_uint lookahead_pos = d->m_lookahead_pos,
3360 lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size,
3361 total_lz_bytes = d->m_total_lz_bytes,
3362 num_flags_left = d->m_num_flags_left;
3363 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
3364 mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3365
3366 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
3367 const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
3368 mz_uint dst_pos =
3369 (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
3370 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3371 d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
3372 d->m_src_buf_left -= num_bytes_to_process;
3373 lookahead_size += num_bytes_to_process;
3374
3375 while (num_bytes_to_process) {
3376 mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
3377 memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
3378 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3379 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc,
3380 MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
3381 d->m_pSrc += n;
3382 dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
3383 num_bytes_to_process -= n;
3384 }
3385
3386 dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
3387 if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
3388 break;
3389
3390 while (lookahead_size >= 4) {
3391 mz_uint cur_match_dist, cur_match_len = 1;
3392 mz_uint8 *pCur_dict = d->m_dict + cur_pos;
3393 mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
3394 mz_uint hash =
3395 (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) &
3396 TDEFL_LEVEL1_HASH_SIZE_MASK;
3397 mz_uint probe_pos = d->m_hash[hash];
3398 d->m_hash[hash] = (mz_uint16)lookahead_pos;
3399
3400 if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <=
3401 dict_size) &&
3402 ((mz_uint32)(
3403 *(d->m_dict + (probe_pos & TDEFL_LZ_DICT_SIZE_MASK)) |
3404 (*(d->m_dict + ((probe_pos & TDEFL_LZ_DICT_SIZE_MASK) + 1))
3405 << 8) |
3406 (*(d->m_dict + ((probe_pos & TDEFL_LZ_DICT_SIZE_MASK) + 2))
3407 << 16)) == first_trigram)) {
3408 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
3409 const mz_uint16 *q =
3410 (const mz_uint16 *)(d->m_dict +
3411 (probe_pos & TDEFL_LZ_DICT_SIZE_MASK));
3412 mz_uint32 probe_len = 32;
3413 do {
3414 } while ((*(++p) == *(++q)) && (*(++p) == *(++q)) &&
3415 (*(++p) == *(++q)) && (*(++p) == *(++q)) && (--probe_len > 0));
3416 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) +
3417 (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
3418 if (!probe_len)
3419 cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
3420
3421 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) ||
3422 ((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3423 (cur_match_dist >= 8U * 1024U))) {
3424 cur_match_len = 1;
3425 *pLZ_code_buf++ = (mz_uint8)first_trigram;
3426 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3427 d->m_huff_count[0][(mz_uint8)first_trigram]++;
3428 } else {
3429 mz_uint32 s0, s1;
3430 cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
3431
3432 MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) &&
3433 (cur_match_dist >= 1) &&
3434 (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
3435
3436 cur_match_dist--;
3437
3438 pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
3439 *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
3440 pLZ_code_buf += 3;
3441 *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
3442
3443 s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
3444 s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
3445 d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
3446
3447 d->m_huff_count[0][s_tdefl_len_sym[cur_match_len -
3448 TDEFL_MIN_MATCH_LEN]]++;
3449 }
3450 } else {
3451 *pLZ_code_buf++ = (mz_uint8)first_trigram;
3452 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3453 d->m_huff_count[0][(mz_uint8)first_trigram]++;
3454 }
3455
3456 if (--num_flags_left == 0) {
3457 num_flags_left = 8;
3458 pLZ_flags = pLZ_code_buf++;
3459 }
3460
3461 total_lz_bytes += cur_match_len;
3462 lookahead_pos += cur_match_len;
3463 dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
3464 cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
3465 MZ_ASSERT(lookahead_size >= cur_match_len);
3466 lookahead_size -= cur_match_len;
3467
3468 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3469 int n;
3470 d->m_lookahead_pos = lookahead_pos;
3471 d->m_lookahead_size = lookahead_size;
3472 d->m_dict_size = dict_size;
3473 d->m_total_lz_bytes = total_lz_bytes;
3474 d->m_pLZ_code_buf = pLZ_code_buf;
3475 d->m_pLZ_flags = pLZ_flags;
3476 d->m_num_flags_left = num_flags_left;
3477 if ((n = tdefl_flush_block(d, 0)) != 0)
3478 return (n < 0) ? MZ_FALSE : MZ_TRUE;
3479 total_lz_bytes = d->m_total_lz_bytes;
3480 pLZ_code_buf = d->m_pLZ_code_buf;
3481 pLZ_flags = d->m_pLZ_flags;
3482 num_flags_left = d->m_num_flags_left;
3483 }
3484 }
3485
3486 while (lookahead_size) {
3487 mz_uint8 lit = d->m_dict[cur_pos];
3488
3489 total_lz_bytes++;
3490 *pLZ_code_buf++ = lit;
3491 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3492 if (--num_flags_left == 0) {
3493 num_flags_left = 8;
3494 pLZ_flags = pLZ_code_buf++;
3495 }
3496
3497 d->m_huff_count[0][lit]++;
3498
3499 lookahead_pos++;
3500 dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
3501 cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3502 lookahead_size--;
3503
3504 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3505 int n;
3506 d->m_lookahead_pos = lookahead_pos;
3507 d->m_lookahead_size = lookahead_size;
3508 d->m_dict_size = dict_size;
3509 d->m_total_lz_bytes = total_lz_bytes;
3510 d->m_pLZ_code_buf = pLZ_code_buf;
3511 d->m_pLZ_flags = pLZ_flags;
3512 d->m_num_flags_left = num_flags_left;
3513 if ((n = tdefl_flush_block(d, 0)) != 0)
3514 return (n < 0) ? MZ_FALSE : MZ_TRUE;
3515 total_lz_bytes = d->m_total_lz_bytes;
3516 pLZ_code_buf = d->m_pLZ_code_buf;
3517 pLZ_flags = d->m_pLZ_flags;
3518 num_flags_left = d->m_num_flags_left;
3519 }
3520 }
3521 }
3522
3523 d->m_lookahead_pos = lookahead_pos;
3524 d->m_lookahead_size = lookahead_size;
3525 d->m_dict_size = dict_size;
3526 d->m_total_lz_bytes = total_lz_bytes;
3527 d->m_pLZ_code_buf = pLZ_code_buf;
3528 d->m_pLZ_flags = pLZ_flags;
3529 d->m_num_flags_left = num_flags_left;
3530 return MZ_TRUE;
3531 }
3532 #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3533
tdefl_record_literal(tdefl_compressor * d,mz_uint8 lit)3534 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d,
3535 mz_uint8 lit) {
3536 d->m_total_lz_bytes++;
3537 *d->m_pLZ_code_buf++ = lit;
3538 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
3539 if (--d->m_num_flags_left == 0) {
3540 d->m_num_flags_left = 8;
3541 d->m_pLZ_flags = d->m_pLZ_code_buf++;
3542 }
3543 d->m_huff_count[0][lit]++;
3544 }
3545
3546 static MZ_FORCEINLINE void
tdefl_record_match(tdefl_compressor * d,mz_uint match_len,mz_uint match_dist)3547 tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) {
3548 mz_uint32 s0, s1;
3549
3550 MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) &&
3551 (match_dist <= TDEFL_LZ_DICT_SIZE));
3552
3553 d->m_total_lz_bytes += match_len;
3554
3555 d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
3556
3557 match_dist -= 1;
3558 d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
3559 d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
3560 d->m_pLZ_code_buf += 3;
3561
3562 *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
3563 if (--d->m_num_flags_left == 0) {
3564 d->m_num_flags_left = 8;
3565 d->m_pLZ_flags = d->m_pLZ_code_buf++;
3566 }
3567
3568 s0 = s_tdefl_small_dist_sym[match_dist & 511];
3569 s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
3570 d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
3571
3572 if (match_len >= TDEFL_MIN_MATCH_LEN)
3573 d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
3574 }
3575
tdefl_compress_normal(tdefl_compressor * d)3576 static mz_bool tdefl_compress_normal(tdefl_compressor *d) {
3577 const mz_uint8 *pSrc = d->m_pSrc;
3578 size_t src_buf_left = d->m_src_buf_left;
3579 tdefl_flush flush = d->m_flush;
3580
3581 while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) {
3582 mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
3583 // Update dictionary and hash chains. Keeps the lookahead size equal to
3584 // TDEFL_MAX_MATCH_LEN.
3585 if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) {
3586 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3587 TDEFL_LZ_DICT_SIZE_MASK,
3588 ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
3589 mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3590 << TDEFL_LZ_HASH_SHIFT) ^
3591 d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
3592 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3593 src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
3594 const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
3595 src_buf_left -= num_bytes_to_process;
3596 d->m_lookahead_size += num_bytes_to_process;
3597 while (pSrc != pSrc_end) {
3598 mz_uint8 c = *pSrc++;
3599 d->m_dict[dst_pos] = c;
3600 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3601 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3602 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
3603 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3604 d->m_hash[hash] = (mz_uint16)(ins_pos);
3605 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3606 ins_pos++;
3607 }
3608 } else {
3609 while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) {
3610 mz_uint8 c = *pSrc++;
3611 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3612 TDEFL_LZ_DICT_SIZE_MASK;
3613 src_buf_left--;
3614 d->m_dict[dst_pos] = c;
3615 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3616 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3617 if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) {
3618 mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
3619 mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3620 << (TDEFL_LZ_HASH_SHIFT * 2)) ^
3621 (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]
3622 << TDEFL_LZ_HASH_SHIFT) ^
3623 c) &
3624 (TDEFL_LZ_HASH_SIZE - 1);
3625 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3626 d->m_hash[hash] = (mz_uint16)(ins_pos);
3627 }
3628 }
3629 }
3630 d->m_dict_size =
3631 MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
3632 if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
3633 break;
3634
3635 // Simple lazy/greedy parsing state machine.
3636 len_to_move = 1;
3637 cur_match_dist = 0;
3638 cur_match_len =
3639 d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
3640 cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3641 if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) {
3642 if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) {
3643 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
3644 cur_match_len = 0;
3645 while (cur_match_len < d->m_lookahead_size) {
3646 if (d->m_dict[cur_pos + cur_match_len] != c)
3647 break;
3648 cur_match_len++;
3649 }
3650 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
3651 cur_match_len = 0;
3652 else
3653 cur_match_dist = 1;
3654 }
3655 } else {
3656 tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size,
3657 d->m_lookahead_size, &cur_match_dist, &cur_match_len);
3658 }
3659 if (((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3660 (cur_match_dist >= 8U * 1024U)) ||
3661 (cur_pos == cur_match_dist) ||
3662 ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) {
3663 cur_match_dist = cur_match_len = 0;
3664 }
3665 if (d->m_saved_match_len) {
3666 if (cur_match_len > d->m_saved_match_len) {
3667 tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
3668 if (cur_match_len >= 128) {
3669 tdefl_record_match(d, cur_match_len, cur_match_dist);
3670 d->m_saved_match_len = 0;
3671 len_to_move = cur_match_len;
3672 } else {
3673 d->m_saved_lit = d->m_dict[cur_pos];
3674 d->m_saved_match_dist = cur_match_dist;
3675 d->m_saved_match_len = cur_match_len;
3676 }
3677 } else {
3678 tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
3679 len_to_move = d->m_saved_match_len - 1;
3680 d->m_saved_match_len = 0;
3681 }
3682 } else if (!cur_match_dist)
3683 tdefl_record_literal(d,
3684 d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
3685 else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) ||
3686 (cur_match_len >= 128)) {
3687 tdefl_record_match(d, cur_match_len, cur_match_dist);
3688 len_to_move = cur_match_len;
3689 } else {
3690 d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
3691 d->m_saved_match_dist = cur_match_dist;
3692 d->m_saved_match_len = cur_match_len;
3693 }
3694 // Move the lookahead forward by len_to_move bytes.
3695 d->m_lookahead_pos += len_to_move;
3696 MZ_ASSERT(d->m_lookahead_size >= len_to_move);
3697 d->m_lookahead_size -= len_to_move;
3698 d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
3699 // Check if it's time to flush the current LZ codes to the internal output
3700 // buffer.
3701 if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
3702 ((d->m_total_lz_bytes > 31 * 1024) &&
3703 (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >=
3704 d->m_total_lz_bytes) ||
3705 (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) {
3706 int n;
3707 d->m_pSrc = pSrc;
3708 d->m_src_buf_left = src_buf_left;
3709 if ((n = tdefl_flush_block(d, 0)) != 0)
3710 return (n < 0) ? MZ_FALSE : MZ_TRUE;
3711 }
3712 }
3713
3714 d->m_pSrc = pSrc;
3715 d->m_src_buf_left = src_buf_left;
3716 return MZ_TRUE;
3717 }
3718
tdefl_flush_output_buffer(tdefl_compressor * d)3719 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) {
3720 if (d->m_pIn_buf_size) {
3721 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3722 }
3723
3724 if (d->m_pOut_buf_size) {
3725 size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs,
3726 d->m_output_flush_remaining);
3727 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs,
3728 d->m_output_buf + d->m_output_flush_ofs, n);
3729 d->m_output_flush_ofs += (mz_uint)n;
3730 d->m_output_flush_remaining -= (mz_uint)n;
3731 d->m_out_buf_ofs += n;
3732
3733 *d->m_pOut_buf_size = d->m_out_buf_ofs;
3734 }
3735
3736 return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE
3737 : TDEFL_STATUS_OKAY;
3738 }
3739
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)3740 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
3741 size_t *pIn_buf_size, void *pOut_buf,
3742 size_t *pOut_buf_size, tdefl_flush flush) {
3743 if (!d) {
3744 if (pIn_buf_size)
3745 *pIn_buf_size = 0;
3746 if (pOut_buf_size)
3747 *pOut_buf_size = 0;
3748 return TDEFL_STATUS_BAD_PARAM;
3749 }
3750
3751 d->m_pIn_buf = pIn_buf;
3752 d->m_pIn_buf_size = pIn_buf_size;
3753 d->m_pOut_buf = pOut_buf;
3754 d->m_pOut_buf_size = pOut_buf_size;
3755 d->m_pSrc = (const mz_uint8 *)(pIn_buf);
3756 d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
3757 d->m_out_buf_ofs = 0;
3758 d->m_flush = flush;
3759
3760 if (((d->m_pPut_buf_func != NULL) ==
3761 ((pOut_buf != NULL) || (pOut_buf_size != NULL))) ||
3762 (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
3763 (d->m_wants_to_finish && (flush != TDEFL_FINISH)) ||
3764 (pIn_buf_size && *pIn_buf_size && !pIn_buf) ||
3765 (pOut_buf_size && *pOut_buf_size && !pOut_buf)) {
3766 if (pIn_buf_size)
3767 *pIn_buf_size = 0;
3768 if (pOut_buf_size)
3769 *pOut_buf_size = 0;
3770 return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
3771 }
3772 d->m_wants_to_finish |= (flush == TDEFL_FINISH);
3773
3774 if ((d->m_output_flush_remaining) || (d->m_finished))
3775 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3776
3777 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3778 if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
3779 ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
3780 ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS |
3781 TDEFL_RLE_MATCHES)) == 0)) {
3782 if (!tdefl_compress_fast(d))
3783 return d->m_prev_return_status;
3784 } else
3785 #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3786 {
3787 if (!tdefl_compress_normal(d))
3788 return d->m_prev_return_status;
3789 }
3790
3791 if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) &&
3792 (pIn_buf))
3793 d->m_adler32 =
3794 (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf,
3795 d->m_pSrc - (const mz_uint8 *)pIn_buf);
3796
3797 if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) &&
3798 (!d->m_output_flush_remaining)) {
3799 if (tdefl_flush_block(d, flush) < 0)
3800 return d->m_prev_return_status;
3801 d->m_finished = (flush == TDEFL_FINISH);
3802 if (flush == TDEFL_FULL_FLUSH) {
3803 MZ_CLEAR_OBJ(d->m_hash);
3804 MZ_CLEAR_OBJ(d->m_next);
3805 d->m_dict_size = 0;
3806 }
3807 }
3808
3809 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3810 }
3811
tdefl_compress_buffer(tdefl_compressor * d,const void * pIn_buf,size_t in_buf_size,tdefl_flush flush)3812 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
3813 size_t in_buf_size, tdefl_flush flush) {
3814 MZ_ASSERT(d->m_pPut_buf_func);
3815 return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
3816 }
3817
tdefl_init(tdefl_compressor * d,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)3818 tdefl_status tdefl_init(tdefl_compressor *d,
3819 tdefl_put_buf_func_ptr pPut_buf_func,
3820 void *pPut_buf_user, int flags) {
3821 d->m_pPut_buf_func = pPut_buf_func;
3822 d->m_pPut_buf_user = pPut_buf_user;
3823 d->m_flags = (mz_uint)(flags);
3824 d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
3825 d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
3826 d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
3827 if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
3828 MZ_CLEAR_OBJ(d->m_hash);
3829 d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size =
3830 d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
3831 d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished =
3832 d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
3833 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3834 d->m_pLZ_flags = d->m_lz_code_buf;
3835 d->m_num_flags_left = 8;
3836 d->m_pOutput_buf = d->m_output_buf;
3837 d->m_pOutput_buf_end = d->m_output_buf;
3838 d->m_prev_return_status = TDEFL_STATUS_OKAY;
3839 d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
3840 d->m_adler32 = 1;
3841 d->m_pIn_buf = NULL;
3842 d->m_pOut_buf = NULL;
3843 d->m_pIn_buf_size = NULL;
3844 d->m_pOut_buf_size = NULL;
3845 d->m_flush = TDEFL_NO_FLUSH;
3846 d->m_pSrc = NULL;
3847 d->m_src_buf_left = 0;
3848 d->m_out_buf_ofs = 0;
3849 memset(&d->m_huff_count[0][0], 0,
3850 sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3851 memset(&d->m_huff_count[1][0], 0,
3852 sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3853 return TDEFL_STATUS_OKAY;
3854 }
3855
tdefl_get_prev_return_status(tdefl_compressor * d)3856 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
3857 return d->m_prev_return_status;
3858 }
3859
tdefl_get_adler32(tdefl_compressor * d)3860 mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
3861
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)3862 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
3863 tdefl_put_buf_func_ptr pPut_buf_func,
3864 void *pPut_buf_user, int flags) {
3865 tdefl_compressor *pComp;
3866 mz_bool succeeded;
3867 if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
3868 return MZ_FALSE;
3869 pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3870 if (!pComp)
3871 return MZ_FALSE;
3872 succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) ==
3873 TDEFL_STATUS_OKAY);
3874 succeeded =
3875 succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) ==
3876 TDEFL_STATUS_DONE);
3877 MZ_FREE(pComp);
3878 return succeeded;
3879 }
3880
3881 typedef struct {
3882 size_t m_size, m_capacity;
3883 mz_uint8 *m_pBuf;
3884 mz_bool m_expandable;
3885 } tdefl_output_buffer;
3886
tdefl_output_buffer_putter(const void * pBuf,int len,void * pUser)3887 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len,
3888 void *pUser) {
3889 tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
3890 size_t new_size = p->m_size + len;
3891 if (new_size > p->m_capacity) {
3892 size_t new_capacity = p->m_capacity;
3893 mz_uint8 *pNew_buf;
3894 if (!p->m_expandable)
3895 return MZ_FALSE;
3896 do {
3897 new_capacity = MZ_MAX(128U, new_capacity << 1U);
3898 } while (new_size > new_capacity);
3899 pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
3900 if (!pNew_buf)
3901 return MZ_FALSE;
3902 p->m_pBuf = pNew_buf;
3903 p->m_capacity = new_capacity;
3904 }
3905 memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
3906 p->m_size = new_size;
3907 return MZ_TRUE;
3908 }
3909
tdefl_compress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)3910 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
3911 size_t *pOut_len, int flags) {
3912 tdefl_output_buffer out_buf;
3913 MZ_CLEAR_OBJ(out_buf);
3914 if (!pOut_len)
3915 return MZ_FALSE;
3916 else
3917 *pOut_len = 0;
3918 out_buf.m_expandable = MZ_TRUE;
3919 if (!tdefl_compress_mem_to_output(
3920 pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3921 return NULL;
3922 *pOut_len = out_buf.m_size;
3923 return out_buf.m_pBuf;
3924 }
3925
tdefl_compress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)3926 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
3927 const void *pSrc_buf, size_t src_buf_len,
3928 int flags) {
3929 tdefl_output_buffer out_buf;
3930 MZ_CLEAR_OBJ(out_buf);
3931 if (!pOut_buf)
3932 return 0;
3933 out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
3934 out_buf.m_capacity = out_buf_len;
3935 if (!tdefl_compress_mem_to_output(
3936 pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3937 return 0;
3938 return out_buf.m_size;
3939 }
3940
3941 #ifndef MINIZ_NO_ZLIB_APIS
3942 static const mz_uint s_tdefl_num_probes[11] = {0, 1, 6, 32, 16, 32,
3943 128, 256, 512, 768, 1500};
3944
3945 // level may actually range from [0,10] (10 is a "hidden" max level, where we
3946 // want a bit more compression and it's fine if throughput to fall off a cliff
3947 // on some files).
tdefl_create_comp_flags_from_zip_params(int level,int window_bits,int strategy)3948 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
3949 int strategy) {
3950 mz_uint comp_flags =
3951 s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] |
3952 ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
3953 if (window_bits > 0)
3954 comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
3955
3956 if (!level)
3957 comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
3958 else if (strategy == MZ_FILTERED)
3959 comp_flags |= TDEFL_FILTER_MATCHES;
3960 else if (strategy == MZ_HUFFMAN_ONLY)
3961 comp_flags &= ~TDEFL_MAX_PROBES_MASK;
3962 else if (strategy == MZ_FIXED)
3963 comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
3964 else if (strategy == MZ_RLE)
3965 comp_flags |= TDEFL_RLE_MATCHES;
3966
3967 return comp_flags;
3968 }
3969 #endif // MINIZ_NO_ZLIB_APIS
3970
3971 #ifdef _MSC_VER
3972 #pragma warning(push)
3973 #pragma warning(disable : 4204) // nonstandard extension used : non-constant
3974 // aggregate initializer (also supported by GNU
3975 // C and C99, so no big deal)
3976 #endif
3977
3978 // Simple PNG writer function by Alex Evans, 2011. Released into the public
3979 // domain: https://gist.github.com/908299, more context at
3980 // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
3981 // This is actually a modification of Alex's original code so PNG files
3982 // 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)3983 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
3984 int h, int num_chans,
3985 size_t *pLen_out,
3986 mz_uint level, mz_bool flip) {
3987 // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was
3988 // defined.
3989 static const mz_uint s_tdefl_png_num_probes[11] = {
3990 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500};
3991 tdefl_compressor *pComp =
3992 (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3993 tdefl_output_buffer out_buf;
3994 int i, bpl = w * num_chans, y, z;
3995 mz_uint32 c;
3996 *pLen_out = 0;
3997 if (!pComp)
3998 return NULL;
3999 MZ_CLEAR_OBJ(out_buf);
4000 out_buf.m_expandable = MZ_TRUE;
4001 out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
4002 if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) {
4003 MZ_FREE(pComp);
4004 return NULL;
4005 }
4006 // write dummy header
4007 for (z = 41; z; --z)
4008 tdefl_output_buffer_putter(&z, 1, &out_buf);
4009 // compress image data
4010 tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf,
4011 s_tdefl_png_num_probes[MZ_MIN(10, level)] |
4012 TDEFL_WRITE_ZLIB_HEADER);
4013 for (y = 0; y < h; ++y) {
4014 tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
4015 tdefl_compress_buffer(pComp,
4016 (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl,
4017 bpl, TDEFL_NO_FLUSH);
4018 }
4019 if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) !=
4020 TDEFL_STATUS_DONE) {
4021 MZ_FREE(pComp);
4022 MZ_FREE(out_buf.m_pBuf);
4023 return NULL;
4024 }
4025 // write real header
4026 *pLen_out = out_buf.m_size - 41;
4027 {
4028 static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
4029 mz_uint8 pnghdr[41] = {0x89,
4030 0x50,
4031 0x4e,
4032 0x47,
4033 0x0d,
4034 0x0a,
4035 0x1a,
4036 0x0a,
4037 0x00,
4038 0x00,
4039 0x00,
4040 0x0d,
4041 0x49,
4042 0x48,
4043 0x44,
4044 0x52,
4045 0,
4046 0,
4047 (mz_uint8)(w >> 8),
4048 (mz_uint8)w,
4049 0,
4050 0,
4051 (mz_uint8)(h >> 8),
4052 (mz_uint8)h,
4053 8,
4054 chans[num_chans],
4055 0,
4056 0,
4057 0,
4058 0,
4059 0,
4060 0,
4061 0,
4062 (mz_uint8)(*pLen_out >> 24),
4063 (mz_uint8)(*pLen_out >> 16),
4064 (mz_uint8)(*pLen_out >> 8),
4065 (mz_uint8)*pLen_out,
4066 0x49,
4067 0x44,
4068 0x41,
4069 0x54};
4070 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
4071 for (i = 0; i < 4; ++i, c <<= 8)
4072 ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
4073 memcpy(out_buf.m_pBuf, pnghdr, 41);
4074 }
4075 // write footer (IDAT CRC-32, followed by IEND chunk)
4076 if (!tdefl_output_buffer_putter(
4077 "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) {
4078 *pLen_out = 0;
4079 MZ_FREE(pComp);
4080 MZ_FREE(out_buf.m_pBuf);
4081 return NULL;
4082 }
4083 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4,
4084 *pLen_out + 4);
4085 for (i = 0; i < 4; ++i, c <<= 8)
4086 (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
4087 // compute final size of file, grab compressed data buffer and return
4088 *pLen_out += 57;
4089 MZ_FREE(pComp);
4090 return out_buf.m_pBuf;
4091 }
tdefl_write_image_to_png_file_in_memory(const void * pImage,int w,int h,int num_chans,size_t * pLen_out)4092 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
4093 int num_chans, size_t *pLen_out) {
4094 // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we
4095 // can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's
4096 // where #defined out)
4097 return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans,
4098 pLen_out, 6, MZ_FALSE);
4099 }
4100
4101 #ifdef _MSC_VER
4102 #pragma warning(pop)
4103 #endif
4104
4105 // ------------------- .ZIP archive reading
4106
4107 #ifndef MINIZ_NO_ARCHIVE_APIS
4108
4109 #ifdef MINIZ_NO_STDIO
4110 #define MZ_FILE void *
4111 #else
4112 #include <stdio.h>
4113 #include <sys/stat.h>
4114
4115 #if defined(_MSC_VER)
mz_fopen(const char * pFilename,const char * pMode)4116 static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4117 FILE *pFile = NULL;
4118 fopen_s(&pFile, pFilename, pMode);
4119 return pFile;
4120 }
mz_freopen(const char * pPath,const char * pMode,FILE * pStream)4121 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4122 FILE *pFile = NULL;
4123 if (freopen_s(&pFile, pPath, pMode, pStream))
4124 return NULL;
4125 return pFile;
4126 }
4127 #ifndef MINIZ_NO_TIME
4128 #include <sys/utime.h>
4129 #endif
4130 #define MZ_FILE FILE
4131 #define MZ_FOPEN mz_fopen
4132 #define MZ_FCLOSE fclose
4133 #define MZ_FREAD fread
4134 #define MZ_FWRITE fwrite
4135 #define MZ_FTELL64 _ftelli64
4136 #define MZ_FSEEK64 _fseeki64
4137 #define MZ_FILE_STAT_STRUCT _stat
4138 #define MZ_FILE_STAT _stat
4139 #define MZ_FFLUSH fflush
4140 #define MZ_FREOPEN mz_freopen
4141 #define MZ_DELETE_FILE remove
4142 #elif defined(__MINGW32__)
4143 #ifndef MINIZ_NO_TIME
4144 #include <sys/utime.h>
4145 #endif
4146 #define MZ_FILE FILE
4147 #define MZ_FOPEN(f, m) fopen(f, m)
4148 #define MZ_FCLOSE fclose
4149 #define MZ_FREAD fread
4150 #define MZ_FWRITE fwrite
4151 #define MZ_FTELL64 ftell
4152 #define MZ_FSEEK64 fseek
4153 #define MZ_FILE_STAT_STRUCT _stat
4154 #define MZ_FILE_STAT _stat
4155 #define MZ_FFLUSH fflush
4156 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4157 #define MZ_DELETE_FILE remove
4158 #elif defined(__TINYC__)
4159 #ifndef MINIZ_NO_TIME
4160 #include <sys/utime.h>
4161 #endif
4162 #define MZ_FILE FILE
4163 #define MZ_FOPEN(f, m) fopen(f, m)
4164 #define MZ_FCLOSE fclose
4165 #define MZ_FREAD fread
4166 #define MZ_FWRITE fwrite
4167 #define MZ_FTELL64 ftell
4168 #define MZ_FSEEK64 fseek
4169 #define MZ_FILE_STAT_STRUCT stat
4170 #define MZ_FILE_STAT stat
4171 #define MZ_FFLUSH fflush
4172 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4173 #define MZ_DELETE_FILE remove
4174 #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
4175 #ifndef MINIZ_NO_TIME
4176 #include <utime.h>
4177 #endif
4178 #define MZ_FILE FILE
4179 #define MZ_FOPEN(f, m) fopen64(f, m)
4180 #define MZ_FCLOSE fclose
4181 #define MZ_FREAD fread
4182 #define MZ_FWRITE fwrite
4183 #define MZ_FTELL64 ftello64
4184 #define MZ_FSEEK64 fseeko64
4185 #define MZ_FILE_STAT_STRUCT stat64
4186 #define MZ_FILE_STAT stat64
4187 #define MZ_FFLUSH fflush
4188 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4189 #define MZ_DELETE_FILE remove
4190 #else
4191 #ifndef MINIZ_NO_TIME
4192 #include <utime.h>
4193 #endif
4194 #define MZ_FILE FILE
4195 #define MZ_FOPEN(f, m) fopen(f, m)
4196 #define MZ_FCLOSE fclose
4197 #define MZ_FREAD fread
4198 #define MZ_FWRITE fwrite
4199 #if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L
4200 #define MZ_FTELL64 ftello
4201 #define MZ_FSEEK64 fseeko
4202 #else
4203 #define MZ_FTELL64 ftell
4204 #define MZ_FSEEK64 fseek
4205 #endif
4206 #define MZ_FILE_STAT_STRUCT stat
4207 #define MZ_FILE_STAT stat
4208 #define MZ_FFLUSH fflush
4209 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4210 #define MZ_DELETE_FILE remove
4211 #endif // #ifdef _MSC_VER
4212 #endif // #ifdef MINIZ_NO_STDIO
4213
4214 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4215
4216 // Various ZIP archive enums. To completely avoid cross platform compiler
4217 // alignment and platform endian issues, miniz.c doesn't use structs for any of
4218 // this stuff.
4219 enum {
4220 // ZIP archive identifiers and record sizes
4221 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
4222 MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
4223 MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
4224 MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
4225 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
4226 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
4227
4228 /* ZIP64 archive identifier and record sizes */
4229 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
4230 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
4231 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
4232 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
4233 MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
4234 MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
4235 MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
4236 MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
4237
4238 // Central directory header record offsets
4239 MZ_ZIP_CDH_SIG_OFS = 0,
4240 MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
4241 MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
4242 MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
4243 MZ_ZIP_CDH_METHOD_OFS = 10,
4244 MZ_ZIP_CDH_FILE_TIME_OFS = 12,
4245 MZ_ZIP_CDH_FILE_DATE_OFS = 14,
4246 MZ_ZIP_CDH_CRC32_OFS = 16,
4247 MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
4248 MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
4249 MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
4250 MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
4251 MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
4252 MZ_ZIP_CDH_DISK_START_OFS = 34,
4253 MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
4254 MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
4255 MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
4256 // Local directory header offsets
4257 MZ_ZIP_LDH_SIG_OFS = 0,
4258 MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
4259 MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
4260 MZ_ZIP_LDH_METHOD_OFS = 8,
4261 MZ_ZIP_LDH_FILE_TIME_OFS = 10,
4262 MZ_ZIP_LDH_FILE_DATE_OFS = 12,
4263 MZ_ZIP_LDH_CRC32_OFS = 14,
4264 MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
4265 MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
4266 MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
4267 MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
4268 // End of central directory offsets
4269 MZ_ZIP_ECDH_SIG_OFS = 0,
4270 MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
4271 MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
4272 MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
4273 MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
4274 MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
4275 MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
4276 MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
4277
4278 /* ZIP64 End of central directory locator offsets */
4279 MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
4280 MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
4281 MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
4282 MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
4283
4284 /* ZIP64 End of central directory header offsets */
4285 MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
4286 MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
4287 MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
4288 MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
4289 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
4290 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
4291 MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
4292 MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
4293 MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
4294 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
4295 MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
4296 MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
4297 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
4298 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
4299 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
4300 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
4301 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
4302 };
4303
4304 typedef struct {
4305 void *m_p;
4306 size_t m_size, m_capacity;
4307 mz_uint m_element_size;
4308 } mz_zip_array;
4309
4310 struct mz_zip_internal_state_tag {
4311 mz_zip_array m_central_dir;
4312 mz_zip_array m_central_dir_offsets;
4313 mz_zip_array m_sorted_central_dir_offsets;
4314
4315 /* The flags passed in when the archive is initially opened. */
4316 uint32_t m_init_flags;
4317
4318 /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
4319 */
4320 mz_bool m_zip64;
4321
4322 /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
4323 * will also be slammed to true too, even if we didn't find a zip64 end of
4324 * central dir header, etc.) */
4325 mz_bool m_zip64_has_extended_info_fields;
4326
4327 /* These fields are used by the file, FILE, memory, and memory/heap read/write
4328 * helpers. */
4329 MZ_FILE *m_pFile;
4330 mz_uint64 m_file_archive_start_ofs;
4331
4332 void *m_pMem;
4333 size_t m_mem_size;
4334 size_t m_mem_capacity;
4335 };
4336
4337 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) \
4338 (array_ptr)->m_element_size = element_size
4339 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \
4340 ((element_type *)((array_ptr)->m_p))[index]
4341
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)4342 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
4343 mz_zip_array *pArray) {
4344 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
4345 memset(pArray, 0, sizeof(mz_zip_array));
4346 }
4347
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)4348 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
4349 mz_zip_array *pArray,
4350 size_t min_new_capacity,
4351 mz_uint growing) {
4352 void *pNew_p;
4353 size_t new_capacity = min_new_capacity;
4354 MZ_ASSERT(pArray->m_element_size);
4355 if (pArray->m_capacity >= min_new_capacity)
4356 return MZ_TRUE;
4357 if (growing) {
4358 new_capacity = MZ_MAX(1, pArray->m_capacity);
4359 while (new_capacity < min_new_capacity)
4360 new_capacity *= 2;
4361 }
4362 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
4363 pArray->m_element_size, new_capacity)))
4364 return MZ_FALSE;
4365 pArray->m_p = pNew_p;
4366 pArray->m_capacity = new_capacity;
4367 return MZ_TRUE;
4368 }
4369
mz_zip_array_reserve(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_capacity,mz_uint growing)4370 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
4371 mz_zip_array *pArray,
4372 size_t new_capacity,
4373 mz_uint growing) {
4374 if (new_capacity > pArray->m_capacity) {
4375 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
4376 return MZ_FALSE;
4377 }
4378 return MZ_TRUE;
4379 }
4380
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)4381 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
4382 mz_zip_array *pArray,
4383 size_t new_size,
4384 mz_uint growing) {
4385 if (new_size > pArray->m_capacity) {
4386 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
4387 return MZ_FALSE;
4388 }
4389 pArray->m_size = new_size;
4390 return MZ_TRUE;
4391 }
4392
mz_zip_array_ensure_room(mz_zip_archive * pZip,mz_zip_array * pArray,size_t n)4393 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
4394 mz_zip_array *pArray,
4395 size_t n) {
4396 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
4397 }
4398
mz_zip_array_push_back(mz_zip_archive * pZip,mz_zip_array * pArray,const void * pElements,size_t n)4399 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
4400 mz_zip_array *pArray,
4401 const void *pElements,
4402 size_t n) {
4403 if (0 == n)
4404 return MZ_TRUE;
4405 if (!pElements)
4406 return MZ_FALSE;
4407
4408 size_t orig_size = pArray->m_size;
4409 if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
4410 return MZ_FALSE;
4411 memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
4412 pElements, n * pArray->m_element_size);
4413 return MZ_TRUE;
4414 }
4415
4416 #ifndef MINIZ_NO_TIME
mz_zip_dos_to_time_t(int dos_time,int dos_date)4417 static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
4418 struct tm tm;
4419 memset(&tm, 0, sizeof(tm));
4420 tm.tm_isdst = -1;
4421 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
4422 tm.tm_mon = ((dos_date >> 5) & 15) - 1;
4423 tm.tm_mday = dos_date & 31;
4424 tm.tm_hour = (dos_time >> 11) & 31;
4425 tm.tm_min = (dos_time >> 5) & 63;
4426 tm.tm_sec = (dos_time << 1) & 62;
4427 return mktime(&tm);
4428 }
4429
4430 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_time_t_to_dos_time(time_t time,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)4431 static void mz_zip_time_t_to_dos_time(time_t time, mz_uint16 *pDOS_time,
4432 mz_uint16 *pDOS_date) {
4433 #ifdef _MSC_VER
4434 struct tm tm_struct;
4435 struct tm *tm = &tm_struct;
4436 errno_t err = localtime_s(tm, &time);
4437 if (err) {
4438 *pDOS_date = 0;
4439 *pDOS_time = 0;
4440 return;
4441 }
4442 #else
4443 struct tm *tm = localtime(&time);
4444 #endif /* #ifdef _MSC_VER */
4445
4446 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
4447 ((tm->tm_sec) >> 1));
4448 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
4449 ((tm->tm_mon + 1) << 5) + tm->tm_mday);
4450 }
4451 #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
4452
4453 #ifndef MINIZ_NO_STDIO
4454 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_get_file_modified_time(const char * pFilename,time_t * pTime)4455 static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
4456 time_t *pTime) {
4457 struct MZ_FILE_STAT_STRUCT file_stat;
4458
4459 /* On Linux with x86 glibc, this call will fail on large files (I think >=
4460 * 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
4461 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
4462 return MZ_FALSE;
4463
4464 *pTime = file_stat.st_mtime;
4465
4466 return MZ_TRUE;
4467 }
4468 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
4469
mz_zip_set_file_times(const char * pFilename,time_t access_time,time_t modified_time)4470 static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
4471 time_t modified_time) {
4472 struct utimbuf t;
4473
4474 memset(&t, 0, sizeof(t));
4475 t.actime = access_time;
4476 t.modtime = modified_time;
4477
4478 return !utime(pFilename, &t);
4479 }
4480 #endif /* #ifndef MINIZ_NO_STDIO */
4481 #endif /* #ifndef MINIZ_NO_TIME */
4482
mz_zip_set_error(mz_zip_archive * pZip,mz_zip_error err_num)4483 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
4484 mz_zip_error err_num) {
4485 if (pZip)
4486 pZip->m_last_error = err_num;
4487 return MZ_FALSE;
4488 }
4489
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint32 flags)4490 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
4491 mz_uint32 flags) {
4492 (void)flags;
4493 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
4494 return MZ_FALSE;
4495
4496 if (!pZip->m_pAlloc)
4497 pZip->m_pAlloc = def_alloc_func;
4498 if (!pZip->m_pFree)
4499 pZip->m_pFree = def_free_func;
4500 if (!pZip->m_pRealloc)
4501 pZip->m_pRealloc = def_realloc_func;
4502
4503 pZip->m_zip_mode = MZ_ZIP_MODE_READING;
4504 pZip->m_archive_size = 0;
4505 pZip->m_central_directory_file_ofs = 0;
4506 pZip->m_total_files = 0;
4507
4508 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
4509 pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
4510 return MZ_FALSE;
4511 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
4512 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
4513 sizeof(mz_uint8));
4514 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
4515 sizeof(mz_uint32));
4516 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
4517 sizeof(mz_uint32));
4518 return MZ_TRUE;
4519 }
4520
4521 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)4522 mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
4523 const mz_zip_array *pCentral_dir_offsets,
4524 mz_uint l_index, mz_uint r_index) {
4525 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
4526 pCentral_dir_array, mz_uint8,
4527 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
4528 l_index)),
4529 *pE;
4530 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
4531 pCentral_dir_array, mz_uint8,
4532 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
4533 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
4534 r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4535 mz_uint8 l = 0, r = 0;
4536 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4537 pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4538 pE = pL + MZ_MIN(l_len, r_len);
4539 while (pL < pE) {
4540 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4541 break;
4542 pL++;
4543 pR++;
4544 }
4545 return (pL == pE) ? (l_len < r_len) : (l < r);
4546 }
4547
4548 #define MZ_SWAP_UINT32(a, b) \
4549 do { \
4550 mz_uint32 t = a; \
4551 a = b; \
4552 b = t; \
4553 } \
4554 MZ_MACRO_END
4555
4556 // Heap sort of lowercased filenames, used to help accelerate plain central
4557 // directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
4558 // but it could allocate memory.)
4559 static void
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)4560 mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
4561 mz_zip_internal_state *pState = pZip->m_pState;
4562 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4563 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4564 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
4565 &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4566 const int size = pZip->m_total_files;
4567 int start = (size - 2) >> 1, end;
4568 while (start >= 0) {
4569 int child, root = start;
4570 for (;;) {
4571 if ((child = (root << 1) + 1) >= size)
4572 break;
4573 child +=
4574 (((child + 1) < size) &&
4575 (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4576 pIndices[child], pIndices[child + 1])));
4577 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4578 pIndices[root], pIndices[child]))
4579 break;
4580 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4581 root = child;
4582 }
4583 start--;
4584 }
4585
4586 end = size - 1;
4587 while (end > 0) {
4588 int child, root = 0;
4589 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
4590 for (;;) {
4591 if ((child = (root << 1) + 1) >= end)
4592 break;
4593 child +=
4594 (((child + 1) < end) &&
4595 mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4596 pIndices[child], pIndices[child + 1]));
4597 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4598 pIndices[root], pIndices[child]))
4599 break;
4600 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4601 root = child;
4602 }
4603 end--;
4604 }
4605 }
4606
mz_zip_reader_locate_header_sig(mz_zip_archive * pZip,mz_uint32 record_sig,mz_uint32 record_size,mz_int64 * pOfs)4607 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
4608 mz_uint32 record_sig,
4609 mz_uint32 record_size,
4610 mz_int64 *pOfs) {
4611 mz_int64 cur_file_ofs;
4612 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4613 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4614
4615 /* Basic sanity checks - reject files which are too small */
4616 if (pZip->m_archive_size < record_size)
4617 return MZ_FALSE;
4618
4619 /* Find the record by scanning the file from the end towards the beginning. */
4620 cur_file_ofs =
4621 MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
4622 for (;;) {
4623 int i,
4624 n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
4625
4626 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
4627 return MZ_FALSE;
4628
4629 for (i = n - 4; i >= 0; --i) {
4630 mz_uint s = MZ_READ_LE32(pBuf + i);
4631 if (s == record_sig) {
4632 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
4633 break;
4634 }
4635 }
4636
4637 if (i >= 0) {
4638 cur_file_ofs += i;
4639 break;
4640 }
4641
4642 /* Give up if we've searched the entire file, or we've gone back "too far"
4643 * (~64kb) */
4644 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
4645 (MZ_UINT16_MAX + record_size)))
4646 return MZ_FALSE;
4647
4648 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
4649 }
4650
4651 *pOfs = cur_file_ofs;
4652 return MZ_TRUE;
4653 }
4654
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint flags)4655 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
4656 mz_uint flags) {
4657 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
4658 cdir_disk_index = 0;
4659 mz_uint64 cdir_ofs = 0;
4660 mz_int64 cur_file_ofs = 0;
4661 const mz_uint8 *p;
4662
4663 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4664 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4665 mz_bool sort_central_dir =
4666 ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
4667 mz_uint32 zip64_end_of_central_dir_locator_u32
4668 [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
4669 sizeof(mz_uint32)];
4670 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
4671
4672 mz_uint32 zip64_end_of_central_dir_header_u32
4673 [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
4674 sizeof(mz_uint32)];
4675 mz_uint8 *pZip64_end_of_central_dir =
4676 (mz_uint8 *)zip64_end_of_central_dir_header_u32;
4677
4678 mz_uint64 zip64_end_of_central_dir_ofs = 0;
4679
4680 /* Basic sanity checks - reject files which are too small, and check the first
4681 * 4 bytes of the file to make sure a local header is there. */
4682 if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4683 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4684
4685 if (!mz_zip_reader_locate_header_sig(
4686 pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
4687 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
4688 return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
4689
4690 /* Read and verify the end of central directory record. */
4691 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
4692 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
4693 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4694 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4695
4696 if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
4697 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
4698 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4699
4700 if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
4701 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
4702 if (pZip->m_pRead(pZip->m_pIO_opaque,
4703 cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
4704 pZip64_locator,
4705 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
4706 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
4707 if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
4708 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
4709 zip64_end_of_central_dir_ofs = MZ_READ_LE64(
4710 pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
4711 if (zip64_end_of_central_dir_ofs >
4712 (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
4713 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4714
4715 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
4716 pZip64_end_of_central_dir,
4717 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
4718 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
4719 if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
4720 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
4721 pZip->m_pState->m_zip64 = MZ_TRUE;
4722 }
4723 }
4724 }
4725 }
4726 }
4727
4728 pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4729 cdir_entries_on_this_disk =
4730 MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4731 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
4732 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
4733 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
4734 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
4735
4736 if (pZip->m_pState->m_zip64) {
4737 mz_uint32 zip64_total_num_of_disks =
4738 MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
4739 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
4740 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4741 mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
4742 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4743 mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
4744 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
4745 mz_uint64 zip64_size_of_central_directory =
4746 MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
4747
4748 if (zip64_size_of_end_of_central_dir_record <
4749 (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
4750 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4751
4752 if (zip64_total_num_of_disks != 1U)
4753 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4754
4755 /* Check for miniz's practical limits */
4756 if (zip64_cdir_total_entries > MZ_UINT32_MAX)
4757 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4758
4759 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
4760
4761 if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
4762 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4763
4764 cdir_entries_on_this_disk =
4765 (mz_uint32)zip64_cdir_total_entries_on_this_disk;
4766
4767 /* Check for miniz's current practical limits (sorry, this should be enough
4768 * for millions of files) */
4769 if (zip64_size_of_central_directory > MZ_UINT32_MAX)
4770 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
4771
4772 cdir_size = (mz_uint32)zip64_size_of_central_directory;
4773
4774 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
4775 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
4776
4777 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
4778 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
4779
4780 cdir_ofs =
4781 MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
4782 }
4783
4784 if (pZip->m_total_files != cdir_entries_on_this_disk)
4785 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4786
4787 if (((num_this_disk | cdir_disk_index) != 0) &&
4788 ((num_this_disk != 1) || (cdir_disk_index != 1)))
4789 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4790
4791 if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
4792 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4793
4794 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
4795 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4796
4797 pZip->m_central_directory_file_ofs = cdir_ofs;
4798
4799 if (pZip->m_total_files) {
4800 mz_uint i, n;
4801 /* Read the entire central directory into a heap block, and allocate another
4802 * heap block to hold the unsorted central dir file record offsets, and
4803 * possibly another to hold the sorted indices. */
4804 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
4805 MZ_FALSE)) ||
4806 (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
4807 pZip->m_total_files, MZ_FALSE)))
4808 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4809
4810 if (sort_central_dir) {
4811 if (!mz_zip_array_resize(pZip,
4812 &pZip->m_pState->m_sorted_central_dir_offsets,
4813 pZip->m_total_files, MZ_FALSE))
4814 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4815 }
4816
4817 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
4818 pZip->m_pState->m_central_dir.m_p,
4819 cdir_size) != cdir_size)
4820 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4821
4822 /* Now create an index into the central directory file records, do some
4823 * basic sanity checking on each record */
4824 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
4825 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
4826 mz_uint total_header_size, disk_index, bit_flags, filename_size,
4827 ext_data_size;
4828 mz_uint64 comp_size, decomp_size, local_header_ofs;
4829
4830 if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
4831 (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
4832 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4833
4834 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
4835 i) =
4836 (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
4837
4838 if (sort_central_dir)
4839 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
4840 mz_uint32, i) = i;
4841
4842 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4843 decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4844 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4845 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4846 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4847
4848 if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
4849 (ext_data_size) &&
4850 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
4851 MZ_UINT32_MAX)) {
4852 /* Attempt to find zip64 extended information field in the entry's extra
4853 * data */
4854 mz_uint32 extra_size_remaining = ext_data_size;
4855
4856 if (extra_size_remaining) {
4857 const mz_uint8 *pExtra_data;
4858 void *buf = NULL;
4859
4860 if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
4861 n) {
4862 buf = MZ_MALLOC(ext_data_size);
4863 if (buf == NULL)
4864 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4865
4866 if (pZip->m_pRead(pZip->m_pIO_opaque,
4867 cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4868 filename_size,
4869 buf, ext_data_size) != ext_data_size) {
4870 MZ_FREE(buf);
4871 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4872 }
4873
4874 pExtra_data = (mz_uint8 *)buf;
4875 } else {
4876 pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
4877 }
4878
4879 do {
4880 mz_uint32 field_id;
4881 mz_uint32 field_data_size;
4882
4883 if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
4884 MZ_FREE(buf);
4885 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4886 }
4887
4888 field_id = MZ_READ_LE16(pExtra_data);
4889 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4890
4891 if ((field_data_size + sizeof(mz_uint16) * 2) >
4892 extra_size_remaining) {
4893 MZ_FREE(buf);
4894 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4895 }
4896
4897 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
4898 /* Ok, the archive didn't have any zip64 headers but it uses a
4899 * zip64 extended information field so mark it as zip64 anyway
4900 * (this can occur with infozip's zip util when it reads
4901 * compresses files from stdin). */
4902 pZip->m_pState->m_zip64 = MZ_TRUE;
4903 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
4904 break;
4905 }
4906
4907 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4908 extra_size_remaining =
4909 extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4910 } while (extra_size_remaining);
4911
4912 MZ_FREE(buf);
4913 }
4914 }
4915
4916 /* I've seen archives that aren't marked as zip64 that uses zip64 ext
4917 * data, argh */
4918 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
4919 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
4920 (decomp_size != comp_size)) ||
4921 (decomp_size && !comp_size))
4922 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4923 }
4924
4925 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
4926 if ((disk_index == MZ_UINT16_MAX) ||
4927 ((disk_index != num_this_disk) && (disk_index != 1)))
4928 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4929
4930 if (comp_size != MZ_UINT32_MAX) {
4931 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
4932 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
4933 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4934 }
4935
4936 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4937 if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
4938 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4939
4940 if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4941 MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
4942 MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
4943 MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
4944 n)
4945 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4946
4947 n -= total_header_size;
4948 p += total_header_size;
4949 }
4950 }
4951
4952 if (sort_central_dir)
4953 mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
4954
4955 return MZ_TRUE;
4956 }
4957
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint32 flags)4958 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
4959 mz_uint32 flags) {
4960 if ((!pZip) || (!pZip->m_pRead))
4961 return MZ_FALSE;
4962 if (!mz_zip_reader_init_internal(pZip, flags))
4963 return MZ_FALSE;
4964 pZip->m_archive_size = size;
4965 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
4966 mz_zip_reader_end(pZip);
4967 return MZ_FALSE;
4968 }
4969 return MZ_TRUE;
4970 }
4971
mz_zip_mem_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)4972 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
4973 void *pBuf, size_t n) {
4974 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4975 size_t s = (file_ofs >= pZip->m_archive_size)
4976 ? 0
4977 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
4978 memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
4979 return s;
4980 }
4981
mz_zip_reader_init_mem(mz_zip_archive * pZip,const void * pMem,size_t size,mz_uint32 flags)4982 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
4983 size_t size, mz_uint32 flags) {
4984 if (!mz_zip_reader_init_internal(pZip, flags))
4985 return MZ_FALSE;
4986 pZip->m_archive_size = size;
4987 pZip->m_pRead = mz_zip_mem_read_func;
4988 pZip->m_pIO_opaque = pZip;
4989 #ifdef __cplusplus
4990 pZip->m_pState->m_pMem = const_cast<void *>(pMem);
4991 #else
4992 pZip->m_pState->m_pMem = (void *)pMem;
4993 #endif
4994 pZip->m_pState->m_mem_size = size;
4995 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
4996 mz_zip_reader_end(pZip);
4997 return MZ_FALSE;
4998 }
4999 return MZ_TRUE;
5000 }
5001
5002 #ifndef MINIZ_NO_STDIO
mz_zip_file_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)5003 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5004 void *pBuf, size_t n) {
5005 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5006 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5007 if (((mz_int64)file_ofs < 0) ||
5008 (((cur_ofs != (mz_int64)file_ofs)) &&
5009 (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5010 return 0;
5011 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5012 }
5013
mz_zip_reader_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint32 flags)5014 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5015 mz_uint32 flags) {
5016 mz_uint64 file_size;
5017 MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
5018 if (!pFile)
5019 return MZ_FALSE;
5020 if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5021 MZ_FCLOSE(pFile);
5022 return MZ_FALSE;
5023 }
5024 file_size = MZ_FTELL64(pFile);
5025 if (!mz_zip_reader_init_internal(pZip, flags)) {
5026 MZ_FCLOSE(pFile);
5027 return MZ_FALSE;
5028 }
5029 pZip->m_pRead = mz_zip_file_read_func;
5030 pZip->m_pIO_opaque = pZip;
5031 pZip->m_pState->m_pFile = pFile;
5032 pZip->m_archive_size = file_size;
5033 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5034 mz_zip_reader_end(pZip);
5035 return MZ_FALSE;
5036 }
5037 return MZ_TRUE;
5038 }
5039 #endif // #ifndef MINIZ_NO_STDIO
5040
mz_zip_reader_get_num_files(mz_zip_archive * pZip)5041 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5042 return pZip ? pZip->m_total_files : 0;
5043 }
5044
5045 static MZ_FORCEINLINE const mz_uint8 *
mz_zip_reader_get_cdh(mz_zip_archive * pZip,mz_uint file_index)5046 mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) {
5047 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) ||
5048 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5049 return NULL;
5050 return &MZ_ZIP_ARRAY_ELEMENT(
5051 &pZip->m_pState->m_central_dir, mz_uint8,
5052 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5053 file_index));
5054 }
5055
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)5056 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
5057 mz_uint file_index) {
5058 mz_uint m_bit_flag;
5059 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5060 if (!p)
5061 return MZ_FALSE;
5062 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5063 return (m_bit_flag & 1);
5064 }
5065
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)5066 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
5067 mz_uint file_index) {
5068 mz_uint filename_len, external_attr;
5069 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5070 if (!p)
5071 return MZ_FALSE;
5072
5073 // First see if the filename ends with a '/' character.
5074 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5075 if (filename_len) {
5076 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
5077 return MZ_TRUE;
5078 }
5079
5080 // Bugfix: This code was also checking if the internal attribute was non-zero,
5081 // which wasn't correct. Most/all zip writers (hopefully) set DOS
5082 // file/directory attributes in the low 16-bits, so check for the DOS
5083 // directory flag and ignore the source OS ID in the created by field.
5084 // FIXME: Remove this check? Is it necessary - we already check the filename.
5085 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5086 if ((external_attr & 0x10) != 0)
5087 return MZ_TRUE;
5088
5089 return MZ_FALSE;
5090 }
5091
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)5092 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
5093 mz_zip_archive_file_stat *pStat) {
5094 mz_uint n;
5095 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5096 if ((!p) || (!pStat))
5097 return MZ_FALSE;
5098
5099 // Unpack the central directory record.
5100 pStat->m_file_index = file_index;
5101 pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
5102 &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
5103 pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
5104 pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
5105 pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5106 pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
5107 #ifndef MINIZ_NO_TIME
5108 pStat->m_time =
5109 mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
5110 MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
5111 #endif
5112 pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
5113 pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5114 pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5115 pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
5116 pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5117 pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5118
5119 // Copy as much of the filename and comment as possible.
5120 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5121 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
5122 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5123 pStat->m_filename[n] = '\0';
5124
5125 n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5126 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
5127 pStat->m_comment_size = n;
5128 memcpy(pStat->m_comment,
5129 p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5130 MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5131 MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5132 n);
5133 pStat->m_comment[n] = '\0';
5134
5135 return MZ_TRUE;
5136 }
5137
mz_zip_reader_get_filename(mz_zip_archive * pZip,mz_uint file_index,char * pFilename,mz_uint filename_buf_size)5138 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
5139 char *pFilename, mz_uint filename_buf_size) {
5140 mz_uint n;
5141 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5142 if (!p) {
5143 if (filename_buf_size)
5144 pFilename[0] = '\0';
5145 return 0;
5146 }
5147 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5148 if (filename_buf_size) {
5149 n = MZ_MIN(n, filename_buf_size - 1);
5150 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5151 pFilename[n] = '\0';
5152 }
5153 return n + 1;
5154 }
5155
mz_zip_reader_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)5156 static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA,
5157 const char *pB,
5158 mz_uint len,
5159 mz_uint flags) {
5160 mz_uint i;
5161 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
5162 return 0 == memcmp(pA, pB, len);
5163 for (i = 0; i < len; ++i)
5164 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
5165 return MZ_FALSE;
5166 return MZ_TRUE;
5167 }
5168
5169 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)5170 mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array,
5171 const mz_zip_array *pCentral_dir_offsets,
5172 mz_uint l_index, const char *pR, mz_uint r_len) {
5173 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5174 pCentral_dir_array, mz_uint8,
5175 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5176 l_index)),
5177 *pE;
5178 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5179 mz_uint8 l = 0, r = 0;
5180 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5181 pE = pL + MZ_MIN(l_len, r_len);
5182 while (pL < pE) {
5183 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
5184 break;
5185 pL++;
5186 pR++;
5187 }
5188 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
5189 }
5190
mz_zip_reader_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename)5191 static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip,
5192 const char *pFilename) {
5193 mz_zip_internal_state *pState = pZip->m_pState;
5194 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5195 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5196 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
5197 &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
5198 const int size = pZip->m_total_files;
5199 const mz_uint filename_len = (mz_uint)strlen(pFilename);
5200 int l = 0, h = size - 1;
5201 while (l <= h) {
5202 int m = (l + h) >> 1, file_index = pIndices[m],
5203 comp =
5204 mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets,
5205 file_index, pFilename, filename_len);
5206 if (!comp)
5207 return file_index;
5208 else if (comp < 0)
5209 l = m + 1;
5210 else
5211 h = m - 1;
5212 }
5213 return -1;
5214 }
5215
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)5216 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
5217 const char *pComment, mz_uint flags) {
5218 mz_uint file_index;
5219 size_t name_len, comment_len;
5220 if ((!pZip) || (!pZip->m_pState) || (!pName) ||
5221 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5222 return -1;
5223 if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
5224 (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
5225 return mz_zip_reader_locate_file_binary_search(pZip, pName);
5226 name_len = strlen(pName);
5227 if (name_len > 0xFFFF)
5228 return -1;
5229 comment_len = pComment ? strlen(pComment) : 0;
5230 if (comment_len > 0xFFFF)
5231 return -1;
5232 for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
5233 const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
5234 &pZip->m_pState->m_central_dir, mz_uint8,
5235 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5236 file_index));
5237 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5238 const char *pFilename =
5239 (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5240 if (filename_len < name_len)
5241 continue;
5242 if (comment_len) {
5243 mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5244 file_comment_len =
5245 MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5246 const char *pFile_comment = pFilename + filename_len + file_extra_len;
5247 if ((file_comment_len != comment_len) ||
5248 (!mz_zip_reader_string_equal(pComment, pFile_comment,
5249 file_comment_len, flags)))
5250 continue;
5251 }
5252 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
5253 int ofs = filename_len - 1;
5254 do {
5255 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
5256 (pFilename[ofs] == ':'))
5257 break;
5258 } while (--ofs >= 0);
5259 ofs++;
5260 pFilename += ofs;
5261 filename_len -= ofs;
5262 }
5263 if ((filename_len == name_len) &&
5264 (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
5265 return file_index;
5266 }
5267 return -1;
5268 }
5269
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)5270 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
5271 mz_uint file_index, void *pBuf,
5272 size_t buf_size, mz_uint flags,
5273 void *pUser_read_buf,
5274 size_t user_read_buf_size) {
5275 int status = TINFL_STATUS_DONE;
5276 mz_uint64 needed_size, cur_file_ofs, comp_remaining,
5277 out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
5278 mz_zip_archive_file_stat file_stat;
5279 void *pRead_buf;
5280 mz_uint32
5281 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5282 sizeof(mz_uint32)];
5283 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5284 tinfl_decompressor inflator;
5285
5286 if ((buf_size) && (!pBuf))
5287 return MZ_FALSE;
5288
5289 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5290 return MZ_FALSE;
5291
5292 // Empty file, or a directory (but not always a directory - I've seen odd zips
5293 // with directories that have compressed data which inflates to 0 bytes)
5294 if (!file_stat.m_comp_size)
5295 return MZ_TRUE;
5296
5297 // Entry is a subdirectory (I've seen old zips with dir entries which have
5298 // compressed deflate data which inflates to 0 bytes, but these entries claim
5299 // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5300 // case - should it fail instead?
5301 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5302 return MZ_TRUE;
5303
5304 // Encryption and patch files are not supported.
5305 if (file_stat.m_bit_flag & (1 | 32))
5306 return MZ_FALSE;
5307
5308 // This function only supports stored and deflate.
5309 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5310 (file_stat.m_method != MZ_DEFLATED))
5311 return MZ_FALSE;
5312
5313 // Ensure supplied output buffer is large enough.
5314 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
5315 : file_stat.m_uncomp_size;
5316 if (buf_size < needed_size)
5317 return MZ_FALSE;
5318
5319 // Read and parse the local directory entry.
5320 cur_file_ofs = file_stat.m_local_header_ofs;
5321 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5322 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5323 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5324 return MZ_FALSE;
5325 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5326 return MZ_FALSE;
5327
5328 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5329 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5330 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5331 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5332 return MZ_FALSE;
5333
5334 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5335 // The file is stored or the caller has requested the compressed data.
5336 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5337 (size_t)needed_size) != needed_size)
5338 return MZ_FALSE;
5339 return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) ||
5340 (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5341 (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
5342 }
5343
5344 // Decompress the file either directly from memory or from a file input
5345 // buffer.
5346 tinfl_init(&inflator);
5347
5348 if (pZip->m_pState->m_pMem) {
5349 // Read directly from the archive in memory.
5350 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5351 read_buf_size = read_buf_avail = file_stat.m_comp_size;
5352 comp_remaining = 0;
5353 } else if (pUser_read_buf) {
5354 // Use a user provided read buffer.
5355 if (!user_read_buf_size)
5356 return MZ_FALSE;
5357 pRead_buf = (mz_uint8 *)pUser_read_buf;
5358 read_buf_size = user_read_buf_size;
5359 read_buf_avail = 0;
5360 comp_remaining = file_stat.m_comp_size;
5361 } else {
5362 // Temporarily allocate a read buffer.
5363 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5364 #ifdef _MSC_VER
5365 if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5366 (read_buf_size > 0x7FFFFFFF))
5367 #else
5368 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
5369 #endif
5370 return MZ_FALSE;
5371 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5372 (size_t)read_buf_size)))
5373 return MZ_FALSE;
5374 read_buf_avail = 0;
5375 comp_remaining = file_stat.m_comp_size;
5376 }
5377
5378 do {
5379 size_t in_buf_size,
5380 out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
5381 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5382 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5383 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5384 (size_t)read_buf_avail) != read_buf_avail) {
5385 status = TINFL_STATUS_FAILED;
5386 break;
5387 }
5388 cur_file_ofs += read_buf_avail;
5389 comp_remaining -= read_buf_avail;
5390 read_buf_ofs = 0;
5391 }
5392 in_buf_size = (size_t)read_buf_avail;
5393 status = tinfl_decompress(
5394 &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5395 (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
5396 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
5397 (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
5398 read_buf_avail -= in_buf_size;
5399 read_buf_ofs += in_buf_size;
5400 out_buf_ofs += out_buf_size;
5401 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
5402
5403 if (status == TINFL_STATUS_DONE) {
5404 // Make sure the entire file was decompressed, and check its CRC.
5405 if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5406 (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5407 (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
5408 status = TINFL_STATUS_FAILED;
5409 }
5410
5411 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
5412 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5413
5414 return status == TINFL_STATUS_DONE;
5415 }
5416
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)5417 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
5418 mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
5419 mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
5420 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5421 if (file_index < 0)
5422 return MZ_FALSE;
5423 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5424 flags, pUser_read_buf,
5425 user_read_buf_size);
5426 }
5427
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)5428 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
5429 void *pBuf, size_t buf_size,
5430 mz_uint flags) {
5431 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5432 flags, NULL, 0);
5433 }
5434
mz_zip_reader_extract_file_to_mem(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags)5435 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
5436 const char *pFilename, void *pBuf,
5437 size_t buf_size, mz_uint flags) {
5438 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
5439 buf_size, flags, NULL, 0);
5440 }
5441
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)5442 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
5443 size_t *pSize, mz_uint flags) {
5444 mz_uint64 comp_size, uncomp_size, alloc_size;
5445 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5446 void *pBuf;
5447
5448 if (pSize)
5449 *pSize = 0;
5450 if (!p)
5451 return NULL;
5452
5453 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5454 uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5455
5456 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
5457 #ifdef _MSC_VER
5458 if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5459 #else
5460 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5461 #endif
5462 return NULL;
5463 if (NULL ==
5464 (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
5465 return NULL;
5466
5467 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
5468 flags)) {
5469 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
5470 return NULL;
5471 }
5472
5473 if (pSize)
5474 *pSize = (size_t)alloc_size;
5475 return pBuf;
5476 }
5477
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)5478 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
5479 const char *pFilename, size_t *pSize,
5480 mz_uint flags) {
5481 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5482 if (file_index < 0) {
5483 if (pSize)
5484 *pSize = 0;
5485 return MZ_FALSE;
5486 }
5487 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
5488 }
5489
mz_zip_reader_extract_to_callback(mz_zip_archive * pZip,mz_uint file_index,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5490 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
5491 mz_uint file_index,
5492 mz_file_write_func pCallback,
5493 void *pOpaque, mz_uint flags) {
5494 int status = TINFL_STATUS_DONE;
5495 mz_uint file_crc32 = MZ_CRC32_INIT;
5496 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
5497 out_buf_ofs = 0, cur_file_ofs;
5498 mz_zip_archive_file_stat file_stat;
5499 void *pRead_buf = NULL;
5500 void *pWrite_buf = NULL;
5501 mz_uint32
5502 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5503 sizeof(mz_uint32)];
5504 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5505
5506 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5507 return MZ_FALSE;
5508
5509 // Empty file, or a directory (but not always a directory - I've seen odd zips
5510 // with directories that have compressed data which inflates to 0 bytes)
5511 if (!file_stat.m_comp_size)
5512 return MZ_TRUE;
5513
5514 // Entry is a subdirectory (I've seen old zips with dir entries which have
5515 // compressed deflate data which inflates to 0 bytes, but these entries claim
5516 // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5517 // case - should it fail instead?
5518 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5519 return MZ_TRUE;
5520
5521 // Encryption and patch files are not supported.
5522 if (file_stat.m_bit_flag & (1 | 32))
5523 return MZ_FALSE;
5524
5525 // This function only supports stored and deflate.
5526 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5527 (file_stat.m_method != MZ_DEFLATED))
5528 return MZ_FALSE;
5529
5530 // Read and parse the local directory entry.
5531 cur_file_ofs = file_stat.m_local_header_ofs;
5532 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5533 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5534 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5535 return MZ_FALSE;
5536 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5537 return MZ_FALSE;
5538
5539 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5540 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5541 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5542 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5543 return MZ_FALSE;
5544
5545 // Decompress the file either directly from memory or from a file input
5546 // buffer.
5547 if (pZip->m_pState->m_pMem) {
5548 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5549 read_buf_size = read_buf_avail = file_stat.m_comp_size;
5550 comp_remaining = 0;
5551 } else {
5552 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5553 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5554 (size_t)read_buf_size)))
5555 return MZ_FALSE;
5556 read_buf_avail = 0;
5557 comp_remaining = file_stat.m_comp_size;
5558 }
5559
5560 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5561 // The file is stored or the caller has requested the compressed data.
5562 if (pZip->m_pState->m_pMem) {
5563 #ifdef _MSC_VER
5564 if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
5565 (file_stat.m_comp_size > 0xFFFFFFFF))
5566 #else
5567 if (((sizeof(size_t) == sizeof(mz_uint32))) &&
5568 (file_stat.m_comp_size > 0xFFFFFFFF))
5569 #endif
5570 return MZ_FALSE;
5571 if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5572 (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
5573 status = TINFL_STATUS_FAILED;
5574 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5575 file_crc32 =
5576 (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
5577 (size_t)file_stat.m_comp_size);
5578 // cur_file_ofs += file_stat.m_comp_size;
5579 out_buf_ofs += file_stat.m_comp_size;
5580 // comp_remaining = 0;
5581 } else {
5582 while (comp_remaining) {
5583 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5584 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5585 (size_t)read_buf_avail) != read_buf_avail) {
5586 status = TINFL_STATUS_FAILED;
5587 break;
5588 }
5589
5590 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5591 file_crc32 = (mz_uint32)mz_crc32(
5592 file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
5593
5594 if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5595 (size_t)read_buf_avail) != read_buf_avail) {
5596 status = TINFL_STATUS_FAILED;
5597 break;
5598 }
5599 cur_file_ofs += read_buf_avail;
5600 out_buf_ofs += read_buf_avail;
5601 comp_remaining -= read_buf_avail;
5602 }
5603 }
5604 } else {
5605 tinfl_decompressor inflator;
5606 tinfl_init(&inflator);
5607
5608 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5609 TINFL_LZ_DICT_SIZE)))
5610 status = TINFL_STATUS_FAILED;
5611 else {
5612 do {
5613 mz_uint8 *pWrite_buf_cur =
5614 (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5615 size_t in_buf_size,
5616 out_buf_size =
5617 TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5618 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5619 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5620 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5621 (size_t)read_buf_avail) != read_buf_avail) {
5622 status = TINFL_STATUS_FAILED;
5623 break;
5624 }
5625 cur_file_ofs += read_buf_avail;
5626 comp_remaining -= read_buf_avail;
5627 read_buf_ofs = 0;
5628 }
5629
5630 in_buf_size = (size_t)read_buf_avail;
5631 status = tinfl_decompress(
5632 &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5633 (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
5634 comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5635 read_buf_avail -= in_buf_size;
5636 read_buf_ofs += in_buf_size;
5637
5638 if (out_buf_size) {
5639 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
5640 out_buf_size) {
5641 status = TINFL_STATUS_FAILED;
5642 break;
5643 }
5644 file_crc32 =
5645 (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
5646 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
5647 status = TINFL_STATUS_FAILED;
5648 break;
5649 }
5650 }
5651 } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
5652 (status == TINFL_STATUS_HAS_MORE_OUTPUT));
5653 }
5654 }
5655
5656 if ((status == TINFL_STATUS_DONE) &&
5657 (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
5658 // Make sure the entire file was decompressed, and check its CRC.
5659 if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5660 (file_crc32 != file_stat.m_crc32))
5661 status = TINFL_STATUS_FAILED;
5662 }
5663
5664 if (!pZip->m_pState->m_pMem)
5665 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5666 if (pWrite_buf)
5667 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
5668
5669 return status == TINFL_STATUS_DONE;
5670 }
5671
mz_zip_reader_extract_file_to_callback(mz_zip_archive * pZip,const char * pFilename,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)5672 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
5673 const char *pFilename,
5674 mz_file_write_func pCallback,
5675 void *pOpaque, mz_uint flags) {
5676 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5677 if (file_index < 0)
5678 return MZ_FALSE;
5679 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
5680 flags);
5681 }
5682
5683 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_callback(void * pOpaque,mz_uint64 ofs,const void * pBuf,size_t n)5684 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
5685 const void *pBuf, size_t n) {
5686 (void)ofs;
5687 return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5688 }
5689
mz_zip_reader_extract_to_file(mz_zip_archive * pZip,mz_uint file_index,const char * pDst_filename,mz_uint flags)5690 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
5691 const char *pDst_filename,
5692 mz_uint flags) {
5693 mz_bool status;
5694 mz_zip_archive_file_stat file_stat;
5695 MZ_FILE *pFile;
5696 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5697 return MZ_FALSE;
5698
5699 pFile = MZ_FOPEN(pDst_filename, "wb");
5700 if (!pFile)
5701 return MZ_FALSE;
5702 status = mz_zip_reader_extract_to_callback(
5703 pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5704 if (MZ_FCLOSE(pFile) == EOF)
5705 return MZ_FALSE;
5706 #ifndef MINIZ_NO_TIME
5707 if (status) {
5708 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5709 }
5710 #endif
5711
5712 return status;
5713 }
5714 #endif // #ifndef MINIZ_NO_STDIO
5715
mz_zip_reader_end(mz_zip_archive * pZip)5716 mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5717 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5718 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5719 return MZ_FALSE;
5720
5721 mz_zip_internal_state *pState = pZip->m_pState;
5722 pZip->m_pState = NULL;
5723 mz_zip_array_clear(pZip, &pState->m_central_dir);
5724 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5725 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5726
5727 #ifndef MINIZ_NO_STDIO
5728 if (pState->m_pFile) {
5729 MZ_FCLOSE(pState->m_pFile);
5730 pState->m_pFile = NULL;
5731 }
5732 #endif // #ifndef MINIZ_NO_STDIO
5733
5734 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5735
5736 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5737
5738 return MZ_TRUE;
5739 }
5740
5741 #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)5742 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
5743 const char *pArchive_filename,
5744 const char *pDst_filename,
5745 mz_uint flags) {
5746 int file_index =
5747 mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
5748 if (file_index < 0)
5749 return MZ_FALSE;
5750 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5751 }
5752 #endif
5753
5754 // ------------------- .ZIP archive writing
5755
5756 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5757
mz_write_le16(mz_uint8 * p,mz_uint16 v)5758 static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5759 p[0] = (mz_uint8)v;
5760 p[1] = (mz_uint8)(v >> 8);
5761 }
mz_write_le32(mz_uint8 * p,mz_uint32 v)5762 static void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
5763 p[0] = (mz_uint8)v;
5764 p[1] = (mz_uint8)(v >> 8);
5765 p[2] = (mz_uint8)(v >> 16);
5766 p[3] = (mz_uint8)(v >> 24);
5767 }
5768 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5769 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5770
mz_zip_writer_init(mz_zip_archive * pZip,mz_uint64 existing_size)5771 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
5772 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
5773 (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5774 return MZ_FALSE;
5775
5776 if (pZip->m_file_offset_alignment) {
5777 // Ensure user specified file offset alignment is a power of 2.
5778 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5779 return MZ_FALSE;
5780 }
5781
5782 if (!pZip->m_pAlloc)
5783 pZip->m_pAlloc = def_alloc_func;
5784 if (!pZip->m_pFree)
5785 pZip->m_pFree = def_free_func;
5786 if (!pZip->m_pRealloc)
5787 pZip->m_pRealloc = def_realloc_func;
5788
5789 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5790 pZip->m_archive_size = existing_size;
5791 pZip->m_central_directory_file_ofs = 0;
5792 pZip->m_total_files = 0;
5793
5794 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5795 pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5796 return MZ_FALSE;
5797 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5798 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5799 sizeof(mz_uint8));
5800 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5801 sizeof(mz_uint32));
5802 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5803 sizeof(mz_uint32));
5804 return MZ_TRUE;
5805 }
5806
mz_zip_heap_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5807 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
5808 const void *pBuf, size_t n) {
5809 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5810 mz_zip_internal_state *pState = pZip->m_pState;
5811 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5812
5813 if ((!n) ||
5814 ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5815 return 0;
5816
5817 if (new_size > pState->m_mem_capacity) {
5818 void *pNew_block;
5819 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5820 while (new_capacity < new_size)
5821 new_capacity *= 2;
5822 if (NULL == (pNew_block = pZip->m_pRealloc(
5823 pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5824 return 0;
5825 pState->m_pMem = pNew_block;
5826 pState->m_mem_capacity = new_capacity;
5827 }
5828 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5829 pState->m_mem_size = (size_t)new_size;
5830 return n;
5831 }
5832
mz_zip_writer_init_heap(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size)5833 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
5834 size_t size_to_reserve_at_beginning,
5835 size_t initial_allocation_size) {
5836 pZip->m_pWrite = mz_zip_heap_write_func;
5837 pZip->m_pIO_opaque = pZip;
5838 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5839 return MZ_FALSE;
5840 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
5841 size_to_reserve_at_beginning))) {
5842 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
5843 pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
5844 mz_zip_writer_end(pZip);
5845 return MZ_FALSE;
5846 }
5847 pZip->m_pState->m_mem_capacity = initial_allocation_size;
5848 }
5849 return MZ_TRUE;
5850 }
5851
5852 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5853 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
5854 const void *pBuf, size_t n) {
5855 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5856 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5857 if (((mz_int64)file_ofs < 0) ||
5858 (((cur_ofs != (mz_int64)file_ofs)) &&
5859 (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5860 return 0;
5861 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5862 }
5863
mz_zip_writer_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning)5864 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
5865 mz_uint64 size_to_reserve_at_beginning) {
5866 MZ_FILE *pFile;
5867 pZip->m_pWrite = mz_zip_file_write_func;
5868 pZip->m_pIO_opaque = pZip;
5869 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5870 return MZ_FALSE;
5871 if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) {
5872 mz_zip_writer_end(pZip);
5873 return MZ_FALSE;
5874 }
5875 pZip->m_pState->m_pFile = pFile;
5876 if (size_to_reserve_at_beginning) {
5877 mz_uint64 cur_ofs = 0;
5878 char buf[4096];
5879 MZ_CLEAR_OBJ(buf);
5880 do {
5881 size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5882 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
5883 mz_zip_writer_end(pZip);
5884 return MZ_FALSE;
5885 }
5886 cur_ofs += n;
5887 size_to_reserve_at_beginning -= n;
5888 } while (size_to_reserve_at_beginning);
5889 }
5890 return MZ_TRUE;
5891 }
5892 #endif // #ifndef MINIZ_NO_STDIO
5893
mz_zip_writer_init_from_reader(mz_zip_archive * pZip,const char * pFilename)5894 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
5895 const char *pFilename) {
5896 mz_zip_internal_state *pState;
5897 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5898 return MZ_FALSE;
5899 // No sense in trying to write to an archive that's already at the support max
5900 // size
5901 if ((pZip->m_total_files == 0xFFFF) ||
5902 ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5903 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
5904 return MZ_FALSE;
5905
5906 pState = pZip->m_pState;
5907
5908 if (pState->m_pFile) {
5909 #ifdef MINIZ_NO_STDIO
5910 pFilename;
5911 return MZ_FALSE;
5912 #else
5913 // Archive is being read from stdio - try to reopen as writable.
5914 if (pZip->m_pIO_opaque != pZip)
5915 return MZ_FALSE;
5916 if (!pFilename)
5917 return MZ_FALSE;
5918 pZip->m_pWrite = mz_zip_file_write_func;
5919 if (NULL ==
5920 (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
5921 // The mz_zip_archive is now in a bogus state because pState->m_pFile is
5922 // NULL, so just close it.
5923 mz_zip_reader_end(pZip);
5924 return MZ_FALSE;
5925 }
5926 #endif // #ifdef MINIZ_NO_STDIO
5927 } else if (pState->m_pMem) {
5928 // Archive lives in a memory block. Assume it's from the heap that we can
5929 // resize using the realloc callback.
5930 if (pZip->m_pIO_opaque != pZip)
5931 return MZ_FALSE;
5932 pState->m_mem_capacity = pState->m_mem_size;
5933 pZip->m_pWrite = mz_zip_heap_write_func;
5934 }
5935 // Archive is being read via a user provided read function - make sure the
5936 // user has specified a write function too.
5937 else if (!pZip->m_pWrite)
5938 return MZ_FALSE;
5939
5940 // Start writing new files at the archive's current central directory
5941 // location.
5942 pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5943 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5944 pZip->m_central_directory_file_ofs = 0;
5945
5946 return MZ_TRUE;
5947 }
5948
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)5949 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
5950 const void *pBuf, size_t buf_size,
5951 mz_uint level_and_flags) {
5952 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
5953 level_and_flags, 0, 0);
5954 }
5955
5956 typedef struct {
5957 mz_zip_archive *m_pZip;
5958 mz_uint64 m_cur_archive_file_ofs;
5959 mz_uint64 m_comp_size;
5960 } mz_zip_writer_add_state;
5961
mz_zip_writer_add_put_buf_callback(const void * pBuf,int len,void * pUser)5962 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
5963 void *pUser) {
5964 mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
5965 if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
5966 pState->m_cur_archive_file_ofs, pBuf,
5967 len) != len)
5968 return MZ_FALSE;
5969 pState->m_cur_archive_file_ofs += len;
5970 pState->m_comp_size += len;
5971 return MZ_TRUE;
5972 }
5973
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)5974 static mz_bool mz_zip_writer_create_local_dir_header(
5975 mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
5976 mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
5977 mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
5978 mz_uint16 dos_time, mz_uint16 dos_date) {
5979 (void)pZip;
5980 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5981 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5982 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5983 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5984 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5985 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5986 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5987 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5988 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
5989 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
5990 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
5991 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
5992 return MZ_TRUE;
5993 }
5994
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)5995 static mz_bool mz_zip_writer_create_central_dir_header(
5996 mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
5997 mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
5998 mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
5999 mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6000 mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
6001 (void)pZip;
6002 mz_uint16 version_made_by = 10 * MZ_VER_MAJOR + MZ_VER_MINOR;
6003 version_made_by |= (MZ_PLATFORM << 8);
6004
6005 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6006 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6007 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, version_made_by);
6008 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6009 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6010 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6011 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6012 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6013 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6014 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
6015 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6016 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6017 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6018 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6019 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6020 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
6021 return MZ_TRUE;
6022 }
6023
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)6024 static mz_bool mz_zip_writer_add_to_central_dir(
6025 mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6026 const void *pExtra, mz_uint16 extra_size, const void *pComment,
6027 mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6028 mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6029 mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
6030 mz_uint32 ext_attributes) {
6031 mz_zip_internal_state *pState = pZip->m_pState;
6032 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6033 size_t orig_central_dir_size = pState->m_central_dir.m_size;
6034 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6035
6036 // No zip64 support yet
6037 if ((local_header_ofs > 0xFFFFFFFF) ||
6038 (((mz_uint64)pState->m_central_dir.m_size +
6039 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
6040 comment_size) > 0xFFFFFFFF))
6041 return MZ_FALSE;
6042
6043 if (!mz_zip_writer_create_central_dir_header(
6044 pZip, central_dir_header, filename_size, extra_size, comment_size,
6045 uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
6046 dos_date, local_header_ofs, ext_attributes))
6047 return MZ_FALSE;
6048
6049 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
6050 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6051 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
6052 filename_size)) ||
6053 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
6054 extra_size)) ||
6055 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
6056 comment_size)) ||
6057 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
6058 ¢ral_dir_ofs, 1))) {
6059 // Try to push the central directory array back into its original state.
6060 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6061 MZ_FALSE);
6062 return MZ_FALSE;
6063 }
6064
6065 return MZ_TRUE;
6066 }
6067
mz_zip_writer_validate_archive_name(const char * pArchive_name)6068 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
6069 // Basic ZIP archive filename validity checks: Valid filenames cannot start
6070 // with a forward slash, cannot contain a drive letter, and cannot use
6071 // DOS-style backward slashes.
6072 if (*pArchive_name == '/')
6073 return MZ_FALSE;
6074 while (*pArchive_name) {
6075 if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
6076 return MZ_FALSE;
6077 pArchive_name++;
6078 }
6079 return MZ_TRUE;
6080 }
6081
6082 static mz_uint
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive * pZip)6083 mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
6084 mz_uint32 n;
6085 if (!pZip->m_file_offset_alignment)
6086 return 0;
6087 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6088 return (pZip->m_file_offset_alignment - n) &
6089 (pZip->m_file_offset_alignment - 1);
6090 }
6091
mz_zip_writer_write_zeros(mz_zip_archive * pZip,mz_uint64 cur_file_ofs,mz_uint32 n)6092 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
6093 mz_uint64 cur_file_ofs, mz_uint32 n) {
6094 char buf[4096];
6095 memset(buf, 0, MZ_MIN(sizeof(buf), n));
6096 while (n) {
6097 mz_uint32 s = MZ_MIN(sizeof(buf), n);
6098 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6099 return MZ_FALSE;
6100 cur_file_ofs += s;
6101 n -= s;
6102 }
6103 return MZ_TRUE;
6104 }
6105
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)6106 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
6107 const char *pArchive_name, const void *pBuf,
6108 size_t buf_size, const void *pComment,
6109 mz_uint16 comment_size,
6110 mz_uint level_and_flags, mz_uint64 uncomp_size,
6111 mz_uint32 uncomp_crc32) {
6112 mz_uint32 ext_attributes = 0;
6113 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6114 mz_uint level, num_alignment_padding_bytes;
6115 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0;
6116 size_t archive_name_size;
6117 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6118 tdefl_compressor *pComp = NULL;
6119 mz_bool store_data_uncompressed;
6120 mz_zip_internal_state *pState;
6121
6122 if ((int)level_and_flags < 0)
6123 level_and_flags = MZ_DEFAULT_LEVEL;
6124 level = level_and_flags & 0xF;
6125 store_data_uncompressed =
6126 ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6127
6128 if ((!pZip) || (!pZip->m_pState) ||
6129 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
6130 (!pArchive_name) || ((comment_size) && (!pComment)) ||
6131 (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
6132 return MZ_FALSE;
6133
6134 local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6135 pState = pZip->m_pState;
6136
6137 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6138 return MZ_FALSE;
6139 // No zip64 support yet
6140 if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6141 return MZ_FALSE;
6142 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6143 return MZ_FALSE;
6144
6145 #ifndef MINIZ_NO_TIME
6146 {
6147 time_t cur_time;
6148 time(&cur_time);
6149 mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6150 }
6151 #endif // #ifndef MINIZ_NO_TIME
6152
6153 archive_name_size = strlen(pArchive_name);
6154 if (archive_name_size > 0xFFFF)
6155 return MZ_FALSE;
6156
6157 num_alignment_padding_bytes =
6158 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6159
6160 // no zip64 support yet
6161 if ((pZip->m_total_files == 0xFFFF) ||
6162 ((pZip->m_archive_size + num_alignment_padding_bytes +
6163 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6164 comment_size + archive_name_size) > 0xFFFFFFFF))
6165 return MZ_FALSE;
6166
6167 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
6168 // Set DOS Subdirectory attribute bit.
6169 ext_attributes |= 0x10;
6170 // Subdirectories cannot contain data.
6171 if ((buf_size) || (uncomp_size))
6172 return MZ_FALSE;
6173 }
6174
6175 // Try to do any allocations before writing to the archive, so if an
6176 // allocation fails the file remains unmodified. (A good idea if we're doing
6177 // an in-place modification.)
6178 if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir,
6179 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6180 archive_name_size + comment_size)) ||
6181 (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6182 return MZ_FALSE;
6183
6184 if ((!store_data_uncompressed) && (buf_size)) {
6185 if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
6186 pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6187 return MZ_FALSE;
6188 }
6189
6190 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6191 num_alignment_padding_bytes +
6192 sizeof(local_dir_header))) {
6193 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6194 return MZ_FALSE;
6195 }
6196 local_dir_header_ofs += num_alignment_padding_bytes;
6197 if (pZip->m_file_offset_alignment) {
6198 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6199 0);
6200 }
6201 cur_archive_file_ofs +=
6202 num_alignment_padding_bytes + sizeof(local_dir_header);
6203
6204 MZ_CLEAR_OBJ(local_dir_header);
6205 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6206 archive_name_size) != archive_name_size) {
6207 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6208 return MZ_FALSE;
6209 }
6210 cur_archive_file_ofs += archive_name_size;
6211
6212 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6213 uncomp_crc32 =
6214 (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6215 uncomp_size = buf_size;
6216 if (uncomp_size <= 3) {
6217 level = 0;
6218 store_data_uncompressed = MZ_TRUE;
6219 }
6220 }
6221
6222 if (store_data_uncompressed) {
6223 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
6224 buf_size) != buf_size) {
6225 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6226 return MZ_FALSE;
6227 }
6228
6229 cur_archive_file_ofs += buf_size;
6230 comp_size = buf_size;
6231
6232 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6233 method = MZ_DEFLATED;
6234 } else if (buf_size) {
6235 mz_zip_writer_add_state state;
6236
6237 state.m_pZip = pZip;
6238 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6239 state.m_comp_size = 0;
6240
6241 if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6242 tdefl_create_comp_flags_from_zip_params(
6243 level, -15, MZ_DEFAULT_STRATEGY)) !=
6244 TDEFL_STATUS_OKAY) ||
6245 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
6246 TDEFL_STATUS_DONE)) {
6247 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6248 return MZ_FALSE;
6249 }
6250
6251 comp_size = state.m_comp_size;
6252 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6253
6254 method = MZ_DEFLATED;
6255 }
6256
6257 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6258 pComp = NULL;
6259
6260 // no zip64 support yet
6261 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6262 return MZ_FALSE;
6263
6264 if (!mz_zip_writer_create_local_dir_header(
6265 pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6266 comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6267 return MZ_FALSE;
6268
6269 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6270 sizeof(local_dir_header)) != sizeof(local_dir_header))
6271 return MZ_FALSE;
6272
6273 if (!mz_zip_writer_add_to_central_dir(
6274 pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6275 comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6276 dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6277 return MZ_FALSE;
6278
6279 pZip->m_total_files++;
6280 pZip->m_archive_size = cur_archive_file_ofs;
6281
6282 return MZ_TRUE;
6283 }
6284
6285 #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,mz_uint32 ext_attributes)6286 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
6287 const char *pSrc_filename, const void *pComment,
6288 mz_uint16 comment_size, mz_uint level_and_flags,
6289 mz_uint32 ext_attributes) {
6290 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6291 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6292 time_t file_modified_time;
6293 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
6294 comp_size = 0;
6295 size_t archive_name_size;
6296 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6297 MZ_FILE *pSrc_file = NULL;
6298
6299 if ((int)level_and_flags < 0)
6300 level_and_flags = MZ_DEFAULT_LEVEL;
6301 level = level_and_flags & 0xF;
6302
6303 if ((!pZip) || (!pZip->m_pState) ||
6304 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
6305 ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6306 return MZ_FALSE;
6307
6308 local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6309
6310 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6311 return MZ_FALSE;
6312 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6313 return MZ_FALSE;
6314
6315 archive_name_size = strlen(pArchive_name);
6316 if (archive_name_size > 0xFFFF)
6317 return MZ_FALSE;
6318
6319 num_alignment_padding_bytes =
6320 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6321
6322 // no zip64 support yet
6323 if ((pZip->m_total_files == 0xFFFF) ||
6324 ((pZip->m_archive_size + num_alignment_padding_bytes +
6325 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6326 comment_size + archive_name_size) > 0xFFFFFFFF))
6327 return MZ_FALSE;
6328
6329 memset(&file_modified_time, 0, sizeof(file_modified_time));
6330 if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6331 return MZ_FALSE;
6332 mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
6333
6334 pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6335 if (!pSrc_file)
6336 return MZ_FALSE;
6337 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6338 uncomp_size = MZ_FTELL64(pSrc_file);
6339 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6340
6341 if (uncomp_size > 0xFFFFFFFF) {
6342 // No zip64 support yet
6343 MZ_FCLOSE(pSrc_file);
6344 return MZ_FALSE;
6345 }
6346 if (uncomp_size <= 3)
6347 level = 0;
6348
6349 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6350 num_alignment_padding_bytes +
6351 sizeof(local_dir_header))) {
6352 MZ_FCLOSE(pSrc_file);
6353 return MZ_FALSE;
6354 }
6355 local_dir_header_ofs += num_alignment_padding_bytes;
6356 if (pZip->m_file_offset_alignment) {
6357 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6358 0);
6359 }
6360 cur_archive_file_ofs +=
6361 num_alignment_padding_bytes + sizeof(local_dir_header);
6362
6363 MZ_CLEAR_OBJ(local_dir_header);
6364 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6365 archive_name_size) != archive_name_size) {
6366 MZ_FCLOSE(pSrc_file);
6367 return MZ_FALSE;
6368 }
6369 cur_archive_file_ofs += archive_name_size;
6370
6371 if (uncomp_size) {
6372 mz_uint64 uncomp_remaining = uncomp_size;
6373 void *pRead_buf =
6374 pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6375 if (!pRead_buf) {
6376 MZ_FCLOSE(pSrc_file);
6377 return MZ_FALSE;
6378 }
6379
6380 if (!level) {
6381 while (uncomp_remaining) {
6382 mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6383 if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) ||
6384 (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
6385 n) != n)) {
6386 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6387 MZ_FCLOSE(pSrc_file);
6388 return MZ_FALSE;
6389 }
6390 uncomp_crc32 =
6391 (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6392 uncomp_remaining -= n;
6393 cur_archive_file_ofs += n;
6394 }
6395 comp_size = uncomp_size;
6396 } else {
6397 mz_bool result = MZ_FALSE;
6398 mz_zip_writer_add_state state;
6399 tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
6400 pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6401 if (!pComp) {
6402 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6403 MZ_FCLOSE(pSrc_file);
6404 return MZ_FALSE;
6405 }
6406
6407 state.m_pZip = pZip;
6408 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6409 state.m_comp_size = 0;
6410
6411 if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6412 tdefl_create_comp_flags_from_zip_params(
6413 level, -15, MZ_DEFAULT_STRATEGY)) !=
6414 TDEFL_STATUS_OKAY) {
6415 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6416 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6417 MZ_FCLOSE(pSrc_file);
6418 return MZ_FALSE;
6419 }
6420
6421 for (;;) {
6422 size_t in_buf_size =
6423 (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
6424 tdefl_status status;
6425
6426 if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6427 break;
6428
6429 uncomp_crc32 = (mz_uint32)mz_crc32(
6430 uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6431 uncomp_remaining -= in_buf_size;
6432
6433 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size,
6434 uncomp_remaining ? TDEFL_NO_FLUSH
6435 : TDEFL_FINISH);
6436 if (status == TDEFL_STATUS_DONE) {
6437 result = MZ_TRUE;
6438 break;
6439 } else if (status != TDEFL_STATUS_OKAY)
6440 break;
6441 }
6442
6443 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6444
6445 if (!result) {
6446 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6447 MZ_FCLOSE(pSrc_file);
6448 return MZ_FALSE;
6449 }
6450
6451 comp_size = state.m_comp_size;
6452 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6453
6454 method = MZ_DEFLATED;
6455 }
6456
6457 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6458 }
6459
6460 MZ_FCLOSE(pSrc_file);
6461 pSrc_file = NULL;
6462
6463 // no zip64 support yet
6464 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6465 return MZ_FALSE;
6466
6467 if (!mz_zip_writer_create_local_dir_header(
6468 pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6469 comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6470 return MZ_FALSE;
6471
6472 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6473 sizeof(local_dir_header)) != sizeof(local_dir_header))
6474 return MZ_FALSE;
6475
6476 if (!mz_zip_writer_add_to_central_dir(
6477 pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6478 comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6479 dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6480 return MZ_FALSE;
6481
6482 pZip->m_total_files++;
6483 pZip->m_archive_size = cur_archive_file_ofs;
6484
6485 return MZ_TRUE;
6486 }
6487 #endif // #ifndef MINIZ_NO_STDIO
6488
mz_zip_writer_add_from_zip_reader(mz_zip_archive * pZip,mz_zip_archive * pSource_zip,mz_uint file_index)6489 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
6490 mz_zip_archive *pSource_zip,
6491 mz_uint file_index) {
6492 mz_uint n, bit_flags, num_alignment_padding_bytes;
6493 mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
6494 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6495 mz_uint32
6496 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6497 sizeof(mz_uint32)];
6498 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6499 mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6500 size_t orig_central_dir_size;
6501 mz_zip_internal_state *pState;
6502 void *pBuf;
6503 const mz_uint8 *pSrc_central_header;
6504
6505 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6506 return MZ_FALSE;
6507 if (NULL ==
6508 (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
6509 return MZ_FALSE;
6510 pState = pZip->m_pState;
6511
6512 num_alignment_padding_bytes =
6513 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6514
6515 // no zip64 support yet
6516 if ((pZip->m_total_files == 0xFFFF) ||
6517 ((pZip->m_archive_size + num_alignment_padding_bytes +
6518 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) >
6519 0xFFFFFFFF))
6520 return MZ_FALSE;
6521
6522 cur_src_file_ofs =
6523 MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6524 cur_dst_file_ofs = pZip->m_archive_size;
6525
6526 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
6527 pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6528 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6529 return MZ_FALSE;
6530 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6531 return MZ_FALSE;
6532 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6533
6534 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
6535 num_alignment_padding_bytes))
6536 return MZ_FALSE;
6537 cur_dst_file_ofs += num_alignment_padding_bytes;
6538 local_dir_header_ofs = cur_dst_file_ofs;
6539 if (pZip->m_file_offset_alignment) {
6540 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6541 0);
6542 }
6543
6544 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
6545 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6546 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6547 return MZ_FALSE;
6548 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6549
6550 n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6551 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6552 comp_bytes_remaining =
6553 n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6554
6555 if (NULL ==
6556 (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6557 (size_t)MZ_MAX(sizeof(mz_uint32) * 4,
6558 MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE,
6559 comp_bytes_remaining)))))
6560 return MZ_FALSE;
6561
6562 while (comp_bytes_remaining) {
6563 n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
6564 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6565 n) != n) {
6566 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6567 return MZ_FALSE;
6568 }
6569 cur_src_file_ofs += n;
6570
6571 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6572 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6573 return MZ_FALSE;
6574 }
6575 cur_dst_file_ofs += n;
6576
6577 comp_bytes_remaining -= n;
6578 }
6579
6580 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6581 if (bit_flags & 8) {
6582 // Copy data descriptor
6583 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6584 sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) {
6585 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6586 return MZ_FALSE;
6587 }
6588
6589 n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
6590 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6591 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6592 return MZ_FALSE;
6593 }
6594
6595 // cur_src_file_ofs += n;
6596 cur_dst_file_ofs += n;
6597 }
6598 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6599
6600 // no zip64 support yet
6601 if (cur_dst_file_ofs > 0xFFFFFFFF)
6602 return MZ_FALSE;
6603
6604 orig_central_dir_size = pState->m_central_dir.m_size;
6605
6606 memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6607 MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
6608 local_dir_header_ofs);
6609 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header,
6610 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6611 return MZ_FALSE;
6612
6613 n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6614 MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
6615 MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6616 if (!mz_zip_array_push_back(
6617 pZip, &pState->m_central_dir,
6618 pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) {
6619 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6620 MZ_FALSE);
6621 return MZ_FALSE;
6622 }
6623
6624 if (pState->m_central_dir.m_size > 0xFFFFFFFF)
6625 return MZ_FALSE;
6626 n = (mz_uint32)orig_central_dir_size;
6627 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
6628 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6629 MZ_FALSE);
6630 return MZ_FALSE;
6631 }
6632
6633 pZip->m_total_files++;
6634 pZip->m_archive_size = cur_dst_file_ofs;
6635
6636 return MZ_TRUE;
6637 }
6638
mz_zip_writer_finalize_archive(mz_zip_archive * pZip)6639 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
6640 mz_zip_internal_state *pState;
6641 mz_uint64 central_dir_ofs, central_dir_size;
6642 mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
6643
6644 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6645 return MZ_FALSE;
6646
6647 pState = pZip->m_pState;
6648
6649 // no zip64 support yet
6650 if ((pZip->m_total_files > 0xFFFF) ||
6651 ((pZip->m_archive_size + pState->m_central_dir.m_size +
6652 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6653 return MZ_FALSE;
6654
6655 central_dir_ofs = 0;
6656 central_dir_size = 0;
6657 if (pZip->m_total_files) {
6658 // Write central directory
6659 central_dir_ofs = pZip->m_archive_size;
6660 central_dir_size = pState->m_central_dir.m_size;
6661 pZip->m_central_directory_file_ofs = central_dir_ofs;
6662 if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
6663 pState->m_central_dir.m_p,
6664 (size_t)central_dir_size) != central_dir_size)
6665 return MZ_FALSE;
6666 pZip->m_archive_size += central_dir_size;
6667 }
6668
6669 // Write end of central directory record
6670 MZ_CLEAR_OBJ(hdr);
6671 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
6672 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
6673 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
6674 pZip->m_total_files);
6675 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
6676 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
6677 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6678
6679 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
6680 sizeof(hdr)) != sizeof(hdr))
6681 return MZ_FALSE;
6682 #ifndef MINIZ_NO_STDIO
6683 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
6684 return MZ_FALSE;
6685 #endif // #ifndef MINIZ_NO_STDIO
6686
6687 pZip->m_archive_size += sizeof(hdr);
6688
6689 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
6690 return MZ_TRUE;
6691 }
6692
mz_zip_writer_finalize_heap_archive(mz_zip_archive * pZip,void ** pBuf,size_t * pSize)6693 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
6694 size_t *pSize) {
6695 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
6696 return MZ_FALSE;
6697 if (pZip->m_pWrite != mz_zip_heap_write_func)
6698 return MZ_FALSE;
6699 if (!mz_zip_writer_finalize_archive(pZip))
6700 return MZ_FALSE;
6701
6702 *pBuf = pZip->m_pState->m_pMem;
6703 *pSize = pZip->m_pState->m_mem_size;
6704 pZip->m_pState->m_pMem = NULL;
6705 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6706 return MZ_TRUE;
6707 }
6708
mz_zip_writer_end(mz_zip_archive * pZip)6709 mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
6710 mz_zip_internal_state *pState;
6711 mz_bool status = MZ_TRUE;
6712 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
6713 ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
6714 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
6715 return MZ_FALSE;
6716
6717 pState = pZip->m_pState;
6718 pZip->m_pState = NULL;
6719 mz_zip_array_clear(pZip, &pState->m_central_dir);
6720 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
6721 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
6722
6723 #ifndef MINIZ_NO_STDIO
6724 if (pState->m_pFile) {
6725 MZ_FCLOSE(pState->m_pFile);
6726 pState->m_pFile = NULL;
6727 }
6728 #endif // #ifndef MINIZ_NO_STDIO
6729
6730 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
6731 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
6732 pState->m_pMem = NULL;
6733 }
6734
6735 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6736 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
6737 return status;
6738 }
6739
6740 #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)6741 mz_bool mz_zip_add_mem_to_archive_file_in_place(
6742 const char *pZip_filename, const char *pArchive_name, const void *pBuf,
6743 size_t buf_size, const void *pComment, mz_uint16 comment_size,
6744 mz_uint level_and_flags) {
6745 mz_bool status, created_new_archive = MZ_FALSE;
6746 mz_zip_archive zip_archive;
6747 struct MZ_FILE_STAT_STRUCT file_stat;
6748 MZ_CLEAR_OBJ(zip_archive);
6749 if ((int)level_and_flags < 0)
6750 level_and_flags = MZ_DEFAULT_LEVEL;
6751 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
6752 ((comment_size) && (!pComment)) ||
6753 ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6754 return MZ_FALSE;
6755 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6756 return MZ_FALSE;
6757 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
6758 // Create a new archive.
6759 if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
6760 return MZ_FALSE;
6761 created_new_archive = MZ_TRUE;
6762 } else {
6763 // Append to an existing archive.
6764 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6765 level_and_flags |
6766 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6767 return MZ_FALSE;
6768 if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) {
6769 mz_zip_reader_end(&zip_archive);
6770 return MZ_FALSE;
6771 }
6772 }
6773 status =
6774 mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
6775 pComment, comment_size, level_and_flags, 0, 0);
6776 // Always finalize, even if adding failed for some reason, so we have a valid
6777 // central directory. (This may not always succeed, but we can try.)
6778 if (!mz_zip_writer_finalize_archive(&zip_archive))
6779 status = MZ_FALSE;
6780 if (!mz_zip_writer_end(&zip_archive))
6781 status = MZ_FALSE;
6782 if ((!status) && (created_new_archive)) {
6783 // It's a new archive and something went wrong, so just delete it.
6784 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6785 (void)ignoredStatus;
6786 }
6787 return status;
6788 }
6789
mz_zip_extract_archive_file_to_heap(const char * pZip_filename,const char * pArchive_name,size_t * pSize,mz_uint flags)6790 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
6791 const char *pArchive_name,
6792 size_t *pSize, mz_uint flags) {
6793 int file_index;
6794 mz_zip_archive zip_archive;
6795 void *p = NULL;
6796
6797 if (pSize)
6798 *pSize = 0;
6799
6800 if ((!pZip_filename) || (!pArchive_name))
6801 return NULL;
6802
6803 MZ_CLEAR_OBJ(zip_archive);
6804 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6805 flags |
6806 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6807 return NULL;
6808
6809 if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL,
6810 flags)) >= 0)
6811 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6812
6813 mz_zip_reader_end(&zip_archive);
6814 return p;
6815 }
6816
6817 #endif // #ifndef MINIZ_NO_STDIO
6818
6819 #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
6820
6821 #endif // #ifndef MINIZ_NO_ARCHIVE_APIS
6822
6823 #ifdef __cplusplus
6824 }
6825 #endif
6826
6827 #endif // MINIZ_HEADER_FILE_ONLY
6828
6829 /*
6830 This is free and unencumbered software released into the public domain.
6831
6832 Anyone is free to copy, modify, publish, use, compile, sell, or
6833 distribute this software, either in source code form or as a compiled
6834 binary, for any purpose, commercial or non-commercial, and by any
6835 means.
6836
6837 In jurisdictions that recognize copyright laws, the author or authors
6838 of this software dedicate any and all copyright interest in the
6839 software to the public domain. We make this dedication for the benefit
6840 of the public at large and to the detriment of our heirs and
6841 successors. We intend this dedication to be an overt act of
6842 relinquishment in perpetuity of all present and future rights to this
6843 software under copyright law.
6844
6845 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6846 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6847 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6848 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6849 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6850 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6851 OTHER DEALINGS IN THE SOFTWARE.
6852
6853 For more information, please refer to <http://unlicense.org/>
6854 */
6855