Atlas - miniz.h

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