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