CSEngine
Loading...
Searching...
No Matches
miniz.h
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
326extern "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!
333typedef 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.
338void 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.
343mz_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.
348mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
349
350// Compression strategies.
351enum {
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. */
361typedef 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 purposely differ from zlib's:
404// items/size is size_t, not unsigned long.
405typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
406typedef void (*mz_free_func)(void *opaque, void *address);
407typedef 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).
419enum {
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.
429enum {
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.
445enum {
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
457struct mz_internal_state;
458
459// Compression/decompression stream struct.
460typedef 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
482typedef mz_stream *mz_streamp;
483
484// Returns the version string of miniz.c.
485const 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.
500int 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)
509int 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().
514int 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.)
531int 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.
537int 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.
542mz_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.
547int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
548 const unsigned char *pSource, mz_ulong source_len);
549int 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().
554mz_ulong mz_compressBound(mz_ulong source_len);
555
556// Initializes a decompressor.
557int 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).
563int 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).
588int mz_inflate(mz_streamp pStream, int flush);
589
590// Deinitializes a decompressor.
591int 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.
596int 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.
601const 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
608typedef unsigned char Byte;
609typedef unsigned int uInt;
610typedef mz_ulong uLong;
611typedef Byte Bytef;
612typedef uInt uIntf;
613typedef char charf;
614typedef int intf;
615typedef void *voidpf;
616typedef uLong uLongf;
617typedef void *voidp;
618typedef 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
684typedef unsigned char mz_uint8;
685typedef signed short mz_int16;
686typedef unsigned short mz_uint16;
687typedef unsigned int mz_uint32;
688typedef unsigned int mz_uint;
689typedef long long mz_int64;
690typedef unsigned long long mz_uint64;
691typedef 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
708enum {
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
714typedef 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];
734
735typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
736 void *pBuf, size_t n);
737typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
738 const void *pBuf, size_t n);
739typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
740
743
744typedef 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
751typedef 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
761typedef 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
786
787typedef 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.
798mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
799 mz_uint32 flags);
800mz_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
804mz_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.
809mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
810
811// Returns detailed information about an archive file entry.
812mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
814
815// Determines if an archive file entry is a directory entry.
816mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
817 mz_uint file_index);
818mz_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.
825mz_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.
831int 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.
835mz_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);
840mz_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.
845mz_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);
848mz_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.
853void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
854 size_t *pSize, mz_uint flags);
855void *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.
860mz_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);
864mz_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.
873mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
874 const char *pDst_filename, mz_uint flags);
875mz_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.
883mz_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.
890mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
891mz_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
896mz_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.
912mz_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.
921mz_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);
924mz_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.
936mz_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.
945mz_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.
953mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
954mz_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.
960mz_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.
968mz_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.
975void *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.
996enum {
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.
1013void *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))
1020size_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.
1027typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
1028int 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
1034
1035// Max size of LZ dictionary.
1036#define TINFL_LZ_DICT_SIZE 32768
1037
1038// Return status.
1039typedef 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.
1062tinfl_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.
1069enum {
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
1078typedef 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];
1083
1084#if MINIZ_HAS_64BIT_REGISTERS
1085#define TINFL_USE_64BIT_BITBUF 1
1086#endif
1087
1088#if TINFL_USE_64BIT_BITBUF
1089typedef mz_uint64 tinfl_bit_buf_t;
1090#define TINFL_BITBUF_SIZE (64)
1091#else
1092typedef mz_uint32 tinfl_bit_buf_t;
1093#define TINFL_BITBUF_SIZE (32)
1094#endif
1095
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).
1118enum {
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).
1138enum {
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.
1160void *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.
1165size_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.
1182void *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);
1186void *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.
1191typedef 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.
1196mz_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
1200enum {
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
1214enum {
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
1224enum {
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.
1238typedef 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
1246typedef 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.
1254typedef 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];
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.)
1290tdefl_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.
1297tdefl_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.
1304tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
1305 size_t in_buf_size, tdefl_flush flush);
1306
1307tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
1308mz_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
1318mz_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
1336typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1337typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1338typedef 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
1387extern "C" {
1388#endif
1389
1390// ------------------- zlib-style API's
1391
1392mz_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/
1420mz_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
1437void mz_free(void *p) { MZ_FREE(p); }
1438
1439#ifndef MINIZ_NO_ZLIB_APIS
1440
1441static 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}
1445static void def_free_func(void *opaque, void *address) {
1446 (void)opaque, (void)address;
1447 MZ_FREE(address);
1448}
1449static 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
1455const char *mz_version(void) { return MZ_VERSION; }
1456
1457int 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
1462int 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
1502int 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
1512int 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
1567int 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
1577mz_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
1585int 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
1614int 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
1620mz_ulong mz_compressBound(mz_ulong source_len) {
1621 return mz_deflateBound(NULL, source_len);
1622}
1623
1624typedef 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;
1631
1632int 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
1669int mz_inflateInit(mz_streamp pStream) {
1670 return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
1671}
1672
1673int 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
1796int 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
1806int 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
1836const 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
2000tinfl_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 rev_code >>= 1;
2198 tree_cur -= (rev_code & 1);
2199 pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2200 }
2201 if (r->m_type == 2) {
2202 for (counter = 0;
2203 counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) {
2204 mz_uint s;
2205 TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2206 if (dist < 16) {
2207 r->m_len_codes[counter++] = (mz_uint8)dist;
2208 continue;
2209 }
2210 if ((dist == 16) && (!counter)) {
2211 TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2212 }
2213 num_extra = "\02\03\07"[dist - 16];
2214 TINFL_GET_BITS(18, s, num_extra);
2215 s += "\03\03\013"[dist - 16];
2216 TINFL_MEMSET(r->m_len_codes + counter,
2217 (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2218 counter += s;
2219 }
2220 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) {
2221 TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2222 }
2223 TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes,
2224 r->m_table_sizes[0]);
2225 TINFL_MEMCPY(r->m_tables[1].m_code_size,
2226 r->m_len_codes + r->m_table_sizes[0],
2227 r->m_table_sizes[1]);
2228 }
2229 }
2230 for (;;) {
2231 mz_uint8 *pSrc;
2232 for (;;) {
2233 if (((pIn_buf_end - pIn_buf_cur) < 4) ||
2234 ((pOut_buf_end - pOut_buf_cur) < 2)) {
2235 TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2236 if (counter >= 256)
2237 break;
2238 while (pOut_buf_cur >= pOut_buf_end) {
2239 TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2240 }
2241 *pOut_buf_cur++ = (mz_uint8)counter;
2242 } else {
2243 int sym2;
2244 mz_uint code_len;
2245#if TINFL_USE_64BIT_BITBUF
2246 if (num_bits < 30) {
2247 bit_buf |=
2248 (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2249 pIn_buf_cur += 4;
2250 num_bits += 32;
2251 }
2252#else
2253 if (num_bits < 15) {
2254 bit_buf |=
2255 (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2256 pIn_buf_cur += 2;
2257 num_bits += 16;
2258 }
2259#endif
2260 if ((sym2 =
2261 r->m_tables[0]
2262 .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2263 0)
2264 code_len = sym2 >> 9;
2265 else {
2266 code_len = TINFL_FAST_LOOKUP_BITS;
2267 do {
2268 sym2 = r->m_tables[0]
2269 .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2270 } while (sym2 < 0);
2271 }
2272 counter = sym2;
2273 bit_buf >>= code_len;
2274 num_bits -= code_len;
2275 if (counter & 256)
2276 break;
2277
2278#if !TINFL_USE_64BIT_BITBUF
2279 if (num_bits < 15) {
2280 bit_buf |=
2281 (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2282 pIn_buf_cur += 2;
2283 num_bits += 16;
2284 }
2285#endif
2286 if ((sym2 =
2287 r->m_tables[0]
2288 .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
2289 0)
2290 code_len = sym2 >> 9;
2291 else {
2292 code_len = TINFL_FAST_LOOKUP_BITS;
2293 do {
2294 sym2 = r->m_tables[0]
2295 .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2296 } while (sym2 < 0);
2297 }
2298 bit_buf >>= code_len;
2299 num_bits -= code_len;
2300
2301 pOut_buf_cur[0] = (mz_uint8)counter;
2302 if (sym2 & 256) {
2303 pOut_buf_cur++;
2304 counter = sym2;
2305 break;
2306 }
2307 pOut_buf_cur[1] = (mz_uint8)sym2;
2308 pOut_buf_cur += 2;
2309 }
2310 }
2311 if ((counter &= 511) == 256)
2312 break;
2313
2314 num_extra = s_length_extra[counter - 257];
2315 counter = s_length_base[counter - 257];
2316 if (num_extra) {
2317 mz_uint extra_bits;
2318 TINFL_GET_BITS(25, extra_bits, num_extra);
2319 counter += extra_bits;
2320 }
2321
2322 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2323 num_extra = s_dist_extra[dist];
2324 dist = s_dist_base[dist];
2325 if (num_extra) {
2326 mz_uint extra_bits;
2327 TINFL_GET_BITS(27, extra_bits, num_extra);
2328 dist += extra_bits;
2329 }
2330
2331 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2332 if ((dist > dist_from_out_buf_start) &&
2333 (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) {
2334 TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2335 }
2336
2337 pSrc = pOut_buf_start +
2338 ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2339
2340 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
2341 while (counter--) {
2342 while (pOut_buf_cur >= pOut_buf_end) {
2343 TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2344 }
2345 *pOut_buf_cur++ =
2346 pOut_buf_start[(dist_from_out_buf_start++ - dist) &
2347 out_buf_size_mask];
2348 }
2349 continue;
2350 }
2351#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2352 else if ((counter >= 9) && (counter <= dist)) {
2353 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2354 do {
2355 ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2356 ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2357 pOut_buf_cur += 8;
2358 } while ((pSrc += 8) < pSrc_end);
2359 if ((counter &= 7) < 3) {
2360 if (counter) {
2361 pOut_buf_cur[0] = pSrc[0];
2362 if (counter > 1)
2363 pOut_buf_cur[1] = pSrc[1];
2364 pOut_buf_cur += counter;
2365 }
2366 continue;
2367 }
2368 }
2369#endif
2370 do {
2371 pOut_buf_cur[0] = pSrc[0];
2372 pOut_buf_cur[1] = pSrc[1];
2373 pOut_buf_cur[2] = pSrc[2];
2374 pOut_buf_cur += 3;
2375 pSrc += 3;
2376 } while ((int)(counter -= 3) > 2);
2377 if ((int)counter > 0) {
2378 pOut_buf_cur[0] = pSrc[0];
2379 if ((int)counter > 1)
2380 pOut_buf_cur[1] = pSrc[1];
2381 pOut_buf_cur += counter;
2382 }
2383 }
2384 }
2385 } while (!(r->m_final & 1));
2386 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
2387 TINFL_SKIP_BITS(32, num_bits & 7);
2388 for (counter = 0; counter < 4; ++counter) {
2389 mz_uint s;
2390 if (num_bits)
2391 TINFL_GET_BITS(41, s, 8);
2392 else
2393 TINFL_GET_BYTE(42, s);
2394 r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2395 }
2396 }
2397 TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2398 TINFL_CR_FINISH
2399
2400common_exit:
2401 r->m_num_bits = num_bits;
2402 r->m_bit_buf = bit_buf;
2403 r->m_dist = dist;
2404 r->m_counter = counter;
2405 r->m_num_extra = num_extra;
2406 r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2407 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2408 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2409 if ((decomp_flags &
2410 (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) &&
2411 (status >= 0)) {
2412 const mz_uint8 *ptr = pOut_buf_next;
2413 size_t buf_len = *pOut_buf_size;
2414 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff,
2415 s2 = r->m_check_adler32 >> 16;
2416 size_t block_len = buf_len % 5552;
2417 while (buf_len) {
2418 for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
2419 s1 += ptr[0], s2 += s1;
2420 s1 += ptr[1], s2 += s1;
2421 s1 += ptr[2], s2 += s1;
2422 s1 += ptr[3], s2 += s1;
2423 s1 += ptr[4], s2 += s1;
2424 s1 += ptr[5], s2 += s1;
2425 s1 += ptr[6], s2 += s1;
2426 s1 += ptr[7], s2 += s1;
2427 }
2428 for (; i < block_len; ++i)
2429 s1 += *ptr++, s2 += s1;
2430 s1 %= 65521U, s2 %= 65521U;
2431 buf_len -= block_len;
2432 block_len = 5552;
2433 }
2434 r->m_check_adler32 = (s2 << 16) + s1;
2435 if ((status == TINFL_STATUS_DONE) &&
2436 (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) &&
2437 (r->m_check_adler32 != r->m_z_adler32))
2438 status = TINFL_STATUS_ADLER32_MISMATCH;
2439 }
2440 return status;
2441}
2442
2443// Higher level helper functions.
2444void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
2445 size_t *pOut_len, int flags) {
2446 tinfl_decompressor decomp;
2447 void *pBuf = NULL, *pNew_buf;
2448 size_t src_buf_ofs = 0, out_buf_capacity = 0;
2449 *pOut_len = 0;
2450 tinfl_init(&decomp);
2451 for (;;) {
2452 size_t src_buf_size = src_buf_len - src_buf_ofs,
2453 dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2454 tinfl_status status = tinfl_decompress(
2455 &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
2456 (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
2457 &dst_buf_size,
2458 (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2459 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2460 if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
2461 MZ_FREE(pBuf);
2462 *pOut_len = 0;
2463 return NULL;
2464 }
2465 src_buf_ofs += src_buf_size;
2466 *pOut_len += dst_buf_size;
2467 if (status == TINFL_STATUS_DONE)
2468 break;
2469 new_out_buf_capacity = out_buf_capacity * 2;
2470 if (new_out_buf_capacity < 128)
2471 new_out_buf_capacity = 128;
2472 pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2473 if (!pNew_buf) {
2474 MZ_FREE(pBuf);
2475 *pOut_len = 0;
2476 return NULL;
2477 }
2478 pBuf = pNew_buf;
2479 out_buf_capacity = new_out_buf_capacity;
2480 }
2481 return pBuf;
2482}
2483
2484size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
2485 const void *pSrc_buf, size_t src_buf_len,
2486 int flags) {
2487 tinfl_decompressor decomp;
2488 tinfl_status status;
2489 tinfl_init(&decomp);
2490 status =
2491 tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len,
2492 (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
2493 (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
2494 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2495 return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
2496 : out_buf_len;
2497}
2498
2499int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
2500 tinfl_put_buf_func_ptr pPut_buf_func,
2501 void *pPut_buf_user, int flags) {
2502 int result = 0;
2503 tinfl_decompressor decomp;
2504 mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2505 size_t in_buf_ofs = 0, dict_ofs = 0;
2506 if (!pDict)
2507 return TINFL_STATUS_FAILED;
2508 tinfl_init(&decomp);
2509 for (;;) {
2510 size_t in_buf_size = *pIn_buf_size - in_buf_ofs,
2511 dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2512 tinfl_status status =
2513 tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
2514 &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2515 (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
2516 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2517 in_buf_ofs += in_buf_size;
2518 if ((dst_buf_size) &&
2519 (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2520 break;
2521 if (status != TINFL_STATUS_HAS_MORE_OUTPUT) {
2522 result = (status == TINFL_STATUS_DONE);
2523 break;
2524 }
2525 dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2526 }
2527 MZ_FREE(pDict);
2528 *pIn_buf_size = in_buf_ofs;
2529 return result;
2530}
2531
2532// ------------------- Low-level Compression (independent from all decompression
2533// API's)
2534
2535// Purposely making these tables static for faster init and thread safety.
2536static const mz_uint16 s_tdefl_len_sym[256] = {
2537 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268,
2538 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272,
2539 272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274,
2540 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276,
2541 276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
2542 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
2543 278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279,
2544 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
2545 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281,
2546 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
2547 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282,
2548 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
2549 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283,
2550 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
2551 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
2552 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2553 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2554 285};
2555
2556static const mz_uint8 s_tdefl_len_extra[256] = {
2557 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2558 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2559 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 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, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2562 4, 4, 4, 4, 4, 4, 4, 4, 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, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2567 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0};
2568
2569static const mz_uint8 s_tdefl_small_dist_sym[512] = {
2570 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8,
2571 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
2572 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
2573 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2574 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2575 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2576 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2580 14, 14, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2583 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2590 16, 16, 16, 16, 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, 17,
2596 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17};
2597
2598static const mz_uint8 s_tdefl_small_dist_extra[512] = {
2599 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,
2600 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,
2601 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,
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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2604 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,
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, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2609 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,
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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2619 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
2620
2621static const mz_uint8 s_tdefl_large_dist_sym[128] = {
2622 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24,
2623 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
2624 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
2625 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2626 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2627 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2628 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
2629
2630static const mz_uint8 s_tdefl_large_dist_extra[128] = {
2631 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
2632 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
2633 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2634 12, 12, 12, 12, 12, 12, 12, 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, 13, 13, 13, 13, 13,
2637 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
2638
2639// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
2640// values.
2641typedef struct {
2642 mz_uint16 m_key, m_sym_index;
2644static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
2645 tdefl_sym_freq *pSyms0,
2646 tdefl_sym_freq *pSyms1) {
2647 mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
2648 tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
2649 MZ_CLEAR_OBJ(hist);
2650 for (i = 0; i < num_syms; i++) {
2651 mz_uint freq = pSyms0[i].m_key;
2652 hist[freq & 0xFF]++;
2653 hist[256 + ((freq >> 8) & 0xFF)]++;
2654 }
2655 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
2656 total_passes--;
2657 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
2658 const mz_uint32 *pHist = &hist[pass << 8];
2659 mz_uint offsets[256], cur_ofs = 0;
2660 for (i = 0; i < 256; i++) {
2661 offsets[i] = cur_ofs;
2662 cur_ofs += pHist[i];
2663 }
2664 for (i = 0; i < num_syms; i++)
2665 pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] =
2666 pCur_syms[i];
2667 {
2668 tdefl_sym_freq *t = pCur_syms;
2669 pCur_syms = pNew_syms;
2670 pNew_syms = t;
2671 }
2672 }
2673 return pCur_syms;
2674}
2675
2676// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat,
2677// alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
2678static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
2679 int root, leaf, next, avbl, used, dpth;
2680 if (n == 0)
2681 return;
2682 else if (n == 1) {
2683 A[0].m_key = 1;
2684 return;
2685 }
2686 A[0].m_key += A[1].m_key;
2687 root = 0;
2688 leaf = 2;
2689 for (next = 1; next < n - 1; next++) {
2690 if (leaf >= n || A[root].m_key < A[leaf].m_key) {
2691 A[next].m_key = A[root].m_key;
2692 A[root++].m_key = (mz_uint16)next;
2693 } else
2694 A[next].m_key = A[leaf++].m_key;
2695 if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) {
2696 A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
2697 A[root++].m_key = (mz_uint16)next;
2698 } else
2699 A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
2700 }
2701 A[n - 2].m_key = 0;
2702 for (next = n - 3; next >= 0; next--)
2703 A[next].m_key = A[A[next].m_key].m_key + 1;
2704 avbl = 1;
2705 used = dpth = 0;
2706 root = n - 2;
2707 next = n - 1;
2708 while (avbl > 0) {
2709 while (root >= 0 && (int)A[root].m_key == dpth) {
2710 used++;
2711 root--;
2712 }
2713 while (avbl > used) {
2714 A[next--].m_key = (mz_uint16)(dpth);
2715 avbl--;
2716 }
2717 avbl = 2 * used;
2718 dpth++;
2719 used = 0;
2720 }
2721}
2722
2723// Limits canonical Huffman code table's max code size.
2724enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
2725static void tdefl_huffman_enforce_max_code_size(int *pNum_codes,
2726 int code_list_len,
2727 int max_code_size) {
2728 int i;
2729 mz_uint32 total = 0;
2730 if (code_list_len <= 1)
2731 return;
2732 for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
2733 pNum_codes[max_code_size] += pNum_codes[i];
2734 for (i = max_code_size; i > 0; i--)
2735 total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
2736 while (total != (1UL << max_code_size)) {
2737 pNum_codes[max_code_size]--;
2738 for (i = max_code_size - 1; i > 0; i--)
2739 if (pNum_codes[i]) {
2740 pNum_codes[i]--;
2741 pNum_codes[i + 1] += 2;
2742 break;
2743 }
2744 total--;
2745 }
2746}
2747
2748static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num,
2749 int table_len, int code_size_limit,
2750 int static_table) {
2751 int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
2752 mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
2753 MZ_CLEAR_OBJ(num_codes);
2754 if (static_table) {
2755 for (i = 0; i < table_len; i++)
2756 num_codes[d->m_huff_code_sizes[table_num][i]]++;
2757 } else {
2758 tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS],
2759 *pSyms;
2760 int num_used_syms = 0;
2761 const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
2762 for (i = 0; i < table_len; i++)
2763 if (pSym_count[i]) {
2764 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
2765 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
2766 }
2767
2768 pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
2769 tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
2770
2771 for (i = 0; i < num_used_syms; i++)
2772 num_codes[pSyms[i].m_key]++;
2773
2774 tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms,
2775 code_size_limit);
2776
2777 MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
2778 MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
2779 for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
2780 for (l = num_codes[i]; l > 0; l--)
2781 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
2782 }
2783
2784 next_code[1] = 0;
2785 for (j = 0, i = 2; i <= code_size_limit; i++)
2786 next_code[i] = j = ((j + num_codes[i - 1]) << 1);
2787
2788 for (i = 0; i < table_len; i++) {
2789 mz_uint rev_code = 0, code, code_size;
2790 if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
2791 continue;
2792 code = next_code[code_size]++;
2793 for (l = code_size; l > 0; l--, code >>= 1)
2794 rev_code = (rev_code << 1) | (code & 1);
2795 d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
2796 }
2797}
2798
2799#define TDEFL_PUT_BITS(b, l) \
2800 do { \
2801 mz_uint bits = b; \
2802 mz_uint len = l; \
2803 MZ_ASSERT(bits <= ((1U << len) - 1U)); \
2804 d->m_bit_buffer |= (bits << d->m_bits_in); \
2805 d->m_bits_in += len; \
2806 while (d->m_bits_in >= 8) { \
2807 if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
2808 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
2809 d->m_bit_buffer >>= 8; \
2810 d->m_bits_in -= 8; \
2811 } \
2812 } \
2813 MZ_MACRO_END
2814
2815#define TDEFL_RLE_PREV_CODE_SIZE() \
2816 { \
2817 if (rle_repeat_count) { \
2818 if (rle_repeat_count < 3) { \
2819 d->m_huff_count[2][prev_code_size] = (mz_uint16)( \
2820 d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
2821 while (rle_repeat_count--) \
2822 packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
2823 } else { \
2824 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
2825 packed_code_sizes[num_packed_code_sizes++] = 16; \
2826 packed_code_sizes[num_packed_code_sizes++] = \
2827 (mz_uint8)(rle_repeat_count - 3); \
2828 } \
2829 rle_repeat_count = 0; \
2830 } \
2831 }
2832
2833#define TDEFL_RLE_ZERO_CODE_SIZE() \
2834 { \
2835 if (rle_z_count) { \
2836 if (rle_z_count < 3) { \
2837 d->m_huff_count[2][0] = \
2838 (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \
2839 while (rle_z_count--) \
2840 packed_code_sizes[num_packed_code_sizes++] = 0; \
2841 } else if (rle_z_count <= 10) { \
2842 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \
2843 packed_code_sizes[num_packed_code_sizes++] = 17; \
2844 packed_code_sizes[num_packed_code_sizes++] = \
2845 (mz_uint8)(rle_z_count - 3); \
2846 } else { \
2847 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \
2848 packed_code_sizes[num_packed_code_sizes++] = 18; \
2849 packed_code_sizes[num_packed_code_sizes++] = \
2850 (mz_uint8)(rle_z_count - 11); \
2851 } \
2852 rle_z_count = 0; \
2853 } \
2854 }
2855
2856static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {
2857 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2858
2859static void tdefl_start_dynamic_block(tdefl_compressor *d) {
2860 int num_lit_codes, num_dist_codes, num_bit_lengths;
2861 mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count,
2862 rle_repeat_count, packed_code_sizes_index;
2863 mz_uint8
2864 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2865 packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2866 prev_code_size = 0xFF;
2867
2868 d->m_huff_count[0][256] = 1;
2869
2870 tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
2871 tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
2872
2873 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
2874 if (d->m_huff_code_sizes[0][num_lit_codes - 1])
2875 break;
2876 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
2877 if (d->m_huff_code_sizes[1][num_dist_codes - 1])
2878 break;
2879
2880 memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0],
2881 sizeof(mz_uint8) * num_lit_codes);
2882 memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0],
2883 sizeof(mz_uint8) * num_dist_codes);
2884 total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
2885 num_packed_code_sizes = 0;
2886 rle_z_count = 0;
2887 rle_repeat_count = 0;
2888
2889 memset(&d->m_huff_count[2][0], 0,
2890 sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
2891 for (i = 0; i < total_code_sizes_to_pack; i++) {
2892 mz_uint8 code_size = code_sizes_to_pack[i];
2893 if (!code_size) {
2894 TDEFL_RLE_PREV_CODE_SIZE();
2895 if (++rle_z_count == 138) {
2896 TDEFL_RLE_ZERO_CODE_SIZE();
2897 }
2898 } else {
2899 TDEFL_RLE_ZERO_CODE_SIZE();
2900 if (code_size != prev_code_size) {
2901 TDEFL_RLE_PREV_CODE_SIZE();
2902 d->m_huff_count[2][code_size] =
2903 (mz_uint16)(d->m_huff_count[2][code_size] + 1);
2904 packed_code_sizes[num_packed_code_sizes++] = code_size;
2905 } else if (++rle_repeat_count == 6) {
2906 TDEFL_RLE_PREV_CODE_SIZE();
2907 }
2908 }
2909 prev_code_size = code_size;
2910 }
2911 if (rle_repeat_count) {
2912 TDEFL_RLE_PREV_CODE_SIZE();
2913 } else {
2914 TDEFL_RLE_ZERO_CODE_SIZE();
2915 }
2916
2917 tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
2918
2919 TDEFL_PUT_BITS(2, 2);
2920
2921 TDEFL_PUT_BITS(num_lit_codes - 257, 5);
2922 TDEFL_PUT_BITS(num_dist_codes - 1, 5);
2923
2924 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
2925 if (d->m_huff_code_sizes
2926 [2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
2927 break;
2928 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
2929 TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
2930 for (i = 0; (int)i < num_bit_lengths; i++)
2931 TDEFL_PUT_BITS(
2932 d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
2933
2934 for (packed_code_sizes_index = 0;
2935 packed_code_sizes_index < num_packed_code_sizes;) {
2936 mz_uint code = packed_code_sizes[packed_code_sizes_index++];
2937 MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
2938 TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
2939 if (code >= 16)
2940 TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
2941 "\02\03\07"[code - 16]);
2942 }
2943}
2944
2945static void tdefl_start_static_block(tdefl_compressor *d) {
2946 mz_uint i;
2947 mz_uint8 *p = &d->m_huff_code_sizes[0][0];
2948
2949 for (i = 0; i <= 143; ++i)
2950 *p++ = 8;
2951 for (; i <= 255; ++i)
2952 *p++ = 9;
2953 for (; i <= 279; ++i)
2954 *p++ = 7;
2955 for (; i <= 287; ++i)
2956 *p++ = 8;
2957
2958 memset(d->m_huff_code_sizes[1], 5, 32);
2959
2960 tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
2961 tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
2962
2963 TDEFL_PUT_BITS(1, 2);
2964}
2965
2966static const mz_uint mz_bitmasks[17] = {
2967 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
2968 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
2969
2970#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && \
2971 MINIZ_HAS_64BIT_REGISTERS
2972static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
2973 mz_uint flags;
2974 mz_uint8 *pLZ_codes;
2975 mz_uint8 *pOutput_buf = d->m_pOutput_buf;
2976 mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
2977 mz_uint64 bit_buffer = d->m_bit_buffer;
2978 mz_uint bits_in = d->m_bits_in;
2979
2980#define TDEFL_PUT_BITS_FAST(b, l) \
2981 { \
2982 bit_buffer |= (((mz_uint64)(b)) << bits_in); \
2983 bits_in += (l); \
2984 }
2985
2986 flags = 1;
2987 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end;
2988 flags >>= 1) {
2989 if (flags == 1)
2990 flags = *pLZ_codes++ | 0x100;
2991
2992 if (flags & 1) {
2993 mz_uint s0, s1, n0, n1, sym, num_extra_bits;
2994 mz_uint match_len = pLZ_codes[0],
2995 match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
2996 pLZ_codes += 3;
2997
2998 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2999 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3000 d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3001 TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3002 s_tdefl_len_extra[match_len]);
3003
3004 // This sequence coaxes MSVC into using cmov's vs. jmp's.
3005 s0 = s_tdefl_small_dist_sym[match_dist & 511];
3006 n0 = s_tdefl_small_dist_extra[match_dist & 511];
3007 s1 = s_tdefl_large_dist_sym[match_dist >> 8];
3008 n1 = s_tdefl_large_dist_extra[match_dist >> 8];
3009 sym = (match_dist < 512) ? s0 : s1;
3010 num_extra_bits = (match_dist < 512) ? n0 : n1;
3011
3012 MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
3013 TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym],
3014 d->m_huff_code_sizes[1][sym]);
3015 TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits],
3016 num_extra_bits);
3017 } else {
3018 mz_uint lit = *pLZ_codes++;
3019 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3020 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3021 d->m_huff_code_sizes[0][lit]);
3022
3023 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3024 flags >>= 1;
3025 lit = *pLZ_codes++;
3026 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3027 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3028 d->m_huff_code_sizes[0][lit]);
3029
3030 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
3031 flags >>= 1;
3032 lit = *pLZ_codes++;
3033 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3034 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
3035 d->m_huff_code_sizes[0][lit]);
3036 }
3037 }
3038 }
3039
3040 if (pOutput_buf >= d->m_pOutput_buf_end)
3041 return MZ_FALSE;
3042
3043 *(mz_uint64 *)pOutput_buf = bit_buffer;
3044 pOutput_buf += (bits_in >> 3);
3045 bit_buffer >>= (bits_in & ~7);
3046 bits_in &= 7;
3047 }
3048
3049#undef TDEFL_PUT_BITS_FAST
3050
3051 d->m_pOutput_buf = pOutput_buf;
3052 d->m_bits_in = 0;
3053 d->m_bit_buffer = 0;
3054
3055 while (bits_in) {
3056 mz_uint32 n = MZ_MIN(bits_in, 16);
3057 TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
3058 bit_buffer >>= n;
3059 bits_in -= n;
3060 }
3061
3062 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3063
3064 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3065}
3066#else
3067static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
3068 mz_uint flags;
3069 mz_uint8 *pLZ_codes;
3070
3071 flags = 1;
3072 for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf;
3073 flags >>= 1) {
3074 if (flags == 1)
3075 flags = *pLZ_codes++ | 0x100;
3076 if (flags & 1) {
3077 mz_uint sym, num_extra_bits;
3078 mz_uint match_len = pLZ_codes[0],
3079 match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
3080 pLZ_codes += 3;
3081
3082 MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3083 TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
3084 d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
3085 TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
3086 s_tdefl_len_extra[match_len]);
3087
3088 if (match_dist < 512) {
3089 sym = s_tdefl_small_dist_sym[match_dist];
3090 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
3091 } else {
3092 sym = s_tdefl_large_dist_sym[match_dist >> 8];
3093 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
3094 }
3095 TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
3096 TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
3097 } else {
3098 mz_uint lit = *pLZ_codes++;
3099 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3100 TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
3101 }
3102 }
3103
3104 TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3105
3106 return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3107}
3108#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&
3109 // MINIZ_HAS_64BIT_REGISTERS
3110
3111static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) {
3112 if (static_block)
3113 tdefl_start_static_block(d);
3114 else
3115 tdefl_start_dynamic_block(d);
3116 return tdefl_compress_lz_codes(d);
3117}
3118
3119static int tdefl_flush_block(tdefl_compressor *d, int flush) {
3120 mz_uint saved_bit_buf, saved_bits_in;
3121 mz_uint8 *pSaved_output_buf;
3122 mz_bool comp_block_succeeded = MZ_FALSE;
3123 int n, use_raw_block =
3124 ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
3125 (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
3126 mz_uint8 *pOutput_buf_start =
3127 ((d->m_pPut_buf_func == NULL) &&
3128 ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
3129 ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs)
3130 : d->m_output_buf;
3131
3132 d->m_pOutput_buf = pOutput_buf_start;
3133 d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
3134
3135 MZ_ASSERT(!d->m_output_flush_remaining);
3136 d->m_output_flush_ofs = 0;
3137 d->m_output_flush_remaining = 0;
3138
3139 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
3140 d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
3141
3142 if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) {
3143 TDEFL_PUT_BITS(0x78, 8);
3144 TDEFL_PUT_BITS(0x01, 8);
3145 }
3146
3147 TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
3148
3149 pSaved_output_buf = d->m_pOutput_buf;
3150 saved_bit_buf = d->m_bit_buffer;
3151 saved_bits_in = d->m_bits_in;
3152
3153 if (!use_raw_block)
3154 comp_block_succeeded =
3155 tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
3156 (d->m_total_lz_bytes < 48));
3157
3158 // If the block gets expanded, forget the current contents of the output
3159 // buffer and send a raw block instead.
3160 if (((use_raw_block) ||
3161 ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >=
3162 d->m_total_lz_bytes))) &&
3163 ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) {
3164 mz_uint i;
3165 d->m_pOutput_buf = pSaved_output_buf;
3166 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3167 TDEFL_PUT_BITS(0, 2);
3168 if (d->m_bits_in) {
3169 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3170 }
3171 for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) {
3172 TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
3173 }
3174 for (i = 0; i < d->m_total_lz_bytes; ++i) {
3175 TDEFL_PUT_BITS(
3176 d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK],
3177 8);
3178 }
3179 }
3180 // Check for the extremely unlikely (if not impossible) case of the compressed
3181 // block not fitting into the output buffer when using dynamic codes.
3182 else if (!comp_block_succeeded) {
3183 d->m_pOutput_buf = pSaved_output_buf;
3184 d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3185 tdefl_compress_block(d, MZ_TRUE);
3186 }
3187
3188 if (flush) {
3189 if (flush == TDEFL_FINISH) {
3190 if (d->m_bits_in) {
3191 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3192 }
3193 if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) {
3194 mz_uint i, a = d->m_adler32;
3195 for (i = 0; i < 4; i++) {
3196 TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
3197 a <<= 8;
3198 }
3199 }
3200 } else {
3201 mz_uint i, z = 0;
3202 TDEFL_PUT_BITS(0, 3);
3203 if (d->m_bits_in) {
3204 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3205 }
3206 for (i = 2; i; --i, z ^= 0xFFFF) {
3207 TDEFL_PUT_BITS(z & 0xFFFF, 16);
3208 }
3209 }
3210 }
3211
3212 MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
3213
3214 memset(&d->m_huff_count[0][0], 0,
3215 sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3216 memset(&d->m_huff_count[1][0], 0,
3217 sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3218
3219 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3220 d->m_pLZ_flags = d->m_lz_code_buf;
3221 d->m_num_flags_left = 8;
3222 d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
3223 d->m_total_lz_bytes = 0;
3224 d->m_block_index++;
3225
3226 if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) {
3227 if (d->m_pPut_buf_func) {
3228 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3229 if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
3230 return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
3231 } else if (pOutput_buf_start == d->m_output_buf) {
3232 int bytes_to_copy = (int)MZ_MIN(
3233 (size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
3234 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf,
3235 bytes_to_copy);
3236 d->m_out_buf_ofs += bytes_to_copy;
3237 if ((n -= bytes_to_copy) != 0) {
3238 d->m_output_flush_ofs = bytes_to_copy;
3239 d->m_output_flush_remaining = n;
3240 }
3241 } else {
3242 d->m_out_buf_ofs += n;
3243 }
3244 }
3245
3246 return d->m_output_flush_remaining;
3247}
3248
3249#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3250#define TDEFL_READ_UNALIGNED_WORD(p) ((p)[0] | (p)[1] << 8)
3251static MZ_FORCEINLINE void
3252tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3253 mz_uint max_match_len, mz_uint *pMatch_dist,
3254 mz_uint *pMatch_len) {
3255 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3256 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3257 probe_len;
3258 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3259 const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
3260 mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]),
3261 s01 = *s;
3262 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3263 if (max_match_len <= match_len)
3264 return;
3265 for (;;) {
3266 for (;;) {
3267 if (--num_probes_left == 0)
3268 return;
3269#define TDEFL_PROBE \
3270 next_probe_pos = d->m_next[probe_pos]; \
3271 if ((!next_probe_pos) || \
3272 ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
3273 return; \
3274 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
3275 if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
3276 break;
3277 TDEFL_PROBE;
3278 TDEFL_PROBE;
3279 TDEFL_PROBE;
3280 }
3281 if (!dist)
3282 break;
3283 q = (const mz_uint16 *)(d->m_dict + probe_pos);
3284 if (*q != s01)
3285 continue;
3286 p = s;
3287 probe_len = 32;
3288 do {
3289 } while ((*(++p) == *(++q)) && (*(++p) == *(++q)) && (*(++p) == *(++q)) &&
3290 (*(++p) == *(++q)) && (--probe_len > 0));
3291 if (!probe_len) {
3292 *pMatch_dist = dist;
3293 *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN);
3294 break;
3295 } else if ((probe_len = ((mz_uint)(p - s) * 2) +
3296 (mz_uint)(*(const mz_uint8 *)p ==
3297 *(const mz_uint8 *)q)) > match_len) {
3298 *pMatch_dist = dist;
3299 if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) ==
3300 max_match_len)
3301 break;
3302 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
3303 }
3304 }
3305}
3306#else
3307static MZ_FORCEINLINE void
3308tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3309 mz_uint max_match_len, mz_uint *pMatch_dist,
3310 mz_uint *pMatch_len) {
3311 mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3312 match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3313 probe_len;
3314 mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3315 const mz_uint8 *s = d->m_dict + pos, *p, *q;
3316 mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
3317 MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3318 if (max_match_len <= match_len)
3319 return;
3320 for (;;) {
3321 for (;;) {
3322 if (--num_probes_left == 0)
3323 return;
3324#define TDEFL_PROBE \
3325 next_probe_pos = d->m_next[probe_pos]; \
3326 if ((!next_probe_pos) || \
3327 ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
3328 return; \
3329 probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
3330 if ((d->m_dict[probe_pos + match_len] == c0) && \
3331 (d->m_dict[probe_pos + match_len - 1] == c1)) \
3332 break;
3333 TDEFL_PROBE;
3334 TDEFL_PROBE;
3335 TDEFL_PROBE;
3336 }
3337 if (!dist)
3338 break;
3339 p = s;
3340 q = d->m_dict + probe_pos;
3341 for (probe_len = 0; probe_len < max_match_len; probe_len++)
3342 if (*p++ != *q++)
3343 break;
3344 if (probe_len > match_len) {
3345 *pMatch_dist = dist;
3346 if ((*pMatch_len = match_len = probe_len) == max_match_len)
3347 return;
3348 c0 = d->m_dict[pos + match_len];
3349 c1 = d->m_dict[pos + match_len - 1];
3350 }
3351 }
3352}
3353#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3354
3355#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3356static mz_bool tdefl_compress_fast(tdefl_compressor *d) {
3357 // Faster, minimally featured LZRW1-style match+parse loop with better
3358 // register utilization. Intended for applications where raw throughput is
3359 // valued more highly than ratio.
3360 mz_uint lookahead_pos = d->m_lookahead_pos,
3361 lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size,
3362 total_lz_bytes = d->m_total_lz_bytes,
3363 num_flags_left = d->m_num_flags_left;
3364 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
3365 mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3366
3367 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
3368 const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
3369 mz_uint dst_pos =
3370 (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
3371 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3372 d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
3373 d->m_src_buf_left -= num_bytes_to_process;
3374 lookahead_size += num_bytes_to_process;
3375
3376 while (num_bytes_to_process) {
3377 mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
3378 memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
3379 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3380 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc,
3381 MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
3382 d->m_pSrc += n;
3383 dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
3384 num_bytes_to_process -= n;
3385 }
3386
3387 dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
3388 if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
3389 break;
3390
3391 while (lookahead_size >= 4) {
3392 mz_uint cur_match_dist, cur_match_len = 1;
3393 mz_uint8 *pCur_dict = d->m_dict + cur_pos;
3394 mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
3395 mz_uint hash =
3396 (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) &
3397 TDEFL_LEVEL1_HASH_SIZE_MASK;
3398 mz_uint probe_pos = d->m_hash[hash];
3399 d->m_hash[hash] = (mz_uint16)lookahead_pos;
3400
3401 if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <=
3402 dict_size) &&
3403 ((mz_uint32)(
3404 *(d->m_dict + (probe_pos & TDEFL_LZ_DICT_SIZE_MASK)) |
3405 (*(d->m_dict + ((probe_pos & TDEFL_LZ_DICT_SIZE_MASK) + 1))
3406 << 8) |
3407 (*(d->m_dict + ((probe_pos & TDEFL_LZ_DICT_SIZE_MASK) + 2))
3408 << 16)) == first_trigram)) {
3409 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
3410 const mz_uint16 *q =
3411 (const mz_uint16 *)(d->m_dict +
3412 (probe_pos & TDEFL_LZ_DICT_SIZE_MASK));
3413 mz_uint32 probe_len = 32;
3414 do {
3415 } while ((*(++p) == *(++q)) && (*(++p) == *(++q)) &&
3416 (*(++p) == *(++q)) && (*(++p) == *(++q)) && (--probe_len > 0));
3417 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) +
3418 (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
3419 if (!probe_len)
3420 cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
3421
3422 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) ||
3423 ((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3424 (cur_match_dist >= 8U * 1024U))) {
3425 cur_match_len = 1;
3426 *pLZ_code_buf++ = (mz_uint8)first_trigram;
3427 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3428 d->m_huff_count[0][(mz_uint8)first_trigram]++;
3429 } else {
3430 mz_uint32 s0, s1;
3431 cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
3432
3433 MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) &&
3434 (cur_match_dist >= 1) &&
3435 (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
3436
3437 cur_match_dist--;
3438
3439 pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
3440 *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
3441 pLZ_code_buf += 3;
3442 *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
3443
3444 s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
3445 s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
3446 d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
3447
3448 d->m_huff_count[0][s_tdefl_len_sym[cur_match_len -
3449 TDEFL_MIN_MATCH_LEN]]++;
3450 }
3451 } else {
3452 *pLZ_code_buf++ = (mz_uint8)first_trigram;
3453 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3454 d->m_huff_count[0][(mz_uint8)first_trigram]++;
3455 }
3456
3457 if (--num_flags_left == 0) {
3458 num_flags_left = 8;
3459 pLZ_flags = pLZ_code_buf++;
3460 }
3461
3462 total_lz_bytes += cur_match_len;
3463 lookahead_pos += cur_match_len;
3464 dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
3465 cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
3466 MZ_ASSERT(lookahead_size >= cur_match_len);
3467 lookahead_size -= cur_match_len;
3468
3469 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3470 int n;
3471 d->m_lookahead_pos = lookahead_pos;
3472 d->m_lookahead_size = lookahead_size;
3473 d->m_dict_size = dict_size;
3474 d->m_total_lz_bytes = total_lz_bytes;
3475 d->m_pLZ_code_buf = pLZ_code_buf;
3476 d->m_pLZ_flags = pLZ_flags;
3477 d->m_num_flags_left = num_flags_left;
3478 if ((n = tdefl_flush_block(d, 0)) != 0)
3479 return (n < 0) ? MZ_FALSE : MZ_TRUE;
3480 total_lz_bytes = d->m_total_lz_bytes;
3481 pLZ_code_buf = d->m_pLZ_code_buf;
3482 pLZ_flags = d->m_pLZ_flags;
3483 num_flags_left = d->m_num_flags_left;
3484 }
3485 }
3486
3487 while (lookahead_size) {
3488 mz_uint8 lit = d->m_dict[cur_pos];
3489
3490 total_lz_bytes++;
3491 *pLZ_code_buf++ = lit;
3492 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3493 if (--num_flags_left == 0) {
3494 num_flags_left = 8;
3495 pLZ_flags = pLZ_code_buf++;
3496 }
3497
3498 d->m_huff_count[0][lit]++;
3499
3500 lookahead_pos++;
3501 dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
3502 cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3503 lookahead_size--;
3504
3505 if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3506 int n;
3507 d->m_lookahead_pos = lookahead_pos;
3508 d->m_lookahead_size = lookahead_size;
3509 d->m_dict_size = dict_size;
3510 d->m_total_lz_bytes = total_lz_bytes;
3511 d->m_pLZ_code_buf = pLZ_code_buf;
3512 d->m_pLZ_flags = pLZ_flags;
3513 d->m_num_flags_left = num_flags_left;
3514 if ((n = tdefl_flush_block(d, 0)) != 0)
3515 return (n < 0) ? MZ_FALSE : MZ_TRUE;
3516 total_lz_bytes = d->m_total_lz_bytes;
3517 pLZ_code_buf = d->m_pLZ_code_buf;
3518 pLZ_flags = d->m_pLZ_flags;
3519 num_flags_left = d->m_num_flags_left;
3520 }
3521 }
3522 }
3523
3524 d->m_lookahead_pos = lookahead_pos;
3525 d->m_lookahead_size = lookahead_size;
3526 d->m_dict_size = dict_size;
3527 d->m_total_lz_bytes = total_lz_bytes;
3528 d->m_pLZ_code_buf = pLZ_code_buf;
3529 d->m_pLZ_flags = pLZ_flags;
3530 d->m_num_flags_left = num_flags_left;
3531 return MZ_TRUE;
3532}
3533#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3534
3535static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d,
3536 mz_uint8 lit) {
3537 d->m_total_lz_bytes++;
3538 *d->m_pLZ_code_buf++ = lit;
3539 *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
3540 if (--d->m_num_flags_left == 0) {
3541 d->m_num_flags_left = 8;
3542 d->m_pLZ_flags = d->m_pLZ_code_buf++;
3543 }
3544 d->m_huff_count[0][lit]++;
3545}
3546
3547static MZ_FORCEINLINE void
3548tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) {
3549 mz_uint32 s0, s1;
3550
3551 MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) &&
3552 (match_dist <= TDEFL_LZ_DICT_SIZE));
3553
3554 d->m_total_lz_bytes += match_len;
3555
3556 d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
3557
3558 match_dist -= 1;
3559 d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
3560 d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
3561 d->m_pLZ_code_buf += 3;
3562
3563 *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
3564 if (--d->m_num_flags_left == 0) {
3565 d->m_num_flags_left = 8;
3566 d->m_pLZ_flags = d->m_pLZ_code_buf++;
3567 }
3568
3569 s0 = s_tdefl_small_dist_sym[match_dist & 511];
3570 s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
3571 d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
3572
3573 if (match_len >= TDEFL_MIN_MATCH_LEN)
3574 d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
3575}
3576
3577static mz_bool tdefl_compress_normal(tdefl_compressor *d) {
3578 const mz_uint8 *pSrc = d->m_pSrc;
3579 size_t src_buf_left = d->m_src_buf_left;
3580 tdefl_flush flush = d->m_flush;
3581
3582 while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) {
3583 mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
3584 // Update dictionary and hash chains. Keeps the lookahead size equal to
3585 // TDEFL_MAX_MATCH_LEN.
3586 if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) {
3587 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3588 TDEFL_LZ_DICT_SIZE_MASK,
3589 ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
3590 mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3591 << TDEFL_LZ_HASH_SHIFT) ^
3592 d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
3593 mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3594 src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
3595 const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
3596 src_buf_left -= num_bytes_to_process;
3597 d->m_lookahead_size += num_bytes_to_process;
3598 while (pSrc != pSrc_end) {
3599 mz_uint8 c = *pSrc++;
3600 d->m_dict[dst_pos] = c;
3601 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3602 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3603 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
3604 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3605 d->m_hash[hash] = (mz_uint16)(ins_pos);
3606 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3607 ins_pos++;
3608 }
3609 } else {
3610 while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) {
3611 mz_uint8 c = *pSrc++;
3612 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3613 TDEFL_LZ_DICT_SIZE_MASK;
3614 src_buf_left--;
3615 d->m_dict[dst_pos] = c;
3616 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3617 d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3618 if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) {
3619 mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
3620 mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3621 << (TDEFL_LZ_HASH_SHIFT * 2)) ^
3622 (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]
3623 << TDEFL_LZ_HASH_SHIFT) ^
3624 c) &
3625 (TDEFL_LZ_HASH_SIZE - 1);
3626 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3627 d->m_hash[hash] = (mz_uint16)(ins_pos);
3628 }
3629 }
3630 }
3631 d->m_dict_size =
3632 MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
3633 if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
3634 break;
3635
3636 // Simple lazy/greedy parsing state machine.
3637 len_to_move = 1;
3638 cur_match_dist = 0;
3639 cur_match_len =
3640 d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
3641 cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3642 if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) {
3643 if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) {
3644 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
3645 cur_match_len = 0;
3646 while (cur_match_len < d->m_lookahead_size) {
3647 if (d->m_dict[cur_pos + cur_match_len] != c)
3648 break;
3649 cur_match_len++;
3650 }
3651 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
3652 cur_match_len = 0;
3653 else
3654 cur_match_dist = 1;
3655 }
3656 } else {
3657 tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size,
3658 d->m_lookahead_size, &cur_match_dist, &cur_match_len);
3659 }
3660 if (((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3661 (cur_match_dist >= 8U * 1024U)) ||
3662 (cur_pos == cur_match_dist) ||
3663 ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) {
3664 cur_match_dist = cur_match_len = 0;
3665 }
3666 if (d->m_saved_match_len) {
3667 if (cur_match_len > d->m_saved_match_len) {
3668 tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
3669 if (cur_match_len >= 128) {
3670 tdefl_record_match(d, cur_match_len, cur_match_dist);
3671 d->m_saved_match_len = 0;
3672 len_to_move = cur_match_len;
3673 } else {
3674 d->m_saved_lit = d->m_dict[cur_pos];
3675 d->m_saved_match_dist = cur_match_dist;
3676 d->m_saved_match_len = cur_match_len;
3677 }
3678 } else {
3679 tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
3680 len_to_move = d->m_saved_match_len - 1;
3681 d->m_saved_match_len = 0;
3682 }
3683 } else if (!cur_match_dist)
3684 tdefl_record_literal(d,
3685 d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
3686 else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) ||
3687 (cur_match_len >= 128)) {
3688 tdefl_record_match(d, cur_match_len, cur_match_dist);
3689 len_to_move = cur_match_len;
3690 } else {
3691 d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
3692 d->m_saved_match_dist = cur_match_dist;
3693 d->m_saved_match_len = cur_match_len;
3694 }
3695 // Move the lookahead forward by len_to_move bytes.
3696 d->m_lookahead_pos += len_to_move;
3697 MZ_ASSERT(d->m_lookahead_size >= len_to_move);
3698 d->m_lookahead_size -= len_to_move;
3699 d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
3700 // Check if it's time to flush the current LZ codes to the internal output
3701 // buffer.
3702 if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
3703 ((d->m_total_lz_bytes > 31 * 1024) &&
3704 (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >=
3705 d->m_total_lz_bytes) ||
3706 (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) {
3707 int n;
3708 d->m_pSrc = pSrc;
3709 d->m_src_buf_left = src_buf_left;
3710 if ((n = tdefl_flush_block(d, 0)) != 0)
3711 return (n < 0) ? MZ_FALSE : MZ_TRUE;
3712 }
3713 }
3714
3715 d->m_pSrc = pSrc;
3716 d->m_src_buf_left = src_buf_left;
3717 return MZ_TRUE;
3718}
3719
3720static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) {
3721 if (d->m_pIn_buf_size) {
3722 *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3723 }
3724
3725 if (d->m_pOut_buf_size) {
3726 size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs,
3727 d->m_output_flush_remaining);
3728 memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs,
3729 d->m_output_buf + d->m_output_flush_ofs, n);
3730 d->m_output_flush_ofs += (mz_uint)n;
3731 d->m_output_flush_remaining -= (mz_uint)n;
3732 d->m_out_buf_ofs += n;
3733
3734 *d->m_pOut_buf_size = d->m_out_buf_ofs;
3735 }
3736
3737 return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE
3738 : TDEFL_STATUS_OKAY;
3739}
3740
3741tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
3742 size_t *pIn_buf_size, void *pOut_buf,
3743 size_t *pOut_buf_size, tdefl_flush flush) {
3744 if (!d) {
3745 if (pIn_buf_size)
3746 *pIn_buf_size = 0;
3747 if (pOut_buf_size)
3748 *pOut_buf_size = 0;
3749 return TDEFL_STATUS_BAD_PARAM;
3750 }
3751
3752 d->m_pIn_buf = pIn_buf;
3753 d->m_pIn_buf_size = pIn_buf_size;
3754 d->m_pOut_buf = pOut_buf;
3755 d->m_pOut_buf_size = pOut_buf_size;
3756 d->m_pSrc = (const mz_uint8 *)(pIn_buf);
3757 d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
3758 d->m_out_buf_ofs = 0;
3759 d->m_flush = flush;
3760
3761 if (((d->m_pPut_buf_func != NULL) ==
3762 ((pOut_buf != NULL) || (pOut_buf_size != NULL))) ||
3763 (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
3764 (d->m_wants_to_finish && (flush != TDEFL_FINISH)) ||
3765 (pIn_buf_size && *pIn_buf_size && !pIn_buf) ||
3766 (pOut_buf_size && *pOut_buf_size && !pOut_buf)) {
3767 if (pIn_buf_size)
3768 *pIn_buf_size = 0;
3769 if (pOut_buf_size)
3770 *pOut_buf_size = 0;
3771 return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
3772 }
3773 d->m_wants_to_finish |= (flush == TDEFL_FINISH);
3774
3775 if ((d->m_output_flush_remaining) || (d->m_finished))
3776 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3777
3778#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3779 if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
3780 ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
3781 ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS |
3782 TDEFL_RLE_MATCHES)) == 0)) {
3783 if (!tdefl_compress_fast(d))
3784 return d->m_prev_return_status;
3785 } else
3786#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3787 {
3788 if (!tdefl_compress_normal(d))
3789 return d->m_prev_return_status;
3790 }
3791
3792 if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) &&
3793 (pIn_buf))
3794 d->m_adler32 =
3795 (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf,
3796 d->m_pSrc - (const mz_uint8 *)pIn_buf);
3797
3798 if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) &&
3799 (!d->m_output_flush_remaining)) {
3800 if (tdefl_flush_block(d, flush) < 0)
3801 return d->m_prev_return_status;
3802 d->m_finished = (flush == TDEFL_FINISH);
3803 if (flush == TDEFL_FULL_FLUSH) {
3804 MZ_CLEAR_OBJ(d->m_hash);
3805 MZ_CLEAR_OBJ(d->m_next);
3806 d->m_dict_size = 0;
3807 }
3808 }
3809
3810 return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3811}
3812
3813tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
3814 size_t in_buf_size, tdefl_flush flush) {
3815 MZ_ASSERT(d->m_pPut_buf_func);
3816 return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
3817}
3818
3819tdefl_status tdefl_init(tdefl_compressor *d,
3820 tdefl_put_buf_func_ptr pPut_buf_func,
3821 void *pPut_buf_user, int flags) {
3822 d->m_pPut_buf_func = pPut_buf_func;
3823 d->m_pPut_buf_user = pPut_buf_user;
3824 d->m_flags = (mz_uint)(flags);
3825 d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
3826 d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
3827 d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
3828 if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
3829 MZ_CLEAR_OBJ(d->m_hash);
3830 d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size =
3831 d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
3832 d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished =
3833 d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
3834 d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3835 d->m_pLZ_flags = d->m_lz_code_buf;
3836 d->m_num_flags_left = 8;
3837 d->m_pOutput_buf = d->m_output_buf;
3838 d->m_pOutput_buf_end = d->m_output_buf;
3839 d->m_prev_return_status = TDEFL_STATUS_OKAY;
3840 d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
3841 d->m_adler32 = 1;
3842 d->m_pIn_buf = NULL;
3843 d->m_pOut_buf = NULL;
3844 d->m_pIn_buf_size = NULL;
3845 d->m_pOut_buf_size = NULL;
3846 d->m_flush = TDEFL_NO_FLUSH;
3847 d->m_pSrc = NULL;
3848 d->m_src_buf_left = 0;
3849 d->m_out_buf_ofs = 0;
3850 memset(&d->m_huff_count[0][0], 0,
3851 sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3852 memset(&d->m_huff_count[1][0], 0,
3853 sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3854 return TDEFL_STATUS_OKAY;
3855}
3856
3857tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
3858 return d->m_prev_return_status;
3859}
3860
3861mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
3862
3863mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
3864 tdefl_put_buf_func_ptr pPut_buf_func,
3865 void *pPut_buf_user, int flags) {
3866 tdefl_compressor *pComp;
3867 mz_bool succeeded;
3868 if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
3869 return MZ_FALSE;
3870 pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3871 if (!pComp)
3872 return MZ_FALSE;
3873 succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) ==
3874 TDEFL_STATUS_OKAY);
3875 succeeded =
3876 succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) ==
3877 TDEFL_STATUS_DONE);
3878 MZ_FREE(pComp);
3879 return succeeded;
3880}
3881
3882typedef struct {
3883 size_t m_size, m_capacity;
3884 mz_uint8 *m_pBuf;
3885 mz_bool m_expandable;
3887
3888static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len,
3889 void *pUser) {
3891 size_t new_size = p->m_size + len;
3892 if (new_size > p->m_capacity) {
3893 size_t new_capacity = p->m_capacity;
3894 mz_uint8 *pNew_buf;
3895 if (!p->m_expandable)
3896 return MZ_FALSE;
3897 do {
3898 new_capacity = MZ_MAX(128U, new_capacity << 1U);
3899 } while (new_size > new_capacity);
3900 pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
3901 if (!pNew_buf)
3902 return MZ_FALSE;
3903 p->m_pBuf = pNew_buf;
3904 p->m_capacity = new_capacity;
3905 }
3906 memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
3907 p->m_size = new_size;
3908 return MZ_TRUE;
3909}
3910
3911void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
3912 size_t *pOut_len, int flags) {
3913 tdefl_output_buffer out_buf;
3914 MZ_CLEAR_OBJ(out_buf);
3915 if (!pOut_len)
3916 return MZ_FALSE;
3917 else
3918 *pOut_len = 0;
3919 out_buf.m_expandable = MZ_TRUE;
3920 if (!tdefl_compress_mem_to_output(
3921 pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3922 return NULL;
3923 *pOut_len = out_buf.m_size;
3924 return out_buf.m_pBuf;
3925}
3926
3927size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
3928 const void *pSrc_buf, size_t src_buf_len,
3929 int flags) {
3930 tdefl_output_buffer out_buf;
3931 MZ_CLEAR_OBJ(out_buf);
3932 if (!pOut_buf)
3933 return 0;
3934 out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
3935 out_buf.m_capacity = out_buf_len;
3936 if (!tdefl_compress_mem_to_output(
3937 pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3938 return 0;
3939 return out_buf.m_size;
3940}
3941
3942#ifndef MINIZ_NO_ZLIB_APIS
3943static const mz_uint s_tdefl_num_probes[11] = {0, 1, 6, 32, 16, 32,
3944 128, 256, 512, 768, 1500};
3945
3946// level may actually range from [0,10] (10 is a "hidden" max level, where we
3947// want a bit more compression and it's fine if throughput to fall off a cliff
3948// on some files).
3949mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
3950 int strategy) {
3951 mz_uint comp_flags =
3952 s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] |
3953 ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
3954 if (window_bits > 0)
3955 comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
3956
3957 if (!level)
3958 comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
3959 else if (strategy == MZ_FILTERED)
3960 comp_flags |= TDEFL_FILTER_MATCHES;
3961 else if (strategy == MZ_HUFFMAN_ONLY)
3962 comp_flags &= ~TDEFL_MAX_PROBES_MASK;
3963 else if (strategy == MZ_FIXED)
3964 comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
3965 else if (strategy == MZ_RLE)
3966 comp_flags |= TDEFL_RLE_MATCHES;
3967
3968 return comp_flags;
3969}
3970#endif // MINIZ_NO_ZLIB_APIS
3971
3972#ifdef _MSC_VER
3973#pragma warning(push)
3974#pragma warning(disable : 4204) // nonstandard extension used : non-constant
3975 // aggregate initializer (also supported by GNU
3976 // C and C99, so no big deal)
3977#endif
3978
3979// Simple PNG writer function by Alex Evans, 2011. Released into the public
3980// domain: https://gist.github.com/908299, more context at
3981// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
3982// This is actually a modification of Alex's original code so PNG files
3983// generated by this function pass pngcheck.
3984void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
3985 int h, int num_chans,
3986 size_t *pLen_out,
3987 mz_uint level, mz_bool flip) {
3988 // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was
3989 // defined.
3990 static const mz_uint s_tdefl_png_num_probes[11] = {
3991 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500};
3992 tdefl_compressor *pComp =
3993 (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3994 tdefl_output_buffer out_buf;
3995 int i, bpl = w * num_chans, y, z;
3996 mz_uint32 c;
3997 *pLen_out = 0;
3998 if (!pComp)
3999 return NULL;
4000 MZ_CLEAR_OBJ(out_buf);
4001 out_buf.m_expandable = MZ_TRUE;
4002 out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
4003 if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) {
4004 MZ_FREE(pComp);
4005 return NULL;
4006 }
4007 // write dummy header
4008 for (z = 41; z; --z)
4009 tdefl_output_buffer_putter(&z, 1, &out_buf);
4010 // compress image data
4011 tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf,
4012 s_tdefl_png_num_probes[MZ_MIN(10, level)] |
4013 TDEFL_WRITE_ZLIB_HEADER);
4014 for (y = 0; y < h; ++y) {
4015 tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
4016 tdefl_compress_buffer(pComp,
4017 (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl,
4018 bpl, TDEFL_NO_FLUSH);
4019 }
4020 if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) !=
4021 TDEFL_STATUS_DONE) {
4022 MZ_FREE(pComp);
4023 MZ_FREE(out_buf.m_pBuf);
4024 return NULL;
4025 }
4026 // write real header
4027 *pLen_out = out_buf.m_size - 41;
4028 {
4029 static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
4030 mz_uint8 pnghdr[41] = {0x89,
4031 0x50,
4032 0x4e,
4033 0x47,
4034 0x0d,
4035 0x0a,
4036 0x1a,
4037 0x0a,
4038 0x00,
4039 0x00,
4040 0x00,
4041 0x0d,
4042 0x49,
4043 0x48,
4044 0x44,
4045 0x52,
4046 0,
4047 0,
4048 (mz_uint8)(w >> 8),
4049 (mz_uint8)w,
4050 0,
4051 0,
4052 (mz_uint8)(h >> 8),
4053 (mz_uint8)h,
4054 8,
4055 chans[num_chans],
4056 0,
4057 0,
4058 0,
4059 0,
4060 0,
4061 0,
4062 0,
4063 (mz_uint8)(*pLen_out >> 24),
4064 (mz_uint8)(*pLen_out >> 16),
4065 (mz_uint8)(*pLen_out >> 8),
4066 (mz_uint8)*pLen_out,
4067 0x49,
4068 0x44,
4069 0x41,
4070 0x54};
4071 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
4072 for (i = 0; i < 4; ++i, c <<= 8)
4073 ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
4074 memcpy(out_buf.m_pBuf, pnghdr, 41);
4075 }
4076 // write footer (IDAT CRC-32, followed by IEND chunk)
4077 if (!tdefl_output_buffer_putter(
4078 "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) {
4079 *pLen_out = 0;
4080 MZ_FREE(pComp);
4081 MZ_FREE(out_buf.m_pBuf);
4082 return NULL;
4083 }
4084 c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4,
4085 *pLen_out + 4);
4086 for (i = 0; i < 4; ++i, c <<= 8)
4087 (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
4088 // compute final size of file, grab compressed data buffer and return
4089 *pLen_out += 57;
4090 MZ_FREE(pComp);
4091 return out_buf.m_pBuf;
4092}
4093void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
4094 int num_chans, size_t *pLen_out) {
4095 // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we
4096 // can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's
4097 // where #defined out)
4098 return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans,
4099 pLen_out, 6, MZ_FALSE);
4100}
4101
4102#ifdef _MSC_VER
4103#pragma warning(pop)
4104#endif
4105
4106// ------------------- .ZIP archive reading
4107
4108#ifndef MINIZ_NO_ARCHIVE_APIS
4109
4110#ifdef MINIZ_NO_STDIO
4111#define MZ_FILE void *
4112#else
4113#include <stdio.h>
4114#include <sys/stat.h>
4115
4116#if defined(_MSC_VER) || defined(__MINGW32__)
4117
4118#include <windows.h>
4119
4120static wchar_t *str2wstr(const char *str) {
4121 int len = strlen(str) + 1;
4122 wchar_t *wstr = static_cast<wchar_t*>(malloc(len * sizeof(wchar_t)));
4123 MultiByteToWideChar(CP_UTF8, 0, str, len * sizeof(char), wstr, len);
4124 return wstr;
4125}
4126
4127static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4128 wchar_t *wFilename = str2wstr(pFilename);
4129 wchar_t *wMode = str2wstr(pMode);
4130 FILE *pFile = _wfopen(wFilename, wMode);
4131
4132 free(wFilename);
4133 free(wMode);
4134
4135 return pFile;
4136}
4137
4138static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4139 wchar_t *wPath = str2wstr(pPath);
4140 wchar_t *wMode = str2wstr(pMode);
4141 FILE *pFile = _wfreopen(wPath, wMode, pStream);
4142
4143 free(wPath);
4144 free(wMode);
4145
4146 return pFile;
4147}
4148
4149#ifndef MINIZ_NO_TIME
4150#include <sys/utime.h>
4151#endif
4152#define MZ_FILE FILE
4153#define MZ_FOPEN mz_fopen
4154#define MZ_FCLOSE fclose
4155#define MZ_FREAD fread
4156#define MZ_FWRITE fwrite
4157#define MZ_FTELL64 _ftelli64
4158#define MZ_FSEEK64 _fseeki64
4159#define MZ_FILE_STAT_STRUCT _stat
4160#define MZ_FILE_STAT _stat
4161#define MZ_FFLUSH fflush
4162#define MZ_FREOPEN mz_freopen
4163#define MZ_DELETE_FILE remove
4164#elif defined(__MINGW32__)
4165#ifndef MINIZ_NO_TIME
4166#include <sys/utime.h>
4167#endif
4168#define MZ_FILE FILE
4169#define MZ_FOPEN(f, m) mz_fopen
4170#define MZ_FCLOSE fclose
4171#define MZ_FREAD fread
4172#define MZ_FWRITE fwrite
4173#define MZ_FTELL64 ftell
4174#define MZ_FSEEK64 fseek
4175#define MZ_FILE_STAT_STRUCT _stat
4176#define MZ_FILE_STAT _stat
4177#define MZ_FFLUSH fflush
4178#define MZ_FREOPEN(f, m, s) mz_freopen
4179#define MZ_DELETE_FILE remove
4180#elif defined(__TINYC__)
4181#ifndef MINIZ_NO_TIME
4182#include <sys/utime.h>
4183#endif
4184#define MZ_FILE FILE
4185#define MZ_FOPEN(f, m) fopen(f, m)
4186#define MZ_FCLOSE fclose
4187#define MZ_FREAD fread
4188#define MZ_FWRITE fwrite
4189#define MZ_FTELL64 ftell
4190#define MZ_FSEEK64 fseek
4191#define MZ_FILE_STAT_STRUCT stat
4192#define MZ_FILE_STAT stat
4193#define MZ_FFLUSH fflush
4194#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4195#define MZ_DELETE_FILE remove
4196#elif defined(__GNUC__) && _LARGEFILE64_SOURCE
4197#ifndef MINIZ_NO_TIME
4198#include <utime.h>
4199#endif
4200#define MZ_FILE FILE
4201#define MZ_FOPEN(f, m) fopen64(f, m)
4202#define MZ_FCLOSE fclose
4203#define MZ_FREAD fread
4204#define MZ_FWRITE fwrite
4205#define MZ_FTELL64 ftello64
4206#define MZ_FSEEK64 fseeko64
4207#define MZ_FILE_STAT_STRUCT stat64
4208#define MZ_FILE_STAT stat64
4209#define MZ_FFLUSH fflush
4210#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4211#define MZ_DELETE_FILE remove
4212#else
4213#ifndef MINIZ_NO_TIME
4214#include <utime.h>
4215#endif
4216#define MZ_FILE FILE
4217#define MZ_FOPEN(f, m) fopen(f, m)
4218#define MZ_FCLOSE fclose
4219#define MZ_FREAD fread
4220#define MZ_FWRITE fwrite
4221#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L
4222#define MZ_FTELL64 ftello
4223#define MZ_FSEEK64 fseeko
4224#else
4225#define MZ_FTELL64 ftell
4226#define MZ_FSEEK64 fseek
4227#endif
4228#define MZ_FILE_STAT_STRUCT stat
4229#define MZ_FILE_STAT stat
4230#define MZ_FFLUSH fflush
4231#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4232#define MZ_DELETE_FILE remove
4233#endif // #ifdef _MSC_VER
4234#endif // #ifdef MINIZ_NO_STDIO
4235
4236#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4237
4238// Various ZIP archive enums. To completely avoid cross platform compiler
4239// alignment and platform endian issues, miniz.c doesn't use structs for any of
4240// this stuff.
4241enum {
4242 // ZIP archive identifiers and record sizes
4243 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
4244 MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
4245 MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
4246 MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
4247 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
4248 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
4249
4250 /* ZIP64 archive identifier and record sizes */
4251 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
4252 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
4253 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
4254 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
4255 MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
4256 MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
4257 MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
4258 MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
4259
4260 // Central directory header record offsets
4261 MZ_ZIP_CDH_SIG_OFS = 0,
4262 MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
4263 MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
4264 MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
4265 MZ_ZIP_CDH_METHOD_OFS = 10,
4266 MZ_ZIP_CDH_FILE_TIME_OFS = 12,
4267 MZ_ZIP_CDH_FILE_DATE_OFS = 14,
4268 MZ_ZIP_CDH_CRC32_OFS = 16,
4269 MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
4270 MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
4271 MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
4272 MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
4273 MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
4274 MZ_ZIP_CDH_DISK_START_OFS = 34,
4275 MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
4276 MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
4277 MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
4278 // Local directory header offsets
4279 MZ_ZIP_LDH_SIG_OFS = 0,
4280 MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
4281 MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
4282 MZ_ZIP_LDH_METHOD_OFS = 8,
4283 MZ_ZIP_LDH_FILE_TIME_OFS = 10,
4284 MZ_ZIP_LDH_FILE_DATE_OFS = 12,
4285 MZ_ZIP_LDH_CRC32_OFS = 14,
4286 MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
4287 MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
4288 MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
4289 MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
4290 // End of central directory offsets
4291 MZ_ZIP_ECDH_SIG_OFS = 0,
4292 MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
4293 MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
4294 MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
4295 MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
4296 MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
4297 MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
4298 MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
4299
4300 /* ZIP64 End of central directory locator offsets */
4301 MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
4302 MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
4303 MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
4304 MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
4305
4306 /* ZIP64 End of central directory header offsets */
4307 MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
4308 MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
4309 MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
4310 MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
4311 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
4312 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
4313 MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
4314 MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
4315 MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
4316 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
4317 MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
4318 MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
4319 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
4320 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
4321 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
4322 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
4323 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
4324};
4325
4326typedef struct {
4327 void *m_p;
4328 size_t m_size, m_capacity;
4329 mz_uint m_element_size;
4330} mz_zip_array;
4331
4333 mz_zip_array m_central_dir;
4334 mz_zip_array m_central_dir_offsets;
4335 mz_zip_array m_sorted_central_dir_offsets;
4336
4337 /* The flags passed in when the archive is initially opened. */
4338 uint32_t m_init_flags;
4339
4340 /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
4341 */
4342 mz_bool m_zip64;
4343
4344 /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
4345 * will also be slammed to true too, even if we didn't find a zip64 end of
4346 * central dir header, etc.) */
4347 mz_bool m_zip64_has_extended_info_fields;
4348
4349 /* These fields are used by the file, FILE, memory, and memory/heap read/write
4350 * helpers. */
4351 MZ_FILE *m_pFile;
4352 mz_uint64 m_file_archive_start_ofs;
4353
4354 void *m_pMem;
4355 size_t m_mem_size;
4356 size_t m_mem_capacity;
4357};
4358
4359#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) \
4360 (array_ptr)->m_element_size = element_size
4361#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) \
4362 ((element_type *)((array_ptr)->m_p))[index]
4363
4364static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
4365 mz_zip_array *pArray) {
4366 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
4367 memset(pArray, 0, sizeof(mz_zip_array));
4368}
4369
4370static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
4371 mz_zip_array *pArray,
4372 size_t min_new_capacity,
4373 mz_uint growing) {
4374 void *pNew_p;
4375 size_t new_capacity = min_new_capacity;
4376 MZ_ASSERT(pArray->m_element_size);
4377 if (pArray->m_capacity >= min_new_capacity)
4378 return MZ_TRUE;
4379 if (growing) {
4380 new_capacity = MZ_MAX(1, pArray->m_capacity);
4381 while (new_capacity < min_new_capacity)
4382 new_capacity *= 2;
4383 }
4384 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
4385 pArray->m_element_size, new_capacity)))
4386 return MZ_FALSE;
4387 pArray->m_p = pNew_p;
4388 pArray->m_capacity = new_capacity;
4389 return MZ_TRUE;
4390}
4391
4392static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
4393 mz_zip_array *pArray,
4394 size_t new_capacity,
4395 mz_uint growing) {
4396 if (new_capacity > pArray->m_capacity) {
4397 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
4398 return MZ_FALSE;
4399 }
4400 return MZ_TRUE;
4401}
4402
4403static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
4404 mz_zip_array *pArray,
4405 size_t new_size,
4406 mz_uint growing) {
4407 if (new_size > pArray->m_capacity) {
4408 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
4409 return MZ_FALSE;
4410 }
4411 pArray->m_size = new_size;
4412 return MZ_TRUE;
4413}
4414
4415static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
4416 mz_zip_array *pArray,
4417 size_t n) {
4418 return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
4419}
4420
4421static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
4422 mz_zip_array *pArray,
4423 const void *pElements,
4424 size_t n) {
4425 if (0 == n)
4426 return MZ_TRUE;
4427 if (!pElements)
4428 return MZ_FALSE;
4429
4430 size_t orig_size = pArray->m_size;
4431 if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
4432 return MZ_FALSE;
4433 memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
4434 pElements, n * pArray->m_element_size);
4435 return MZ_TRUE;
4436}
4437
4438#ifndef MINIZ_NO_TIME
4439static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
4440 struct tm tm;
4441 memset(&tm, 0, sizeof(tm));
4442 tm.tm_isdst = -1;
4443 tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
4444 tm.tm_mon = ((dos_date >> 5) & 15) - 1;
4445 tm.tm_mday = dos_date & 31;
4446 tm.tm_hour = (dos_time >> 11) & 31;
4447 tm.tm_min = (dos_time >> 5) & 63;
4448 tm.tm_sec = (dos_time << 1) & 62;
4449 return mktime(&tm);
4450}
4451
4452#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4453static void mz_zip_time_t_to_dos_time(time_t time, mz_uint16 *pDOS_time,
4454 mz_uint16 *pDOS_date) {
4455#ifdef _MSC_VER
4456 struct tm tm_struct;
4457 struct tm *tm = &tm_struct;
4458 errno_t err = localtime_s(tm, &time);
4459 if (err) {
4460 *pDOS_date = 0;
4461 *pDOS_time = 0;
4462 return;
4463 }
4464#else
4465 struct tm *tm = localtime(&time);
4466#endif /* #ifdef _MSC_VER */
4467
4468 *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
4469 ((tm->tm_sec) >> 1));
4470 *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
4471 ((tm->tm_mon + 1) << 5) + tm->tm_mday);
4472}
4473#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
4474
4475#ifndef MINIZ_NO_STDIO
4476#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
4477static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
4478 time_t *pTime) {
4479 struct MZ_FILE_STAT_STRUCT file_stat;
4480
4481 /* On Linux with x86 glibc, this call will fail on large files (I think >=
4482 * 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
4483 if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
4484 return MZ_FALSE;
4485
4486 *pTime = file_stat.st_mtime;
4487
4488 return MZ_TRUE;
4489}
4490#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
4491
4492static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
4493 time_t modified_time) {
4494 struct utimbuf t;
4495
4496 memset(&t, 0, sizeof(t));
4497 t.actime = access_time;
4498 t.modtime = modified_time;
4499
4500 return !utime(pFilename, &t);
4501}
4502#endif /* #ifndef MINIZ_NO_STDIO */
4503#endif /* #ifndef MINIZ_NO_TIME */
4504
4505static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
4506 mz_zip_error err_num) {
4507 if (pZip)
4508 pZip->m_last_error = err_num;
4509 return MZ_FALSE;
4510}
4511
4512static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
4513 mz_uint32 flags) {
4514 (void)flags;
4515 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
4516 return MZ_FALSE;
4517
4518 if (!pZip->m_pAlloc)
4519 pZip->m_pAlloc = def_alloc_func;
4520 if (!pZip->m_pFree)
4521 pZip->m_pFree = def_free_func;
4522 if (!pZip->m_pRealloc)
4523 pZip->m_pRealloc = def_realloc_func;
4524
4525 pZip->m_zip_mode = MZ_ZIP_MODE_READING;
4526 pZip->m_archive_size = 0;
4527 pZip->m_central_directory_file_ofs = 0;
4528 pZip->m_total_files = 0;
4529
4530 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
4531 pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
4532 return MZ_FALSE;
4533 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
4534 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
4535 sizeof(mz_uint8));
4536 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
4537 sizeof(mz_uint32));
4538 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
4539 sizeof(mz_uint32));
4540 return MZ_TRUE;
4541}
4542
4543static MZ_FORCEINLINE mz_bool
4544mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
4545 const mz_zip_array *pCentral_dir_offsets,
4546 mz_uint l_index, mz_uint r_index) {
4547 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
4548 pCentral_dir_array, mz_uint8,
4549 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
4550 l_index)),
4551 *pE;
4552 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
4553 pCentral_dir_array, mz_uint8,
4554 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
4555 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
4556 r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4557 mz_uint8 l = 0, r = 0;
4558 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4559 pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4560 pE = pL + MZ_MIN(l_len, r_len);
4561 while (pL < pE) {
4562 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4563 break;
4564 pL++;
4565 pR++;
4566 }
4567 return (pL == pE) ? (l_len < r_len) : (l < r);
4568}
4569
4570#define MZ_SWAP_UINT32(a, b) \
4571 do { \
4572 mz_uint32 t = a; \
4573 a = b; \
4574 b = t; \
4575 } \
4576 MZ_MACRO_END
4577
4578// Heap sort of lowercased filenames, used to help accelerate plain central
4579// directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
4580// but it could allocate memory.)
4581static void
4582mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
4583 mz_zip_internal_state *pState = pZip->m_pState;
4584 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4585 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4586 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
4587 &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4588 const int size = pZip->m_total_files;
4589 int start = (size - 2) >> 1, end;
4590 while (start >= 0) {
4591 int child, root = start;
4592 for (;;) {
4593 if ((child = (root << 1) + 1) >= size)
4594 break;
4595 child +=
4596 (((child + 1) < size) &&
4597 (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4598 pIndices[child], pIndices[child + 1])));
4599 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4600 pIndices[root], pIndices[child]))
4601 break;
4602 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4603 root = child;
4604 }
4605 start--;
4606 }
4607
4608 end = size - 1;
4609 while (end > 0) {
4610 int child, root = 0;
4611 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
4612 for (;;) {
4613 if ((child = (root << 1) + 1) >= end)
4614 break;
4615 child +=
4616 (((child + 1) < end) &&
4617 mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4618 pIndices[child], pIndices[child + 1]));
4619 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
4620 pIndices[root], pIndices[child]))
4621 break;
4622 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
4623 root = child;
4624 }
4625 end--;
4626 }
4627}
4628
4629static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
4630 mz_uint32 record_sig,
4631 mz_uint32 record_size,
4632 mz_int64 *pOfs) {
4633 mz_int64 cur_file_ofs;
4634 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4635 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4636
4637 /* Basic sanity checks - reject files which are too small */
4638 if (pZip->m_archive_size < record_size)
4639 return MZ_FALSE;
4640
4641 /* Find the record by scanning the file from the end towards the beginning. */
4642 cur_file_ofs =
4643 MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
4644 for (;;) {
4645 int i,
4646 n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
4647
4648 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
4649 return MZ_FALSE;
4650
4651 for (i = n - 4; i >= 0; --i) {
4652 mz_uint s = MZ_READ_LE32(pBuf + i);
4653 if (s == record_sig) {
4654 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
4655 break;
4656 }
4657 }
4658
4659 if (i >= 0) {
4660 cur_file_ofs += i;
4661 break;
4662 }
4663
4664 /* Give up if we've searched the entire file, or we've gone back "too far"
4665 * (~64kb) */
4666 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
4667 (MZ_UINT16_MAX + record_size)))
4668 return MZ_FALSE;
4669
4670 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
4671 }
4672
4673 *pOfs = cur_file_ofs;
4674 return MZ_TRUE;
4675}
4676
4677static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
4678 mz_uint flags) {
4679 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
4680 cdir_disk_index = 0;
4681 mz_uint64 cdir_ofs = 0;
4682 mz_int64 cur_file_ofs = 0;
4683 const mz_uint8 *p;
4684
4685 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
4686 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
4687 mz_bool sort_central_dir =
4688 ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
4689 mz_uint32 zip64_end_of_central_dir_locator_u32
4690 [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
4691 sizeof(mz_uint32)];
4692 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
4693
4694 mz_uint32 zip64_end_of_central_dir_header_u32
4695 [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
4696 sizeof(mz_uint32)];
4697 mz_uint8 *pZip64_end_of_central_dir =
4698 (mz_uint8 *)zip64_end_of_central_dir_header_u32;
4699
4700 mz_uint64 zip64_end_of_central_dir_ofs = 0;
4701
4702 /* Basic sanity checks - reject files which are too small, and check the first
4703 * 4 bytes of the file to make sure a local header is there. */
4704 if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4705 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4706
4707 if (!mz_zip_reader_locate_header_sig(
4708 pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
4709 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
4710 return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
4711
4712 /* Read and verify the end of central directory record. */
4713 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
4714 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
4715 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4716 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4717
4718 if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
4719 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
4720 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4721
4722 if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
4723 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
4724 if (pZip->m_pRead(pZip->m_pIO_opaque,
4725 cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
4726 pZip64_locator,
4727 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
4728 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
4729 if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
4730 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
4731 zip64_end_of_central_dir_ofs = MZ_READ_LE64(
4732 pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
4733 if (zip64_end_of_central_dir_ofs >
4734 (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
4735 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4736
4737 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
4738 pZip64_end_of_central_dir,
4739 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
4740 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
4741 if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
4742 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
4743 pZip->m_pState->m_zip64 = MZ_TRUE;
4744 }
4745 }
4746 }
4747 }
4748 }
4749
4750 pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4751 cdir_entries_on_this_disk =
4752 MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4753 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
4754 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
4755 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
4756 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
4757
4758 if (pZip->m_pState->m_zip64) {
4759 mz_uint32 zip64_total_num_of_disks =
4760 MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
4761 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
4762 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
4763 mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
4764 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
4765 mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
4766 pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
4767 mz_uint64 zip64_size_of_central_directory =
4768 MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
4769
4770 if (zip64_size_of_end_of_central_dir_record <
4771 (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
4772 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4773
4774 if (zip64_total_num_of_disks != 1U)
4775 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4776
4777 /* Check for miniz's practical limits */
4778 if (zip64_cdir_total_entries > MZ_UINT32_MAX)
4779 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4780
4781 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
4782
4783 if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
4784 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
4785
4786 cdir_entries_on_this_disk =
4787 (mz_uint32)zip64_cdir_total_entries_on_this_disk;
4788
4789 /* Check for miniz's current practical limits (sorry, this should be enough
4790 * for millions of files) */
4791 if (zip64_size_of_central_directory > MZ_UINT32_MAX)
4792 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
4793
4794 cdir_size = (mz_uint32)zip64_size_of_central_directory;
4795
4796 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
4797 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
4798
4799 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
4800 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
4801
4802 cdir_ofs =
4803 MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
4804 }
4805
4806 if (pZip->m_total_files != cdir_entries_on_this_disk)
4807 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4808
4809 if (((num_this_disk | cdir_disk_index) != 0) &&
4810 ((num_this_disk != 1) || (cdir_disk_index != 1)))
4811 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4812
4813 if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
4814 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4815
4816 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
4817 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4818
4819 pZip->m_central_directory_file_ofs = cdir_ofs;
4820
4821 if (pZip->m_total_files) {
4822 mz_uint i, n;
4823 /* Read the entire central directory into a heap block, and allocate another
4824 * heap block to hold the unsorted central dir file record offsets, and
4825 * possibly another to hold the sorted indices. */
4826 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
4827 MZ_FALSE)) ||
4828 (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
4829 pZip->m_total_files, MZ_FALSE)))
4830 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4831
4832 if (sort_central_dir) {
4833 if (!mz_zip_array_resize(pZip,
4834 &pZip->m_pState->m_sorted_central_dir_offsets,
4835 pZip->m_total_files, MZ_FALSE))
4836 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4837 }
4838
4839 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
4840 pZip->m_pState->m_central_dir.m_p,
4841 cdir_size) != cdir_size)
4842 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4843
4844 /* Now create an index into the central directory file records, do some
4845 * basic sanity checking on each record */
4846 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
4847 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
4848 mz_uint total_header_size, disk_index, bit_flags, filename_size,
4849 ext_data_size;
4850 mz_uint64 comp_size, decomp_size, local_header_ofs;
4851
4852 if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
4853 (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
4854 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4855
4856 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
4857 i) =
4858 (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
4859
4860 if (sort_central_dir)
4861 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
4862 mz_uint32, i) = i;
4863
4864 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4865 decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4866 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4867 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4868 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4869
4870 if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
4871 (ext_data_size) &&
4872 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
4873 MZ_UINT32_MAX)) {
4874 /* Attempt to find zip64 extended information field in the entry's extra
4875 * data */
4876 mz_uint32 extra_size_remaining = ext_data_size;
4877
4878 if (extra_size_remaining) {
4879 const mz_uint8 *pExtra_data;
4880 void *buf = NULL;
4881
4882 if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
4883 n) {
4884 buf = MZ_MALLOC(ext_data_size);
4885 if (buf == NULL)
4886 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4887
4888 if (pZip->m_pRead(pZip->m_pIO_opaque,
4889 cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4890 filename_size,
4891 buf, ext_data_size) != ext_data_size) {
4892 MZ_FREE(buf);
4893 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4894 }
4895
4896 pExtra_data = (mz_uint8 *)buf;
4897 } else {
4898 pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
4899 }
4900
4901 do {
4902 mz_uint32 field_id;
4903 mz_uint32 field_data_size;
4904
4905 if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
4906 MZ_FREE(buf);
4907 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4908 }
4909
4910 field_id = MZ_READ_LE16(pExtra_data);
4911 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4912
4913 if ((field_data_size + sizeof(mz_uint16) * 2) >
4914 extra_size_remaining) {
4915 MZ_FREE(buf);
4916 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4917 }
4918
4919 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
4920 /* Ok, the archive didn't have any zip64 headers but it uses a
4921 * zip64 extended information field so mark it as zip64 anyway
4922 * (this can occur with infozip's zip util when it reads
4923 * compresses files from stdin). */
4924 pZip->m_pState->m_zip64 = MZ_TRUE;
4925 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
4926 break;
4927 }
4928
4929 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4930 extra_size_remaining =
4931 extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4932 } while (extra_size_remaining);
4933
4934 MZ_FREE(buf);
4935 }
4936 }
4937
4938 /* I've seen archives that aren't marked as zip64 that uses zip64 ext
4939 * data, argh */
4940 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
4941 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
4942 (decomp_size != comp_size)) ||
4943 (decomp_size && !comp_size))
4944 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4945 }
4946
4947 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
4948 if ((disk_index == MZ_UINT16_MAX) ||
4949 ((disk_index != num_this_disk) && (disk_index != 1)))
4950 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
4951
4952 if (comp_size != MZ_UINT32_MAX) {
4953 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
4954 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
4955 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4956 }
4957
4958 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4959 if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
4960 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4961
4962 if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
4963 MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
4964 MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
4965 MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
4966 n)
4967 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4968
4969 n -= total_header_size;
4970 p += total_header_size;
4971 }
4972 }
4973
4974 if (sort_central_dir)
4975 mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
4976
4977 return MZ_TRUE;
4978}
4979
4980mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
4981 mz_uint32 flags) {
4982 if ((!pZip) || (!pZip->m_pRead))
4983 return MZ_FALSE;
4984 if (!mz_zip_reader_init_internal(pZip, flags))
4985 return MZ_FALSE;
4986 pZip->m_archive_size = size;
4987 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
4988 mz_zip_reader_end(pZip);
4989 return MZ_FALSE;
4990 }
4991 return MZ_TRUE;
4992}
4993
4994static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
4995 void *pBuf, size_t n) {
4996 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4997 size_t s = (file_ofs >= pZip->m_archive_size)
4998 ? 0
4999 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
5000 memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
5001 return s;
5002}
5003
5004mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
5005 size_t size, mz_uint32 flags) {
5006 if (!mz_zip_reader_init_internal(pZip, flags))
5007 return MZ_FALSE;
5008 pZip->m_archive_size = size;
5009 pZip->m_pRead = mz_zip_mem_read_func;
5010 pZip->m_pIO_opaque = pZip;
5011#ifdef __cplusplus
5012 pZip->m_pState->m_pMem = const_cast<void *>(pMem);
5013#else
5014 pZip->m_pState->m_pMem = (void *)pMem;
5015#endif
5016 pZip->m_pState->m_mem_size = size;
5017 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5018 mz_zip_reader_end(pZip);
5019 return MZ_FALSE;
5020 }
5021 return MZ_TRUE;
5022}
5023
5024#ifndef MINIZ_NO_STDIO
5025static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5026 void *pBuf, size_t n) {
5027 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5028 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5029 if (((mz_int64)file_ofs < 0) ||
5030 (((cur_ofs != (mz_int64)file_ofs)) &&
5031 (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5032 return 0;
5033 return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5034}
5035
5036mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5037 mz_uint32 flags) {
5038 mz_uint64 file_size;
5039 MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb");
5040 if (!pFile)
5041 return MZ_FALSE;
5042 if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5043 MZ_FCLOSE(pFile);
5044 return MZ_FALSE;
5045 }
5046 file_size = MZ_FTELL64(pFile);
5047 if (!mz_zip_reader_init_internal(pZip, flags)) {
5048 MZ_FCLOSE(pFile);
5049 return MZ_FALSE;
5050 }
5051 pZip->m_pRead = mz_zip_file_read_func;
5052 pZip->m_pIO_opaque = pZip;
5053 pZip->m_pState->m_pFile = pFile;
5054 pZip->m_archive_size = file_size;
5055 if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5056 mz_zip_reader_end(pZip);
5057 return MZ_FALSE;
5058 }
5059 return MZ_TRUE;
5060}
5061#endif // #ifndef MINIZ_NO_STDIO
5062
5063mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
5064 return pZip ? pZip->m_total_files : 0;
5065}
5066
5067static MZ_FORCEINLINE const mz_uint8 *
5068mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) {
5069 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) ||
5070 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5071 return NULL;
5072 return &MZ_ZIP_ARRAY_ELEMENT(
5073 &pZip->m_pState->m_central_dir, mz_uint8,
5074 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5075 file_index));
5076}
5077
5078mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
5079 mz_uint file_index) {
5080 mz_uint m_bit_flag;
5081 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5082 if (!p)
5083 return MZ_FALSE;
5084 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5085 return (m_bit_flag & 1);
5086}
5087
5088mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
5089 mz_uint file_index) {
5090 mz_uint filename_len, external_attr;
5091 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5092 if (!p)
5093 return MZ_FALSE;
5094
5095 // First see if the filename ends with a '/' character.
5096 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5097 if (filename_len) {
5098 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
5099 return MZ_TRUE;
5100 }
5101
5102 // Bugfix: This code was also checking if the internal attribute was non-zero,
5103 // which wasn't correct. Most/all zip writers (hopefully) set DOS
5104 // file/directory attributes in the low 16-bits, so check for the DOS
5105 // directory flag and ignore the source OS ID in the created by field.
5106 // FIXME: Remove this check? Is it necessary - we already check the filename.
5107 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5108 if ((external_attr & 0x10) != 0)
5109 return MZ_TRUE;
5110
5111 return MZ_FALSE;
5112}
5113
5114mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
5115 mz_zip_archive_file_stat *pStat) {
5116 mz_uint n;
5117 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5118 if ((!p) || (!pStat))
5119 return MZ_FALSE;
5120
5121 // Unpack the central directory record.
5122 pStat->m_file_index = file_index;
5123 pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
5124 &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
5125 pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
5126 pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
5127 pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5128 pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
5129#ifndef MINIZ_NO_TIME
5130 pStat->m_time =
5131 mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
5132 MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
5133#endif
5134 pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
5135 pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5136 pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5137 pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
5138 pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
5139 pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5140
5141 // Copy as much of the filename and comment as possible.
5142 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5143 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
5144 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5145 pStat->m_filename[n] = '\0';
5146
5147 n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5148 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
5149 pStat->m_comment_size = n;
5150 memcpy(pStat->m_comment,
5151 p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5152 MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5153 MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5154 n);
5155 pStat->m_comment[n] = '\0';
5156
5157 return MZ_TRUE;
5158}
5159
5160mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
5161 char *pFilename, mz_uint filename_buf_size) {
5162 mz_uint n;
5163 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5164 if (!p) {
5165 if (filename_buf_size)
5166 pFilename[0] = '\0';
5167 return 0;
5168 }
5169 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5170 if (filename_buf_size) {
5171 n = MZ_MIN(n, filename_buf_size - 1);
5172 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
5173 pFilename[n] = '\0';
5174 }
5175 return n + 1;
5176}
5177
5178static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA,
5179 const char *pB,
5180 mz_uint len,
5181 mz_uint flags) {
5182 mz_uint i;
5183 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
5184 return 0 == memcmp(pA, pB, len);
5185 for (i = 0; i < len; ++i)
5186 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
5187 return MZ_FALSE;
5188 return MZ_TRUE;
5189}
5190
5191static MZ_FORCEINLINE int
5192mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array,
5193 const mz_zip_array *pCentral_dir_offsets,
5194 mz_uint l_index, const char *pR, mz_uint r_len) {
5195 const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5196 pCentral_dir_array, mz_uint8,
5197 MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5198 l_index)),
5199 *pE;
5200 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5201 mz_uint8 l = 0, r = 0;
5202 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5203 pE = pL + MZ_MIN(l_len, r_len);
5204 while (pL < pE) {
5205 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
5206 break;
5207 pL++;
5208 pR++;
5209 }
5210 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
5211}
5212
5213static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip,
5214 const char *pFilename) {
5215 mz_zip_internal_state *pState = pZip->m_pState;
5216 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5217 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5218 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
5219 &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
5220 const int size = pZip->m_total_files;
5221 const mz_uint filename_len = (mz_uint)strlen(pFilename);
5222 int l = 0, h = size - 1;
5223 while (l <= h) {
5224 int m = (l + h) >> 1, file_index = pIndices[m],
5225 comp =
5226 mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets,
5227 file_index, pFilename, filename_len);
5228 if (!comp)
5229 return file_index;
5230 else if (comp < 0)
5231 l = m + 1;
5232 else
5233 h = m - 1;
5234 }
5235 return -1;
5236}
5237
5238int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
5239 const char *pComment, mz_uint flags) {
5240 mz_uint file_index;
5241 size_t name_len, comment_len;
5242 if ((!pZip) || (!pZip->m_pState) || (!pName) ||
5243 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5244 return -1;
5245 if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
5246 (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
5247 return mz_zip_reader_locate_file_binary_search(pZip, pName);
5248 name_len = strlen(pName);
5249 if (name_len > 0xFFFF)
5250 return -1;
5251 comment_len = pComment ? strlen(pComment) : 0;
5252 if (comment_len > 0xFFFF)
5253 return -1;
5254 for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
5255 const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
5256 &pZip->m_pState->m_central_dir, mz_uint8,
5257 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5258 file_index));
5259 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5260 const char *pFilename =
5261 (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5262 if (filename_len < name_len)
5263 continue;
5264 if (comment_len) {
5265 mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
5266 file_comment_len =
5267 MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
5268 const char *pFile_comment = pFilename + filename_len + file_extra_len;
5269 if ((file_comment_len != comment_len) ||
5270 (!mz_zip_reader_string_equal(pComment, pFile_comment,
5271 file_comment_len, flags)))
5272 continue;
5273 }
5274 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
5275 int ofs = filename_len - 1;
5276 do {
5277 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
5278 (pFilename[ofs] == ':'))
5279 break;
5280 } while (--ofs >= 0);
5281 ofs++;
5282 pFilename += ofs;
5283 filename_len -= ofs;
5284 }
5285 if ((filename_len == name_len) &&
5286 (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags)))
5287 return file_index;
5288 }
5289 return -1;
5290}
5291
5292mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
5293 mz_uint file_index, void *pBuf,
5294 size_t buf_size, mz_uint flags,
5295 void *pUser_read_buf,
5296 size_t user_read_buf_size) {
5297 int status = TINFL_STATUS_DONE;
5298 mz_uint64 needed_size, cur_file_ofs, comp_remaining,
5299 out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
5300 mz_zip_archive_file_stat file_stat;
5301 void *pRead_buf;
5302 mz_uint32
5303 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5304 sizeof(mz_uint32)];
5305 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5306 tinfl_decompressor inflator;
5307
5308 if ((buf_size) && (!pBuf))
5309 return MZ_FALSE;
5310
5311 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5312 return MZ_FALSE;
5313
5314 // Empty file, or a directory (but not always a directory - I've seen odd zips
5315 // with directories that have compressed data which inflates to 0 bytes)
5316 if (!file_stat.m_comp_size)
5317 return MZ_TRUE;
5318
5319 // Entry is a subdirectory (I've seen old zips with dir entries which have
5320 // compressed deflate data which inflates to 0 bytes, but these entries claim
5321 // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5322 // case - should it fail instead?
5323 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5324 return MZ_TRUE;
5325
5326 // Encryption and patch files are not supported.
5327 if (file_stat.m_bit_flag & (1 | 32))
5328 return MZ_FALSE;
5329
5330 // This function only supports stored and deflate.
5331 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5332 (file_stat.m_method != MZ_DEFLATED))
5333 return MZ_FALSE;
5334
5335 // Ensure supplied output buffer is large enough.
5336 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
5337 : file_stat.m_uncomp_size;
5338 if (buf_size < needed_size)
5339 return MZ_FALSE;
5340
5341 // Read and parse the local directory entry.
5342 cur_file_ofs = file_stat.m_local_header_ofs;
5343 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5344 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5345 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5346 return MZ_FALSE;
5347 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5348 return MZ_FALSE;
5349
5350 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5351 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5352 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5353 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5354 return MZ_FALSE;
5355
5356 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5357 // The file is stored or the caller has requested the compressed data.
5358 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5359 (size_t)needed_size) != needed_size)
5360 return MZ_FALSE;
5361 return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) ||
5362 (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5363 (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32);
5364 }
5365
5366 // Decompress the file either directly from memory or from a file input
5367 // buffer.
5368 tinfl_init(&inflator);
5369
5370 if (pZip->m_pState->m_pMem) {
5371 // Read directly from the archive in memory.
5372 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5373 read_buf_size = read_buf_avail = file_stat.m_comp_size;
5374 comp_remaining = 0;
5375 } else if (pUser_read_buf) {
5376 // Use a user provided read buffer.
5377 if (!user_read_buf_size)
5378 return MZ_FALSE;
5379 pRead_buf = (mz_uint8 *)pUser_read_buf;
5380 read_buf_size = user_read_buf_size;
5381 read_buf_avail = 0;
5382 comp_remaining = file_stat.m_comp_size;
5383 } else {
5384 // Temporarily allocate a read buffer.
5385 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5386 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
5387 return MZ_FALSE;
5388
5389 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5390 (size_t)read_buf_size)))
5391 return MZ_FALSE;
5392 read_buf_avail = 0;
5393 comp_remaining = file_stat.m_comp_size;
5394 }
5395
5396 do {
5397 size_t in_buf_size,
5398 out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
5399 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5400 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5401 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5402 (size_t)read_buf_avail) != read_buf_avail) {
5403 status = TINFL_STATUS_FAILED;
5404 break;
5405 }
5406 cur_file_ofs += read_buf_avail;
5407 comp_remaining -= read_buf_avail;
5408 read_buf_ofs = 0;
5409 }
5410 in_buf_size = (size_t)read_buf_avail;
5411 status = tinfl_decompress(
5412 &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5413 (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
5414 TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
5415 (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
5416 read_buf_avail -= in_buf_size;
5417 read_buf_ofs += in_buf_size;
5418 out_buf_ofs += out_buf_size;
5419 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
5420
5421 if (status == TINFL_STATUS_DONE) {
5422 // Make sure the entire file was decompressed, and check its CRC.
5423 if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5424 (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
5425 (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32))
5426 status = TINFL_STATUS_FAILED;
5427 }
5428
5429 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
5430 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5431
5432 return status == TINFL_STATUS_DONE;
5433}
5434
5435mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
5436 mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
5437 mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
5438 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5439 if (file_index < 0)
5440 return MZ_FALSE;
5441 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5442 flags, pUser_read_buf,
5443 user_read_buf_size);
5444}
5445
5446mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
5447 void *pBuf, size_t buf_size,
5448 mz_uint flags) {
5449 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
5450 flags, NULL, 0);
5451}
5452
5453mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
5454 const char *pFilename, void *pBuf,
5455 size_t buf_size, mz_uint flags) {
5456 return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
5457 buf_size, flags, NULL, 0);
5458}
5459
5460void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
5461 size_t *pSize, mz_uint flags) {
5462 mz_uint64 comp_size, uncomp_size, alloc_size;
5463 const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index);
5464 void *pBuf;
5465
5466 if (pSize)
5467 *pSize = 0;
5468 if (!p)
5469 return NULL;
5470
5471 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5472 uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5473
5474 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
5475 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
5476 return NULL;
5477 if (NULL ==
5478 (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
5479 return NULL;
5480
5481 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
5482 flags)) {
5483 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
5484 return NULL;
5485 }
5486
5487 if (pSize)
5488 *pSize = (size_t)alloc_size;
5489 return pBuf;
5490}
5491
5492void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
5493 const char *pFilename, size_t *pSize,
5494 mz_uint flags) {
5495 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5496 if (file_index < 0) {
5497 if (pSize)
5498 *pSize = 0;
5499 return MZ_FALSE;
5500 }
5501 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
5502}
5503
5504mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
5505 mz_uint file_index,
5506 mz_file_write_func pCallback,
5507 void *pOpaque, mz_uint flags) {
5508 int status = TINFL_STATUS_DONE;
5509 mz_uint file_crc32 = MZ_CRC32_INIT;
5510 mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
5511 out_buf_ofs = 0, cur_file_ofs;
5512 mz_zip_archive_file_stat file_stat;
5513 void *pRead_buf = NULL;
5514 void *pWrite_buf = NULL;
5515 mz_uint32
5516 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5517 sizeof(mz_uint32)];
5518 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5519
5520 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5521 return MZ_FALSE;
5522
5523 // Empty file, or a directory (but not always a directory - I've seen odd zips
5524 // with directories that have compressed data which inflates to 0 bytes)
5525 if (!file_stat.m_comp_size)
5526 return MZ_TRUE;
5527
5528 // Entry is a subdirectory (I've seen old zips with dir entries which have
5529 // compressed deflate data which inflates to 0 bytes, but these entries claim
5530 // to uncompress to 512 bytes in the headers). I'm torn how to handle this
5531 // case - should it fail instead?
5532 if (mz_zip_reader_is_file_a_directory(pZip, file_index))
5533 return MZ_TRUE;
5534
5535 // Encryption and patch files are not supported.
5536 if (file_stat.m_bit_flag & (1 | 32))
5537 return MZ_FALSE;
5538
5539 // This function only supports stored and deflate.
5540 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
5541 (file_stat.m_method != MZ_DEFLATED))
5542 return MZ_FALSE;
5543
5544 // Read and parse the local directory entry.
5545 cur_file_ofs = file_stat.m_local_header_ofs;
5546 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
5547 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
5548 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5549 return MZ_FALSE;
5550 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5551 return MZ_FALSE;
5552
5553 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
5554 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
5555 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5556 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
5557 return MZ_FALSE;
5558
5559 // Decompress the file either directly from memory or from a file input
5560 // buffer.
5561 if (pZip->m_pState->m_pMem) {
5562 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
5563 read_buf_size = read_buf_avail = file_stat.m_comp_size;
5564 comp_remaining = 0;
5565 } else {
5566 read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5567 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5568 (size_t)read_buf_size)))
5569 return MZ_FALSE;
5570 read_buf_avail = 0;
5571 comp_remaining = file_stat.m_comp_size;
5572 }
5573
5574 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
5575 // The file is stored or the caller has requested the compressed data.
5576 if (pZip->m_pState->m_pMem) {
5577 if (((sizeof(size_t) == sizeof(mz_uint32))) &&
5578 (file_stat.m_comp_size > 0xFFFFFFFF))
5579 return MZ_FALSE;
5580
5581 if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5582 (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
5583 status = TINFL_STATUS_FAILED;
5584 else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5585 file_crc32 =
5586 (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
5587 (size_t)file_stat.m_comp_size);
5588 // cur_file_ofs += file_stat.m_comp_size;
5589 out_buf_ofs += file_stat.m_comp_size;
5590 // comp_remaining = 0;
5591 } else {
5592 while (comp_remaining) {
5593 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5594 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5595 (size_t)read_buf_avail) != read_buf_avail) {
5596 status = TINFL_STATUS_FAILED;
5597 break;
5598 }
5599
5600 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5601 file_crc32 = (mz_uint32)mz_crc32(
5602 file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
5603
5604 if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
5605 (size_t)read_buf_avail) != read_buf_avail) {
5606 status = TINFL_STATUS_FAILED;
5607 break;
5608 }
5609 cur_file_ofs += read_buf_avail;
5610 out_buf_ofs += read_buf_avail;
5611 comp_remaining -= read_buf_avail;
5612 }
5613 }
5614 } else {
5615 tinfl_decompressor inflator;
5616 tinfl_init(&inflator);
5617
5618 if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
5619 TINFL_LZ_DICT_SIZE)))
5620 status = TINFL_STATUS_FAILED;
5621 else {
5622 do {
5623 mz_uint8 *pWrite_buf_cur =
5624 (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5625 size_t in_buf_size,
5626 out_buf_size =
5627 TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5628 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
5629 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
5630 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
5631 (size_t)read_buf_avail) != read_buf_avail) {
5632 status = TINFL_STATUS_FAILED;
5633 break;
5634 }
5635 cur_file_ofs += read_buf_avail;
5636 comp_remaining -= read_buf_avail;
5637 read_buf_ofs = 0;
5638 }
5639
5640 in_buf_size = (size_t)read_buf_avail;
5641 status = tinfl_decompress(
5642 &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
5643 (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
5644 comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5645 read_buf_avail -= in_buf_size;
5646 read_buf_ofs += in_buf_size;
5647
5648 if (out_buf_size) {
5649 if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
5650 out_buf_size) {
5651 status = TINFL_STATUS_FAILED;
5652 break;
5653 }
5654 file_crc32 =
5655 (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
5656 if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
5657 status = TINFL_STATUS_FAILED;
5658 break;
5659 }
5660 }
5661 } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
5662 (status == TINFL_STATUS_HAS_MORE_OUTPUT));
5663 }
5664 }
5665
5666 if ((status == TINFL_STATUS_DONE) &&
5667 (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
5668 // Make sure the entire file was decompressed, and check its CRC.
5669 if ((out_buf_ofs != file_stat.m_uncomp_size) ||
5670 (file_crc32 != file_stat.m_crc32))
5671 status = TINFL_STATUS_FAILED;
5672 }
5673
5674 if (!pZip->m_pState->m_pMem)
5675 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
5676 if (pWrite_buf)
5677 pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
5678
5679 return status == TINFL_STATUS_DONE;
5680}
5681
5682mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
5683 const char *pFilename,
5684 mz_file_write_func pCallback,
5685 void *pOpaque, mz_uint flags) {
5686 int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags);
5687 if (file_index < 0)
5688 return MZ_FALSE;
5689 return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
5690 flags);
5691}
5692
5693#ifndef MINIZ_NO_STDIO
5694static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
5695 const void *pBuf, size_t n) {
5696 (void)ofs;
5697 return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5698}
5699
5700mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
5701 const char *pDst_filename,
5702 mz_uint flags) {
5703 mz_bool status;
5704 mz_zip_archive_file_stat file_stat;
5705 MZ_FILE *pFile;
5706 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5707 return MZ_FALSE;
5708
5709 pFile = MZ_FOPEN(pDst_filename, "wb");
5710 if (!pFile)
5711 return MZ_FALSE;
5712 status = mz_zip_reader_extract_to_callback(
5713 pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5714 if (MZ_FCLOSE(pFile) == EOF)
5715 return MZ_FALSE;
5716#ifndef MINIZ_NO_TIME
5717 if (status) {
5718 mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5719 }
5720#endif
5721
5722 return status;
5723}
5724#endif // #ifndef MINIZ_NO_STDIO
5725
5726mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5727 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5728 (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5729 return MZ_FALSE;
5730
5731 mz_zip_internal_state *pState = pZip->m_pState;
5732 pZip->m_pState = NULL;
5733 mz_zip_array_clear(pZip, &pState->m_central_dir);
5734 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5735 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5736
5737#ifndef MINIZ_NO_STDIO
5738 if (pState->m_pFile) {
5739 MZ_FCLOSE(pState->m_pFile);
5740 pState->m_pFile = NULL;
5741 }
5742#endif // #ifndef MINIZ_NO_STDIO
5743
5744 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5745
5746 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5747
5748 return MZ_TRUE;
5749}
5750
5751#ifndef MINIZ_NO_STDIO
5752mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
5753 const char *pArchive_filename,
5754 const char *pDst_filename,
5755 mz_uint flags) {
5756 int file_index =
5757 mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags);
5758 if (file_index < 0)
5759 return MZ_FALSE;
5760 return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5761}
5762#endif
5763
5764// ------------------- .ZIP archive writing
5765
5766#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5767
5768static void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
5769 p[0] = (mz_uint8)v;
5770 p[1] = (mz_uint8)(v >> 8);
5771}
5772static void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
5773 p[0] = (mz_uint8)v;
5774 p[1] = (mz_uint8)(v >> 8);
5775 p[2] = (mz_uint8)(v >> 16);
5776 p[3] = (mz_uint8)(v >> 24);
5777}
5778#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5779#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5780
5781mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
5782 if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
5783 (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5784 return MZ_FALSE;
5785
5786 if (pZip->m_file_offset_alignment) {
5787 // Ensure user specified file offset alignment is a power of 2.
5788 if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5789 return MZ_FALSE;
5790 }
5791
5792 if (!pZip->m_pAlloc)
5793 pZip->m_pAlloc = def_alloc_func;
5794 if (!pZip->m_pFree)
5795 pZip->m_pFree = def_free_func;
5796 if (!pZip->m_pRealloc)
5797 pZip->m_pRealloc = def_realloc_func;
5798
5799 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5800 pZip->m_archive_size = existing_size;
5801 pZip->m_central_directory_file_ofs = 0;
5802 pZip->m_total_files = 0;
5803
5804 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5805 pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5806 return MZ_FALSE;
5807 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5808 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5809 sizeof(mz_uint8));
5810 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5811 sizeof(mz_uint32));
5812 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5813 sizeof(mz_uint32));
5814 return MZ_TRUE;
5815}
5816
5817static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
5818 const void *pBuf, size_t n) {
5819 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5820 mz_zip_internal_state *pState = pZip->m_pState;
5821 mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5822
5823 if ((!n) ||
5824 ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)))
5825 return 0;
5826
5827 if (new_size > pState->m_mem_capacity) {
5828 void *pNew_block;
5829 size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5830 while (new_capacity < new_size)
5831 new_capacity *= 2;
5832 if (NULL == (pNew_block = pZip->m_pRealloc(
5833 pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5834 return 0;
5835 pState->m_pMem = pNew_block;
5836 pState->m_mem_capacity = new_capacity;
5837 }
5838 memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5839 pState->m_mem_size = (size_t)new_size;
5840 return n;
5841}
5842
5843mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
5844 size_t size_to_reserve_at_beginning,
5845 size_t initial_allocation_size) {
5846 pZip->m_pWrite = mz_zip_heap_write_func;
5847 pZip->m_pIO_opaque = pZip;
5848 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5849 return MZ_FALSE;
5850 if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
5851 size_to_reserve_at_beginning))) {
5852 if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
5853 pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
5854 mz_zip_writer_end(pZip);
5855 return MZ_FALSE;
5856 }
5857 pZip->m_pState->m_mem_capacity = initial_allocation_size;
5858 }
5859 return MZ_TRUE;
5860}
5861
5862#ifndef MINIZ_NO_STDIO
5863static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
5864 const void *pBuf, size_t n) {
5865 mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5866 mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5867 if (((mz_int64)file_ofs < 0) ||
5868 (((cur_ofs != (mz_int64)file_ofs)) &&
5869 (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5870 return 0;
5871 return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5872}
5873
5874mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
5875 mz_uint64 size_to_reserve_at_beginning) {
5876 MZ_FILE *pFile;
5877 pZip->m_pWrite = mz_zip_file_write_func;
5878 pZip->m_pIO_opaque = pZip;
5879 if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning))
5880 return MZ_FALSE;
5881 if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) {
5882 mz_zip_writer_end(pZip);
5883 return MZ_FALSE;
5884 }
5885 pZip->m_pState->m_pFile = pFile;
5886 if (size_to_reserve_at_beginning) {
5887 mz_uint64 cur_ofs = 0;
5888 char buf[4096];
5889 MZ_CLEAR_OBJ(buf);
5890 do {
5891 size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5892 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
5893 mz_zip_writer_end(pZip);
5894 return MZ_FALSE;
5895 }
5896 cur_ofs += n;
5897 size_to_reserve_at_beginning -= n;
5898 } while (size_to_reserve_at_beginning);
5899 }
5900 return MZ_TRUE;
5901}
5902#endif // #ifndef MINIZ_NO_STDIO
5903
5904mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
5905 const char *pFilename) {
5906 mz_zip_internal_state *pState;
5907 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5908 return MZ_FALSE;
5909 // No sense in trying to write to an archive that's already at the support max
5910 // size
5911 if ((pZip->m_total_files == 0xFFFF) ||
5912 ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5913 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
5914 return MZ_FALSE;
5915
5916 pState = pZip->m_pState;
5917
5918 if (pState->m_pFile) {
5919#ifdef MINIZ_NO_STDIO
5920 pFilename;
5921 return MZ_FALSE;
5922#else
5923 // Archive is being read from stdio - try to reopen as writable.
5924 if (pZip->m_pIO_opaque != pZip)
5925 return MZ_FALSE;
5926 if (!pFilename)
5927 return MZ_FALSE;
5928 pZip->m_pWrite = mz_zip_file_write_func;
5929 if (NULL ==
5930 (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
5931 // The mz_zip_archive is now in a bogus state because pState->m_pFile is
5932 // NULL, so just close it.
5933 mz_zip_reader_end(pZip);
5934 return MZ_FALSE;
5935 }
5936#endif // #ifdef MINIZ_NO_STDIO
5937 } else if (pState->m_pMem) {
5938 // Archive lives in a memory block. Assume it's from the heap that we can
5939 // resize using the realloc callback.
5940 if (pZip->m_pIO_opaque != pZip)
5941 return MZ_FALSE;
5942 pState->m_mem_capacity = pState->m_mem_size;
5943 pZip->m_pWrite = mz_zip_heap_write_func;
5944 }
5945 // Archive is being read via a user provided read function - make sure the
5946 // user has specified a write function too.
5947 else if (!pZip->m_pWrite)
5948 return MZ_FALSE;
5949
5950 // Start writing new files at the archive's current central directory
5951 // location.
5952 pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5953 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5954 pZip->m_central_directory_file_ofs = 0;
5955
5956 return MZ_TRUE;
5957}
5958
5959mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
5960 const void *pBuf, size_t buf_size,
5961 mz_uint level_and_flags) {
5962 return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
5963 level_and_flags, 0, 0);
5964}
5965
5966typedef struct {
5967 mz_zip_archive *m_pZip;
5968 mz_uint64 m_cur_archive_file_ofs;
5969 mz_uint64 m_comp_size;
5971
5972static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
5973 void *pUser) {
5975 if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
5976 pState->m_cur_archive_file_ofs, pBuf,
5977 len) != len)
5978 return MZ_FALSE;
5979 pState->m_cur_archive_file_ofs += len;
5980 pState->m_comp_size += len;
5981 return MZ_TRUE;
5982}
5983
5984static mz_bool mz_zip_writer_create_local_dir_header(
5985 mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
5986 mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
5987 mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
5988 mz_uint16 dos_time, mz_uint16 dos_date) {
5989 (void)pZip;
5990 memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5991 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5992 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5993 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5994 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5995 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5996 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5997 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5998 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size);
5999 MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6000 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6001 MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6002 return MZ_TRUE;
6003}
6004
6005static mz_bool mz_zip_writer_create_central_dir_header(
6006 mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
6007 mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
6008 mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
6009 mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6010 mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
6011 (void)pZip;
6012 mz_uint16 version_made_by = 10 * MZ_VER_MAJOR + MZ_VER_MINOR;
6013 version_made_by |= (MZ_PLATFORM << 8);
6014
6015 memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6016 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6017 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, version_made_by);
6018 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6019 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6020 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6021 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6022 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6023 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6024 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size);
6025 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size);
6026 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6027 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6028 MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6029 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6030 MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs);
6031 return MZ_TRUE;
6032}
6033
6034static mz_bool mz_zip_writer_add_to_central_dir(
6035 mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6036 const void *pExtra, mz_uint16 extra_size, const void *pComment,
6037 mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
6038 mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
6039 mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
6040 mz_uint32 ext_attributes) {
6041 mz_zip_internal_state *pState = pZip->m_pState;
6042 mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6043 size_t orig_central_dir_size = pState->m_central_dir.m_size;
6044 mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6045
6046 // No zip64 support yet
6047 if ((local_header_ofs > 0xFFFFFFFF) ||
6048 (((mz_uint64)pState->m_central_dir.m_size +
6049 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
6050 comment_size) > 0xFFFFFFFF))
6051 return MZ_FALSE;
6052
6053 if (!mz_zip_writer_create_central_dir_header(
6054 pZip, central_dir_header, filename_size, extra_size, comment_size,
6055 uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
6056 dos_date, local_header_ofs, ext_attributes))
6057 return MZ_FALSE;
6058
6059 if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
6060 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6061 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
6062 filename_size)) ||
6063 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
6064 extra_size)) ||
6065 (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
6066 comment_size)) ||
6067 (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
6068 &central_dir_ofs, 1))) {
6069 // Try to push the central directory array back into its original state.
6070 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6071 MZ_FALSE);
6072 return MZ_FALSE;
6073 }
6074
6075 return MZ_TRUE;
6076}
6077
6078static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
6079 // Basic ZIP archive filename validity checks: Valid filenames cannot start
6080 // with a forward slash, cannot contain a drive letter, and cannot use
6081 // DOS-style backward slashes.
6082 if (*pArchive_name == '/')
6083 return MZ_FALSE;
6084 while (*pArchive_name) {
6085 if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
6086 return MZ_FALSE;
6087 pArchive_name++;
6088 }
6089 return MZ_TRUE;
6090}
6091
6092static mz_uint
6093mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
6094 mz_uint32 n;
6095 if (!pZip->m_file_offset_alignment)
6096 return 0;
6097 n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6098 return (pZip->m_file_offset_alignment - n) &
6099 (pZip->m_file_offset_alignment - 1);
6100}
6101
6102static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
6103 mz_uint64 cur_file_ofs, mz_uint32 n) {
6104 char buf[4096];
6105 memset(buf, 0, MZ_MIN(sizeof(buf), n));
6106 while (n) {
6107 mz_uint32 s = MZ_MIN(sizeof(buf), n);
6108 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6109 return MZ_FALSE;
6110 cur_file_ofs += s;
6111 n -= s;
6112 }
6113 return MZ_TRUE;
6114}
6115
6116mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
6117 const char *pArchive_name, const void *pBuf,
6118 size_t buf_size, const void *pComment,
6119 mz_uint16 comment_size,
6120 mz_uint level_and_flags, mz_uint64 uncomp_size,
6121 mz_uint32 uncomp_crc32) {
6122 mz_uint32 ext_attributes = 0;
6123 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6124 mz_uint level, num_alignment_padding_bytes;
6125 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0;
6126 size_t archive_name_size;
6127 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6128 tdefl_compressor *pComp = NULL;
6129 mz_bool store_data_uncompressed;
6130 mz_zip_internal_state *pState;
6131
6132 if ((int)level_and_flags < 0)
6133 level_and_flags = MZ_DEFAULT_LEVEL;
6134 level = level_and_flags & 0xF;
6135 store_data_uncompressed =
6136 ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6137
6138 if ((!pZip) || (!pZip->m_pState) ||
6139 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
6140 (!pArchive_name) || ((comment_size) && (!pComment)) ||
6141 (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION))
6142 return MZ_FALSE;
6143
6144 local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6145 pState = pZip->m_pState;
6146
6147 if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6148 return MZ_FALSE;
6149 // No zip64 support yet
6150 if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6151 return MZ_FALSE;
6152 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6153 return MZ_FALSE;
6154
6155#ifndef MINIZ_NO_TIME
6156 {
6157 time_t cur_time;
6158 time(&cur_time);
6159 mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6160 }
6161#endif // #ifndef MINIZ_NO_TIME
6162
6163 archive_name_size = strlen(pArchive_name);
6164 if (archive_name_size > 0xFFFF)
6165 return MZ_FALSE;
6166
6167 num_alignment_padding_bytes =
6168 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6169
6170 // no zip64 support yet
6171 if ((pZip->m_total_files == 0xFFFF) ||
6172 ((pZip->m_archive_size + num_alignment_padding_bytes +
6173 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6174 comment_size + archive_name_size) > 0xFFFFFFFF))
6175 return MZ_FALSE;
6176
6177 if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
6178 // Set DOS Subdirectory attribute bit.
6179 ext_attributes |= 0x10;
6180 // Subdirectories cannot contain data.
6181 if ((buf_size) || (uncomp_size))
6182 return MZ_FALSE;
6183 }
6184
6185 // Try to do any allocations before writing to the archive, so if an
6186 // allocation fails the file remains unmodified. (A good idea if we're doing
6187 // an in-place modification.)
6188 if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir,
6189 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6190 archive_name_size + comment_size)) ||
6191 (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6192 return MZ_FALSE;
6193
6194 if ((!store_data_uncompressed) && (buf_size)) {
6195 if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
6196 pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6197 return MZ_FALSE;
6198 }
6199
6200 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6201 num_alignment_padding_bytes +
6202 sizeof(local_dir_header))) {
6203 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6204 return MZ_FALSE;
6205 }
6206 local_dir_header_ofs += num_alignment_padding_bytes;
6207 if (pZip->m_file_offset_alignment) {
6208 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6209 0);
6210 }
6211 cur_archive_file_ofs +=
6212 num_alignment_padding_bytes + sizeof(local_dir_header);
6213
6214 MZ_CLEAR_OBJ(local_dir_header);
6215 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6216 archive_name_size) != archive_name_size) {
6217 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6218 return MZ_FALSE;
6219 }
6220 cur_archive_file_ofs += archive_name_size;
6221
6222 if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6223 uncomp_crc32 =
6224 (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6225 uncomp_size = buf_size;
6226 if (uncomp_size <= 3) {
6227 level = 0;
6228 store_data_uncompressed = MZ_TRUE;
6229 }
6230 }
6231
6232 if (store_data_uncompressed) {
6233 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
6234 buf_size) != buf_size) {
6235 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6236 return MZ_FALSE;
6237 }
6238
6239 cur_archive_file_ofs += buf_size;
6240 comp_size = buf_size;
6241
6242 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6243 method = MZ_DEFLATED;
6244 } else if (buf_size) {
6246
6247 state.m_pZip = pZip;
6248 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6249 state.m_comp_size = 0;
6250
6251 if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6252 tdefl_create_comp_flags_from_zip_params(
6253 level, -15, MZ_DEFAULT_STRATEGY)) !=
6254 TDEFL_STATUS_OKAY) ||
6255 (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
6256 TDEFL_STATUS_DONE)) {
6257 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6258 return MZ_FALSE;
6259 }
6260
6261 comp_size = state.m_comp_size;
6262 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6263
6264 method = MZ_DEFLATED;
6265 }
6266
6267 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6268 pComp = NULL;
6269
6270 // no zip64 support yet
6271 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6272 return MZ_FALSE;
6273
6274 if (!mz_zip_writer_create_local_dir_header(
6275 pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6276 comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6277 return MZ_FALSE;
6278
6279 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6280 sizeof(local_dir_header)) != sizeof(local_dir_header))
6281 return MZ_FALSE;
6282
6283 if (!mz_zip_writer_add_to_central_dir(
6284 pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6285 comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6286 dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6287 return MZ_FALSE;
6288
6289 pZip->m_total_files++;
6290 pZip->m_archive_size = cur_archive_file_ofs;
6291
6292 return MZ_TRUE;
6293}
6294
6295#ifndef MINIZ_NO_STDIO
6296mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
6297 const char *pSrc_filename, const void *pComment,
6298 mz_uint16 comment_size, mz_uint level_and_flags,
6299 mz_uint32 ext_attributes) {
6300 mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6301 mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6302#ifndef MINIZ_NO_TIME
6303 time_t file_modified_time;
6304#endif
6305
6306 mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
6307 comp_size = 0;
6308 size_t archive_name_size;
6309 mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6310 MZ_FILE *pSrc_file = NULL;
6311
6312 if ((int)level_and_flags < 0)
6313 level_and_flags = MZ_DEFAULT_LEVEL;
6314 level = level_and_flags & 0xF;
6315
6316 if ((!pZip) || (!pZip->m_pState) ||
6317 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
6318 ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6319 return MZ_FALSE;
6320
6321 local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size;
6322
6323 if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6324 return MZ_FALSE;
6325 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6326 return MZ_FALSE;
6327
6328 archive_name_size = strlen(pArchive_name);
6329 if (archive_name_size > 0xFFFF)
6330 return MZ_FALSE;
6331
6332 num_alignment_padding_bytes =
6333 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6334
6335 // no zip64 support yet
6336 if ((pZip->m_total_files == 0xFFFF) ||
6337 ((pZip->m_archive_size + num_alignment_padding_bytes +
6338 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6339 comment_size + archive_name_size) > 0xFFFFFFFF))
6340 return MZ_FALSE;
6341
6342#ifndef MINIZ_NO_TIME
6343 memset(&file_modified_time, 0, sizeof(file_modified_time));
6344 if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6345 return MZ_FALSE;
6346 mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
6347#endif
6348
6349 pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6350 if (!pSrc_file)
6351 return MZ_FALSE;
6352 MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6353 uncomp_size = MZ_FTELL64(pSrc_file);
6354 MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6355
6356 if (uncomp_size > 0xFFFFFFFF) {
6357 // No zip64 support yet
6358 MZ_FCLOSE(pSrc_file);
6359 return MZ_FALSE;
6360 }
6361 if (uncomp_size <= 3)
6362 level = 0;
6363
6364 if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
6365 num_alignment_padding_bytes +
6366 sizeof(local_dir_header))) {
6367 MZ_FCLOSE(pSrc_file);
6368 return MZ_FALSE;
6369 }
6370 local_dir_header_ofs += num_alignment_padding_bytes;
6371 if (pZip->m_file_offset_alignment) {
6372 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6373 0);
6374 }
6375 cur_archive_file_ofs +=
6376 num_alignment_padding_bytes + sizeof(local_dir_header);
6377
6378 MZ_CLEAR_OBJ(local_dir_header);
6379 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
6380 archive_name_size) != archive_name_size) {
6381 MZ_FCLOSE(pSrc_file);
6382 return MZ_FALSE;
6383 }
6384 cur_archive_file_ofs += archive_name_size;
6385
6386 if (uncomp_size) {
6387 mz_uint64 uncomp_remaining = uncomp_size;
6388 void *pRead_buf =
6389 pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6390 if (!pRead_buf) {
6391 MZ_FCLOSE(pSrc_file);
6392 return MZ_FALSE;
6393 }
6394
6395 if (!level) {
6396 while (uncomp_remaining) {
6397 mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6398 if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) ||
6399 (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
6400 n) != n)) {
6401 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6402 MZ_FCLOSE(pSrc_file);
6403 return MZ_FALSE;
6404 }
6405 uncomp_crc32 =
6406 (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6407 uncomp_remaining -= n;
6408 cur_archive_file_ofs += n;
6409 }
6410 comp_size = uncomp_size;
6411 } else {
6412 mz_bool result = MZ_FALSE;
6414 tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
6415 pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6416 if (!pComp) {
6417 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6418 MZ_FCLOSE(pSrc_file);
6419 return MZ_FALSE;
6420 }
6421
6422 state.m_pZip = pZip;
6423 state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6424 state.m_comp_size = 0;
6425
6426 if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
6427 tdefl_create_comp_flags_from_zip_params(
6428 level, -15, MZ_DEFAULT_STRATEGY)) !=
6429 TDEFL_STATUS_OKAY) {
6430 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6431 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6432 MZ_FCLOSE(pSrc_file);
6433 return MZ_FALSE;
6434 }
6435
6436 for (;;) {
6437 size_t in_buf_size =
6438 (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE);
6439 tdefl_status status;
6440
6441 if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6442 break;
6443
6444 uncomp_crc32 = (mz_uint32)mz_crc32(
6445 uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6446 uncomp_remaining -= in_buf_size;
6447
6448 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size,
6449 uncomp_remaining ? TDEFL_NO_FLUSH
6450 : TDEFL_FINISH);
6451 if (status == TDEFL_STATUS_DONE) {
6452 result = MZ_TRUE;
6453 break;
6454 } else if (status != TDEFL_STATUS_OKAY)
6455 break;
6456 }
6457
6458 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6459
6460 if (!result) {
6461 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6462 MZ_FCLOSE(pSrc_file);
6463 return MZ_FALSE;
6464 }
6465
6466 comp_size = state.m_comp_size;
6467 cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6468
6469 method = MZ_DEFLATED;
6470 }
6471
6472 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6473 }
6474
6475 MZ_FCLOSE(pSrc_file);
6476 pSrc_file = NULL;
6477
6478 // no zip64 support yet
6479 if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF))
6480 return MZ_FALSE;
6481
6482 if (!mz_zip_writer_create_local_dir_header(
6483 pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size,
6484 comp_size, uncomp_crc32, method, 0, dos_time, dos_date))
6485 return MZ_FALSE;
6486
6487 if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header,
6488 sizeof(local_dir_header)) != sizeof(local_dir_header))
6489 return MZ_FALSE;
6490
6491 if (!mz_zip_writer_add_to_central_dir(
6492 pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment,
6493 comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0,
6494 dos_time, dos_date, local_dir_header_ofs, ext_attributes))
6495 return MZ_FALSE;
6496
6497 pZip->m_total_files++;
6498 pZip->m_archive_size = cur_archive_file_ofs;
6499
6500 return MZ_TRUE;
6501}
6502#endif // #ifndef MINIZ_NO_STDIO
6503
6504mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
6505 mz_zip_archive *pSource_zip,
6506 mz_uint file_index) {
6507 mz_uint n, bit_flags, num_alignment_padding_bytes;
6508 mz_uint64 comp_bytes_remaining, local_dir_header_ofs;
6509 mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6510 mz_uint32
6511 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6512 sizeof(mz_uint32)];
6513 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6514 mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6515 size_t orig_central_dir_size;
6516 mz_zip_internal_state *pState;
6517 void *pBuf;
6518 const mz_uint8 *pSrc_central_header;
6519
6520 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6521 return MZ_FALSE;
6522 if (NULL ==
6523 (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index)))
6524 return MZ_FALSE;
6525 pState = pZip->m_pState;
6526
6527 num_alignment_padding_bytes =
6528 mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6529
6530 // no zip64 support yet
6531 if ((pZip->m_total_files == 0xFFFF) ||
6532 ((pZip->m_archive_size + num_alignment_padding_bytes +
6533 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) >
6534 0xFFFFFFFF))
6535 return MZ_FALSE;
6536
6537 cur_src_file_ofs =
6538 MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6539 cur_dst_file_ofs = pZip->m_archive_size;
6540
6541 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
6542 pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6543 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6544 return MZ_FALSE;
6545 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6546 return MZ_FALSE;
6547 cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6548
6549 if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
6550 num_alignment_padding_bytes))
6551 return MZ_FALSE;
6552 cur_dst_file_ofs += num_alignment_padding_bytes;
6553 local_dir_header_ofs = cur_dst_file_ofs;
6554 if (pZip->m_file_offset_alignment) {
6555 MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
6556 0);
6557 }
6558
6559 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
6560 MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6561 MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6562 return MZ_FALSE;
6563 cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6564
6565 n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6566 MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6567 comp_bytes_remaining =
6568 n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6569
6570 if (NULL ==
6571 (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6572 (size_t)MZ_MAX(sizeof(mz_uint32) * 4,
6573 MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE,
6574 comp_bytes_remaining)))))
6575 return MZ_FALSE;
6576
6577 while (comp_bytes_remaining) {
6578 n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining);
6579 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6580 n) != n) {
6581 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6582 return MZ_FALSE;
6583 }
6584 cur_src_file_ofs += n;
6585
6586 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6587 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6588 return MZ_FALSE;
6589 }
6590 cur_dst_file_ofs += n;
6591
6592 comp_bytes_remaining -= n;
6593 }
6594
6595 bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6596 if (bit_flags & 8) {
6597 // Copy data descriptor
6598 if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
6599 sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) {
6600 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6601 return MZ_FALSE;
6602 }
6603
6604 n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3);
6605 if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
6606 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6607 return MZ_FALSE;
6608 }
6609
6610 // cur_src_file_ofs += n;
6611 cur_dst_file_ofs += n;
6612 }
6613 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6614
6615 // no zip64 support yet
6616 if (cur_dst_file_ofs > 0xFFFFFFFF)
6617 return MZ_FALSE;
6618
6619 orig_central_dir_size = pState->m_central_dir.m_size;
6620
6621 memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6622 MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
6623 local_dir_header_ofs);
6624 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header,
6625 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
6626 return MZ_FALSE;
6627
6628 n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6629 MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
6630 MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6631 if (!mz_zip_array_push_back(
6632 pZip, &pState->m_central_dir,
6633 pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) {
6634 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6635 MZ_FALSE);
6636 return MZ_FALSE;
6637 }
6638
6639 if (pState->m_central_dir.m_size > 0xFFFFFFFF)
6640 return MZ_FALSE;
6641 n = (mz_uint32)orig_central_dir_size;
6642 if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
6643 mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
6644 MZ_FALSE);
6645 return MZ_FALSE;
6646 }
6647
6648 pZip->m_total_files++;
6649 pZip->m_archive_size = cur_dst_file_ofs;
6650
6651 return MZ_TRUE;
6652}
6653
6654mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
6655 mz_zip_internal_state *pState;
6656 mz_uint64 central_dir_ofs, central_dir_size;
6657 mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE];
6658
6659 if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
6660 return MZ_FALSE;
6661
6662 pState = pZip->m_pState;
6663
6664 // no zip64 support yet
6665 if ((pZip->m_total_files > 0xFFFF) ||
6666 ((pZip->m_archive_size + pState->m_central_dir.m_size +
6667 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF))
6668 return MZ_FALSE;
6669
6670 central_dir_ofs = 0;
6671 central_dir_size = 0;
6672 if (pZip->m_total_files) {
6673 // Write central directory
6674 central_dir_ofs = pZip->m_archive_size;
6675 central_dir_size = pState->m_central_dir.m_size;
6676 pZip->m_central_directory_file_ofs = central_dir_ofs;
6677 if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
6678 pState->m_central_dir.m_p,
6679 (size_t)central_dir_size) != central_dir_size)
6680 return MZ_FALSE;
6681 pZip->m_archive_size += central_dir_size;
6682 }
6683
6684 // Write end of central directory record
6685 MZ_CLEAR_OBJ(hdr);
6686 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
6687 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
6688 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
6689 pZip->m_total_files);
6690 MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
6691 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size);
6692 MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs);
6693
6694 if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
6695 sizeof(hdr)) != sizeof(hdr))
6696 return MZ_FALSE;
6697#ifndef MINIZ_NO_STDIO
6698 if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
6699 return MZ_FALSE;
6700#endif // #ifndef MINIZ_NO_STDIO
6701
6702 pZip->m_archive_size += sizeof(hdr);
6703
6704 pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
6705 return MZ_TRUE;
6706}
6707
6708mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf,
6709 size_t *pSize) {
6710 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize))
6711 return MZ_FALSE;
6712 if (pZip->m_pWrite != mz_zip_heap_write_func)
6713 return MZ_FALSE;
6714 if (!mz_zip_writer_finalize_archive(pZip))
6715 return MZ_FALSE;
6716
6717 *pBuf = pZip->m_pState->m_pMem;
6718 *pSize = pZip->m_pState->m_mem_size;
6719 pZip->m_pState->m_pMem = NULL;
6720 pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
6721 return MZ_TRUE;
6722}
6723
6724mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
6725 mz_zip_internal_state *pState;
6726 mz_bool status = MZ_TRUE;
6727 if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
6728 ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
6729 (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
6730 return MZ_FALSE;
6731
6732 pState = pZip->m_pState;
6733 pZip->m_pState = NULL;
6734 mz_zip_array_clear(pZip, &pState->m_central_dir);
6735 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
6736 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
6737
6738#ifndef MINIZ_NO_STDIO
6739 if (pState->m_pFile) {
6740 MZ_FCLOSE(pState->m_pFile);
6741 pState->m_pFile = NULL;
6742 }
6743#endif // #ifndef MINIZ_NO_STDIO
6744
6745 if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
6746 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
6747 pState->m_pMem = NULL;
6748 }
6749
6750 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6751 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
6752 return status;
6753}
6754
6755#ifndef MINIZ_NO_STDIO
6756mz_bool mz_zip_add_mem_to_archive_file_in_place(
6757 const char *pZip_filename, const char *pArchive_name, const void *pBuf,
6758 size_t buf_size, const void *pComment, mz_uint16 comment_size,
6759 mz_uint level_and_flags) {
6760 mz_bool status, created_new_archive = MZ_FALSE;
6761 mz_zip_archive zip_archive;
6762 struct MZ_FILE_STAT_STRUCT file_stat;
6763 MZ_CLEAR_OBJ(zip_archive);
6764 if ((int)level_and_flags < 0)
6765 level_and_flags = MZ_DEFAULT_LEVEL;
6766 if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
6767 ((comment_size) && (!pComment)) ||
6768 ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
6769 return MZ_FALSE;
6770 if (!mz_zip_writer_validate_archive_name(pArchive_name))
6771 return MZ_FALSE;
6772 if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
6773 // Create a new archive.
6774 if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0))
6775 return MZ_FALSE;
6776 created_new_archive = MZ_TRUE;
6777 } else {
6778 // Append to an existing archive.
6779 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6780 level_and_flags |
6781 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6782 return MZ_FALSE;
6783 if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) {
6784 mz_zip_reader_end(&zip_archive);
6785 return MZ_FALSE;
6786 }
6787 }
6788 status =
6789 mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
6790 pComment, comment_size, level_and_flags, 0, 0);
6791 // Always finalize, even if adding failed for some reason, so we have a valid
6792 // central directory. (This may not always succeed, but we can try.)
6793 if (!mz_zip_writer_finalize_archive(&zip_archive))
6794 status = MZ_FALSE;
6795 if (!mz_zip_writer_end(&zip_archive))
6796 status = MZ_FALSE;
6797 if ((!status) && (created_new_archive)) {
6798 // It's a new archive and something went wrong, so just delete it.
6799 int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
6800 (void)ignoredStatus;
6801 }
6802 return status;
6803}
6804
6805void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
6806 const char *pArchive_name,
6807 size_t *pSize, mz_uint flags) {
6808 int file_index;
6809 mz_zip_archive zip_archive;
6810 void *p = NULL;
6811
6812 if (pSize)
6813 *pSize = 0;
6814
6815 if ((!pZip_filename) || (!pArchive_name))
6816 return NULL;
6817
6818 MZ_CLEAR_OBJ(zip_archive);
6819 if (!mz_zip_reader_init_file(&zip_archive, pZip_filename,
6820 flags |
6821 MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY))
6822 return NULL;
6823
6824 if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL,
6825 flags)) >= 0)
6826 p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
6827
6828 mz_zip_reader_end(&zip_archive);
6829 return p;
6830}
6831
6832#endif // #ifndef MINIZ_NO_STDIO
6833
6834#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
6835
6836#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
6837
6838#ifdef __cplusplus
6839}
6840#endif
6841
6842#endif // MINIZ_HEADER_FILE_ONLY
6843
6844/*
6845 This is free and unencumbered software released into the public domain.
6846
6847 Anyone is free to copy, modify, publish, use, compile, sell, or
6848 distribute this software, either in source code form or as a compiled
6849 binary, for any purpose, commercial or non-commercial, and by any
6850 means.
6851
6852 In jurisdictions that recognize copyright laws, the author or authors
6853 of this software dedicate any and all copyright interest in the
6854 software to the public domain. We make this dedication for the benefit
6855 of the public at large and to the detriment of our heirs and
6856 successors. We intend this dedication to be an overt act of
6857 relinquishment in perpetuity of all present and future rights to this
6858 software under copyright law.
6859
6860 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
6861 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6862 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6863 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
6864 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
6865 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
6866 OTHER DEALINGS IN THE SOFTWARE.
6867
6868 For more information, please refer to <http://unlicense.org/>
6869*/