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