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