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