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