/[zanavi_public1]/navit/navit/maptool/miniz.c
ZANavi

Contents of /navit/navit/maptool/miniz.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:executable *

   
Visit the ZANavi Wiki