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