miniz.h
author Ozkan Sezer <sezeroz@gmail.com>
Sat, 13 Oct 2018 15:02:56 +0300
changeset 596 4b70bfe18fb7
parent 582 335864e0a7a6
permissions -rw-r--r--
fix build against libpng-1.5.x versions.
slouken@481
     1
/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
slouken@481
     2
   See "unlicense" statement at the end of this file.
slouken@481
     3
   Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013
slouken@481
     4
   Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
slouken@481
     5
slouken@481
     6
   Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define
slouken@481
     7
   MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
slouken@481
     8
slouken@481
     9
   * Change History
slouken@481
    10
     10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!):
slouken@481
    11
       - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug
slouken@481
    12
        would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
slouken@481
    13
        (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
slouken@481
    14
       - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
slouken@481
    15
       - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
slouken@481
    16
         Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
slouken@481
    17
       - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
slouken@481
    18
       - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
slouken@481
    19
       - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
slouken@481
    20
       - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
slouken@481
    21
       - Merged MZ_FORCEINLINE fix from hdeanclark
slouken@481
    22
       - Fix <time.h> include before config #ifdef, thanks emil.brink
slouken@481
    23
       - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
slouken@481
    24
        set it to 1 for real-time compression).
slouken@481
    25
       - Merged in some compiler fixes from paulharris's github repro.
slouken@481
    26
       - Retested this build under Windows (VS 2010, including static analysis), tcc  0.9.26, gcc v4.6 and clang v3.3.
slouken@481
    27
       - Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
slouken@481
    28
       - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
slouken@481
    29
       - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
slouken@481
    30
       - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
slouken@481
    31
     5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
slouken@481
    32
     5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
slouken@481
    33
       - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
slouken@481
    34
       - Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
slouken@481
    35
       - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
slouken@481
    36
        "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
slouken@481
    37
       - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
slouken@481
    38
       - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
slouken@481
    39
       - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
slouken@481
    40
       - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
slouken@481
    41
       - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
slouken@481
    42
     4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
slouken@481
    43
      level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com> for the feedback/bug report.
slouken@481
    44
     5/28/11 v1.11 - Added statement from unlicense.org
slouken@481
    45
     5/27/11 v1.10 - Substantial compressor optimizations:
slouken@481
    46
      - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a
slouken@481
    47
      - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
slouken@481
    48
      - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
slouken@481
    49
      - Refactored the compression code for better readability and maintainability.
slouken@481
    50
      - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large
slouken@481
    51
       drop in throughput on some files).
slouken@481
    52
     5/15/11 v1.09 - Initial stable release.
slouken@481
    53
slouken@481
    54
   * Low-level Deflate/Inflate implementation notes:
slouken@481
    55
slouken@481
    56
     Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or
slouken@481
    57
     greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses
slouken@481
    58
     approximately as well as zlib.
slouken@481
    59
slouken@481
    60
     Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function
slouken@481
    61
     coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory
slouken@481
    62
     block large enough to hold the entire file.
slouken@481
    63
slouken@481
    64
     The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation.
slouken@481
    65
slouken@481
    66
   * zlib-style API notes:
slouken@481
    67
slouken@481
    68
     miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in
slouken@481
    69
     zlib replacement in many apps:
slouken@481
    70
        The z_stream struct, optional memory allocation callbacks
slouken@481
    71
        deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
slouken@481
    72
        inflateInit/inflateInit2/inflate/inflateEnd
slouken@481
    73
        compress, compress2, compressBound, uncompress
slouken@481
    74
        CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines.
slouken@481
    75
        Supports raw deflate streams or standard zlib streams with adler-32 checking.
slouken@481
    76
slouken@481
    77
     Limitations:
slouken@481
    78
      The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries.
slouken@481
    79
      I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but
slouken@481
    80
      there are no guarantees that miniz.c pulls this off perfectly.
slouken@481
    81
slouken@481
    82
   * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by
slouken@481
    83
     Alex Evans. Supports 1-4 bytes/pixel images.
slouken@481
    84
slouken@481
    85
   * ZIP archive API notes:
slouken@481
    86
slouken@481
    87
     The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to
slouken@481
    88
     get the job done with minimal fuss. There are simple API's to retrieve file information, read files from
slouken@481
    89
     existing archives, create new archives, append new files to existing archives, or clone archive data from
slouken@481
    90
     one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h),
slouken@481
    91
     or you can specify custom file read/write callbacks.
slouken@481
    92
slouken@481
    93
     - Archive reading: Just call this function to read a single file from a disk archive:
slouken@481
    94
slouken@481
    95
      void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name,
slouken@481
    96
        size_t *pSize, mz_uint zip_flags);
slouken@481
    97
slouken@481
    98
     For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central
slouken@481
    99
     directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files.
slouken@481
   100
slouken@481
   101
     - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file:
slouken@481
   102
slouken@481
   103
     int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
slouken@481
   104
slouken@481
   105
     The locate operation can optionally check file comments too, which (as one example) can be used to identify
slouken@481
   106
     multiple versions of the same file in an archive. This function uses a simple linear search through the central
slouken@481
   107
     directory, so it's not very fast.
slouken@481
   108
slouken@481
   109
     Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and
slouken@481
   110
     retrieve detailed info on each file by calling mz_zip_reader_file_stat().
slouken@481
   111
slouken@481
   112
     - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data
slouken@481
   113
     to disk and builds an exact image of the central directory in memory. The central directory image is written
slouken@481
   114
     all at once at the end of the archive file when the archive is finalized.
slouken@481
   115
slouken@481
   116
     The archive writer can optionally align each file's local header and file data to any power of 2 alignment,
slouken@481
   117
     which can be useful when the archive will be read from optical media. Also, the writer supports placing
slouken@481
   118
     arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still
slouken@481
   119
     readable by any ZIP tool.
slouken@481
   120
slouken@481
   121
     - Archive appending: The simple way to add a single file to an archive is to call this function:
slouken@481
   122
slouken@481
   123
      mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name,
slouken@481
   124
        const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
slouken@481
   125
slouken@481
   126
     The archive will be created if it doesn't already exist, otherwise it'll be appended to.
slouken@481
   127
     Note the appending is done in-place and is not an atomic operation, so if something goes wrong
slouken@481
   128
     during the operation it's possible the archive could be left without a central directory (although the local
slouken@481
   129
     file headers and file data will be fine, so the archive will be recoverable).
slouken@481
   130
slouken@481
   131
     For more complex archive modification scenarios:
slouken@481
   132
     1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to
slouken@481
   133
     preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the
slouken@481
   134
     compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and
slouken@481
   135
     you're done. This is safe but requires a bunch of temporary disk space or heap memory.
slouken@481
   136
slouken@481
   137
     2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(),
slouken@481
   138
     append new files as needed, then finalize the archive which will write an updated central directory to the
slouken@481
   139
     original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a
slouken@481
   140
     possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
slouken@481
   141
slouken@481
   142
     - ZIP archive support limitations:
slouken@481
   143
     No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
slouken@481
   144
     Requires streams capable of seeking.
slouken@481
   145
slouken@481
   146
   * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
slouken@481
   147
     below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
slouken@481
   148
slouken@481
   149
   * Important: For best perf. be sure to customize the below macros for your target platform:
slouken@481
   150
     #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
slouken@481
   151
     #define MINIZ_LITTLE_ENDIAN 1
slouken@481
   152
     #define MINIZ_HAS_64BIT_REGISTERS 1
slouken@481
   153
slouken@481
   154
   * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz
slouken@481
   155
     uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files
slouken@481
   156
     (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
slouken@481
   157
*/
slouken@481
   158
slouken@481
   159
#ifndef MINIZ_HEADER_INCLUDED
slouken@481
   160
#define MINIZ_HEADER_INCLUDED
slouken@481
   161
slouken@545
   162
/*#include <stdlib.h>*/
slouken@481
   163
slouken@481
   164
// Defines to completely disable specific portions of miniz.c:
slouken@481
   165
// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
slouken@481
   166
slouken@481
   167
// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
slouken@481
   168
#define MINIZ_NO_STDIO
slouken@481
   169
slouken@481
   170
// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
slouken@481
   171
// get/set file times, and the C run-time funcs that get/set times won't be called.
slouken@481
   172
// The current downside is the times written to your archives will be from 1979.
slouken@481
   173
#define MINIZ_NO_TIME
slouken@481
   174
slouken@481
   175
// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
slouken@481
   176
#define MINIZ_NO_ARCHIVE_APIS
slouken@481
   177
slouken@481
   178
// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
slouken@481
   179
#define MINIZ_NO_ARCHIVE_WRITING_APIS
slouken@481
   180
slouken@481
   181
// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
slouken@481
   182
#define MINIZ_NO_ZLIB_APIS
slouken@481
   183
slouken@481
   184
// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
slouken@481
   185
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
slouken@481
   186
slouken@481
   187
// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
slouken@481
   188
// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
slouken@481
   189
// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
slouken@481
   190
// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
slouken@481
   191
//#define MINIZ_NO_MALLOC
slouken@481
   192
#define MINIZ_SDL_MALLOC
slouken@481
   193
slouken@481
   194
// Define MINIZ_STATIC_FUNCTIONS to make all functions static. You probably
slouken@481
   195
// want this if you're using miniz in a library
slouken@481
   196
#define MINIZ_STATIC_FUNCTIONS
slouken@481
   197
slouken@481
   198
#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
slouken@481
   199
  // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux
slouken@481
   200
  #define MINIZ_NO_TIME
slouken@481
   201
#endif
slouken@481
   202
slouken@481
   203
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
slouken@481
   204
  #include <time.h>
slouken@481
   205
#endif
slouken@481
   206
slouken@481
   207
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
slouken@481
   208
// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
slouken@481
   209
#define MINIZ_X86_OR_X64_CPU 1
slouken@481
   210
#endif
slouken@481
   211
slouken@481
   212
#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
slouken@481
   213
// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
slouken@481
   214
#define MINIZ_LITTLE_ENDIAN 1
slouken@481
   215
#endif
slouken@481
   216
slouken@481
   217
#if MINIZ_X86_OR_X64_CPU
slouken@481
   218
// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
slouken@481
   219
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
slouken@481
   220
#endif
slouken@481
   221
slouken@481
   222
#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
slouken@481
   223
// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
slouken@481
   224
#define MINIZ_HAS_64BIT_REGISTERS 1
slouken@481
   225
#endif
slouken@481
   226
slouken@481
   227
#ifdef MINIZ_STATIC_FUNCTIONS
slouken@481
   228
#define MINIZ_STATIC static
slouken@481
   229
#else
slouken@481
   230
#define MINIZ_STATIC
slouken@481
   231
#endif
slouken@481
   232
slouken@481
   233
#ifdef __cplusplus
slouken@481
   234
extern "C" {
slouken@481
   235
#endif
slouken@481
   236
slouken@481
   237
// ------------------- zlib-style API Definitions.
slouken@481
   238
slouken@481
   239
// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
slouken@481
   240
typedef unsigned long mz_ulong;
slouken@481
   241
slouken@481
   242
// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
slouken@481
   243
MINIZ_STATIC void mz_free(void *p);
slouken@481
   244
slouken@481
   245
#define MZ_ADLER32_INIT (1)
slouken@481
   246
// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
slouken@481
   247
MINIZ_STATIC mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
slouken@481
   248
slouken@481
   249
#define MZ_CRC32_INIT (0)
slouken@481
   250
// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
slouken@481
   251
MINIZ_STATIC mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
slouken@481
   252
slouken@481
   253
// Compression strategies.
slouken@481
   254
enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
slouken@481
   255
slouken@481
   256
// Method
slouken@481
   257
#define MZ_DEFLATED 8
slouken@481
   258
slouken@481
   259
#ifndef MINIZ_NO_ZLIB_APIS
slouken@481
   260
slouken@481
   261
// Heap allocation callbacks.
slouken@481
   262
// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
slouken@481
   263
typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
slouken@481
   264
typedef void (*mz_free_func)(void *opaque, void *address);
slouken@481
   265
typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
slouken@481
   266
slouken@481
   267
#define MZ_VERSION          "9.1.15"
slouken@481
   268
#define MZ_VERNUM           0x91F0
slouken@481
   269
#define MZ_VER_MAJOR        9
slouken@481
   270
#define MZ_VER_MINOR        1
slouken@481
   271
#define MZ_VER_REVISION     15
slouken@481
   272
#define MZ_VER_SUBREVISION  0
slouken@481
   273
slouken@481
   274
// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
slouken@481
   275
enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
slouken@481
   276
slouken@481
   277
// Return status codes. MZ_PARAM_ERROR is non-standard.
slouken@481
   278
enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
slouken@481
   279
slouken@481
   280
// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
slouken@481
   281
enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 };
slouken@481
   282
slouken@481
   283
// Window bits
slouken@481
   284
#define MZ_DEFAULT_WINDOW_BITS 15
slouken@481
   285
slouken@481
   286
struct mz_internal_state;
slouken@481
   287
slouken@481
   288
// Compression/decompression stream struct.
slouken@481
   289
typedef struct mz_stream_s
slouken@481
   290
{
slouken@481
   291
  const unsigned char *next_in;     // pointer to next byte to read
slouken@481
   292
  unsigned int avail_in;            // number of bytes available at next_in
slouken@481
   293
  mz_ulong total_in;                // total number of bytes consumed so far
slouken@481
   294
slouken@481
   295
  unsigned char *next_out;          // pointer to next byte to write
slouken@481
   296
  unsigned int avail_out;           // number of bytes that can be written to next_out
slouken@481
   297
  mz_ulong total_out;               // total number of bytes produced so far
slouken@481
   298
slouken@481
   299
  char *msg;                        // error msg (unused)
slouken@481
   300
  struct mz_internal_state *state;  // internal state, allocated by zalloc/zfree
slouken@481
   301
slouken@481
   302
  mz_alloc_func zalloc;             // optional heap allocation function (defaults to malloc)
slouken@481
   303
  mz_free_func zfree;               // optional heap free function (defaults to free)
slouken@481
   304
  void *opaque;                     // heap alloc function user pointer
slouken@481
   305
slouken@481
   306
  int data_type;                    // data_type (unused)
slouken@481
   307
  mz_ulong adler;                   // adler32 of the source or uncompressed data
slouken@481
   308
  mz_ulong reserved;                // not used
slouken@481
   309
} mz_stream;
slouken@481
   310
slouken@481
   311
typedef mz_stream *mz_streamp;
slouken@481
   312
slouken@481
   313
// Returns the version string of miniz.c.
slouken@481
   314
MINIZ_STATIC const char *mz_version(void);
slouken@481
   315
slouken@481
   316
// mz_deflateInit() initializes a compressor with default options:
slouken@481
   317
// Parameters:
slouken@481
   318
//  pStream must point to an initialized mz_stream struct.
slouken@481
   319
//  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
slouken@481
   320
//  level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
slouken@481
   321
//  (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
slouken@481
   322
// Return values:
slouken@481
   323
//  MZ_OK on success.
slouken@481
   324
//  MZ_STREAM_ERROR if the stream is bogus.
slouken@481
   325
//  MZ_PARAM_ERROR if the input parameters are bogus.
slouken@481
   326
//  MZ_MEM_ERROR on out of memory.
slouken@481
   327
MINIZ_STATIC int mz_deflateInit(mz_streamp pStream, int level);
slouken@481
   328
slouken@481
   329
// mz_deflateInit2() is like mz_deflate(), except with more control:
slouken@481
   330
// Additional parameters:
slouken@481
   331
//   method must be MZ_DEFLATED
slouken@481
   332
//   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
slouken@481
   333
//   mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
slouken@481
   334
MINIZ_STATIC int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
slouken@481
   335
slouken@481
   336
// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
slouken@481
   337
MINIZ_STATIC int mz_deflateReset(mz_streamp pStream);
slouken@481
   338
slouken@481
   339
// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
slouken@481
   340
// Parameters:
slouken@481
   341
//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
slouken@481
   342
//   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
slouken@481
   343
// Return values:
slouken@481
   344
//   MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
slouken@481
   345
//   MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
slouken@481
   346
//   MZ_STREAM_ERROR if the stream is bogus.
slouken@481
   347
//   MZ_PARAM_ERROR if one of the parameters is invalid.
slouken@481
   348
//   MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
slouken@481
   349
MINIZ_STATIC int mz_deflate(mz_streamp pStream, int flush);
slouken@481
   350
slouken@481
   351
// mz_deflateEnd() deinitializes a compressor:
slouken@481
   352
// Return values:
slouken@481
   353
//  MZ_OK on success.
slouken@481
   354
//  MZ_STREAM_ERROR if the stream is bogus.
slouken@481
   355
MINIZ_STATIC int mz_deflateEnd(mz_streamp pStream);
slouken@481
   356
slouken@481
   357
// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
slouken@481
   358
MINIZ_STATIC mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
slouken@481
   359
slouken@481
   360
// Single-call compression functions mz_compress() and mz_compress2():
slouken@481
   361
// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
slouken@481
   362
MINIZ_STATIC int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
slouken@481
   363
MINIZ_STATIC int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
slouken@481
   364
slouken@481
   365
// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
slouken@481
   366
MINIZ_STATIC mz_ulong mz_compressBound(mz_ulong source_len);
slouken@481
   367
slouken@481
   368
// Initializes a decompressor.
slouken@481
   369
MINIZ_STATIC int mz_inflateInit(mz_streamp pStream);
slouken@481
   370
slouken@481
   371
// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
slouken@481
   372
// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
slouken@481
   373
MINIZ_STATIC int mz_inflateInit2(mz_streamp pStream, int window_bits);
slouken@481
   374
slouken@481
   375
// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
slouken@481
   376
// Parameters:
slouken@481
   377
//   pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
slouken@481
   378
//   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
slouken@481
   379
//   On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
slouken@481
   380
//   MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
slouken@481
   381
// Return values:
slouken@481
   382
//   MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
slouken@481
   383
//   MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
slouken@481
   384
//   MZ_STREAM_ERROR if the stream is bogus.
slouken@481
   385
//   MZ_DATA_ERROR if the deflate stream is invalid.
slouken@481
   386
//   MZ_PARAM_ERROR if one of the parameters is invalid.
slouken@481
   387
//   MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
slouken@481
   388
//   with more input data, or with more room in the output buffer (except when using single call decompression, described above).
slouken@481
   389
MINIZ_STATIC int mz_inflate(mz_streamp pStream, int flush);
slouken@481
   390
slouken@481
   391
// Deinitializes a decompressor.
slouken@481
   392
MINIZ_STATIC int mz_inflateEnd(mz_streamp pStream);
slouken@481
   393
slouken@481
   394
// Single-call decompression.
slouken@481
   395
// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
slouken@481
   396
MINIZ_STATIC int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
slouken@481
   397
slouken@481
   398
// Returns a string description of the specified error code, or NULL if the error code is invalid.
slouken@481
   399
MINIZ_STATIC const char *mz_error(int err);
slouken@481
   400
slouken@481
   401
// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
slouken@481
   402
// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
slouken@481
   403
#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
slouken@481
   404
  typedef unsigned char Byte;
slouken@481
   405
  typedef unsigned int uInt;
slouken@481
   406
  typedef mz_ulong uLong;
slouken@481
   407
  typedef Byte Bytef;
slouken@481
   408
  typedef uInt uIntf;
slouken@481
   409
  typedef char charf;
slouken@481
   410
  typedef int intf;
slouken@481
   411
  typedef void *voidpf;
slouken@481
   412
  typedef uLong uLongf;
slouken@481
   413
  typedef void *voidp;
slouken@481
   414
  typedef void *const voidpc;
slouken@481
   415
  #define Z_NULL                0
slouken@481
   416
  #define Z_NO_FLUSH            MZ_NO_FLUSH
slouken@481
   417
  #define Z_PARTIAL_FLUSH       MZ_PARTIAL_FLUSH
slouken@481
   418
  #define Z_SYNC_FLUSH          MZ_SYNC_FLUSH
slouken@481
   419
  #define Z_FULL_FLUSH          MZ_FULL_FLUSH
slouken@481
   420
  #define Z_FINISH              MZ_FINISH
slouken@481
   421
  #define Z_BLOCK               MZ_BLOCK
slouken@481
   422
  #define Z_OK                  MZ_OK
slouken@481
   423
  #define Z_STREAM_END          MZ_STREAM_END
slouken@481
   424
  #define Z_NEED_DICT           MZ_NEED_DICT
slouken@481
   425
  #define Z_ERRNO               MZ_ERRNO
slouken@481
   426
  #define Z_STREAM_ERROR        MZ_STREAM_ERROR
slouken@481
   427
  #define Z_DATA_ERROR          MZ_DATA_ERROR
slouken@481
   428
  #define Z_MEM_ERROR           MZ_MEM_ERROR
slouken@481
   429
  #define Z_BUF_ERROR           MZ_BUF_ERROR
slouken@481
   430
  #define Z_VERSION_ERROR       MZ_VERSION_ERROR
slouken@481
   431
  #define Z_PARAM_ERROR         MZ_PARAM_ERROR
slouken@481
   432
  #define Z_NO_COMPRESSION      MZ_NO_COMPRESSION
slouken@481
   433
  #define Z_BEST_SPEED          MZ_BEST_SPEED
slouken@481
   434
  #define Z_BEST_COMPRESSION    MZ_BEST_COMPRESSION
slouken@481
   435
  #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
slouken@481
   436
  #define Z_DEFAULT_STRATEGY    MZ_DEFAULT_STRATEGY
slouken@481
   437
  #define Z_FILTERED            MZ_FILTERED
slouken@481
   438
  #define Z_HUFFMAN_ONLY        MZ_HUFFMAN_ONLY
slouken@481
   439
  #define Z_RLE                 MZ_RLE
slouken@481
   440
  #define Z_FIXED               MZ_FIXED
slouken@481
   441
  #define Z_DEFLATED            MZ_DEFLATED
slouken@481
   442
  #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
slouken@481
   443
  #define alloc_func            mz_alloc_func
slouken@481
   444
  #define free_func             mz_free_func
slouken@481
   445
  #define internal_state        mz_internal_state
slouken@481
   446
  #define z_stream              mz_stream
slouken@481
   447
  #define deflateInit           mz_deflateInit
slouken@481
   448
  #define deflateInit2          mz_deflateInit2
slouken@481
   449
  #define deflateReset          mz_deflateReset
slouken@481
   450
  #define deflate               mz_deflate
slouken@481
   451
  #define deflateEnd            mz_deflateEnd
slouken@481
   452
  #define deflateBound          mz_deflateBound
slouken@481
   453
  #define compress              mz_compress
slouken@481
   454
  #define compress2             mz_compress2
slouken@481
   455
  #define compressBound         mz_compressBound
slouken@481
   456
  #define inflateInit           mz_inflateInit
slouken@481
   457
  #define inflateInit2          mz_inflateInit2
slouken@481
   458
  #define inflate               mz_inflate
slouken@481
   459
  #define inflateEnd            mz_inflateEnd
slouken@481
   460
  #define uncompress            mz_uncompress
slouken@481
   461
  #define crc32                 mz_crc32
slouken@481
   462
  #define adler32               mz_adler32
slouken@481
   463
  #define MAX_WBITS             15
slouken@481
   464
  #define MAX_MEM_LEVEL         9
slouken@481
   465
  #define zError                mz_error
slouken@481
   466
  #define ZLIB_VERSION          MZ_VERSION
slouken@481
   467
  #define ZLIB_VERNUM           MZ_VERNUM
slouken@481
   468
  #define ZLIB_VER_MAJOR        MZ_VER_MAJOR
slouken@481
   469
  #define ZLIB_VER_MINOR        MZ_VER_MINOR
slouken@481
   470
  #define ZLIB_VER_REVISION     MZ_VER_REVISION
slouken@481
   471
  #define ZLIB_VER_SUBREVISION  MZ_VER_SUBREVISION
slouken@481
   472
  #define zlibVersion           mz_version
slouken@481
   473
  #define zlib_version          mz_version()
slouken@481
   474
#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
slouken@481
   475
slouken@481
   476
#endif // MINIZ_NO_ZLIB_APIS
slouken@481
   477
slouken@481
   478
// ------------------- Types and macros
slouken@481
   479
slouken@481
   480
typedef unsigned char mz_uint8;
slouken@481
   481
typedef signed short mz_int16;
slouken@481
   482
typedef unsigned short mz_uint16;
slouken@481
   483
typedef unsigned int mz_uint32;
slouken@481
   484
typedef unsigned int mz_uint;
slouken@481
   485
typedef long long mz_int64;
slouken@481
   486
typedef unsigned long long mz_uint64;
slouken@481
   487
typedef int mz_bool;
slouken@481
   488
slouken@481
   489
#define MZ_FALSE (0)
slouken@481
   490
#define MZ_TRUE (1)
slouken@481
   491
slouken@481
   492
// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
slouken@481
   493
#ifdef _MSC_VER
slouken@481
   494
   #define MZ_MACRO_END while (0, 0)
slouken@481
   495
#else
slouken@481
   496
   #define MZ_MACRO_END while (0)
slouken@481
   497
#endif
slouken@481
   498
slouken@481
   499
// ------------------- ZIP archive reading/writing
slouken@481
   500
slouken@481
   501
#ifndef MINIZ_NO_ARCHIVE_APIS
slouken@481
   502
slouken@481
   503
enum
slouken@481
   504
{
slouken@481
   505
  MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024,
slouken@481
   506
  MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
slouken@481
   507
  MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
slouken@481
   508
};
slouken@481
   509
slouken@481
   510
typedef struct
slouken@481
   511
{
slouken@481
   512
  mz_uint32 m_file_index;
slouken@481
   513
  mz_uint32 m_central_dir_ofs;
slouken@481
   514
  mz_uint16 m_version_made_by;
slouken@481
   515
  mz_uint16 m_version_needed;
slouken@481
   516
  mz_uint16 m_bit_flag;
slouken@481
   517
  mz_uint16 m_method;
slouken@481
   518
#ifndef MINIZ_NO_TIME
slouken@481
   519
  time_t m_time;
slouken@481
   520
#endif
slouken@481
   521
  mz_uint32 m_crc32;
slouken@481
   522
  mz_uint64 m_comp_size;
slouken@481
   523
  mz_uint64 m_uncomp_size;
slouken@481
   524
  mz_uint16 m_internal_attr;
slouken@481
   525
  mz_uint32 m_external_attr;
slouken@481
   526
  mz_uint64 m_local_header_ofs;
slouken@481
   527
  mz_uint32 m_comment_size;
slouken@481
   528
  char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
slouken@481
   529
  char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
slouken@481
   530
} mz_zip_archive_file_stat;
slouken@481
   531
slouken@481
   532
typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
slouken@481
   533
typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
slouken@481
   534
slouken@481
   535
struct mz_zip_internal_state_tag;
slouken@481
   536
typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
slouken@481
   537
slouken@481
   538
typedef enum
slouken@481
   539
{
slouken@481
   540
  MZ_ZIP_MODE_INVALID = 0,
slouken@481
   541
  MZ_ZIP_MODE_READING = 1,
slouken@481
   542
  MZ_ZIP_MODE_WRITING = 2,
slouken@481
   543
  MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
slouken@481
   544
} mz_zip_mode;
slouken@481
   545
slouken@481
   546
typedef struct mz_zip_archive_tag
slouken@481
   547
{
slouken@481
   548
  mz_uint64 m_archive_size;
slouken@481
   549
  mz_uint64 m_central_directory_file_ofs;
slouken@481
   550
  mz_uint m_total_files;
slouken@481
   551
  mz_zip_mode m_zip_mode;
slouken@481
   552
slouken@481
   553
  mz_uint m_file_offset_alignment;
slouken@481
   554
slouken@481
   555
  mz_alloc_func m_pAlloc;
slouken@481
   556
  mz_free_func m_pFree;
slouken@481
   557
  mz_realloc_func m_pRealloc;
slouken@481
   558
  void *m_pAlloc_opaque;
slouken@481
   559
slouken@481
   560
  mz_file_read_func m_pRead;
slouken@481
   561
  mz_file_write_func m_pWrite;
slouken@481
   562
  void *m_pIO_opaque;
slouken@481
   563
slouken@481
   564
  mz_zip_internal_state *m_pState;
slouken@481
   565
slouken@481
   566
} mz_zip_archive;
slouken@481
   567
slouken@481
   568
typedef enum
slouken@481
   569
{
slouken@481
   570
  MZ_ZIP_FLAG_CASE_SENSITIVE                = 0x0100,
slouken@481
   571
  MZ_ZIP_FLAG_IGNORE_PATH                   = 0x0200,
slouken@481
   572
  MZ_ZIP_FLAG_COMPRESSED_DATA               = 0x0400,
slouken@481
   573
  MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
slouken@481
   574
} mz_zip_flags;
slouken@481
   575
slouken@481
   576
// ZIP archive reading
slouken@481
   577
slouken@481
   578
// Inits a ZIP archive reader.
slouken@481
   579
// These functions read and validate the archive's central directory.
slouken@481
   580
MINIZ_STATIC mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
slouken@481
   581
MINIZ_STATIC mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
slouken@481
   582
slouken@481
   583
#ifndef MINIZ_NO_STDIO
slouken@481
   584
MINIZ_STATIC mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
slouken@481
   585
#endif
slouken@481
   586
slouken@481
   587
// Returns the total number of files in the archive.
slouken@481
   588
MINIZ_STATIC mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
slouken@481
   589
slouken@481
   590
// Returns detailed information about an archive file entry.
slouken@481
   591
MINIZ_STATIC mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
slouken@481
   592
slouken@481
   593
// Determines if an archive file entry is a directory entry.
slouken@481
   594
MINIZ_STATIC mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
slouken@481
   595
MINIZ_STATIC mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
slouken@481
   596
slouken@481
   597
// Retrieves the filename of an archive file entry.
slouken@481
   598
// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
slouken@481
   599
MINIZ_STATIC mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
slouken@481
   600
slouken@481
   601
// Attempts to locates a file in the archive's central directory.
slouken@481
   602
// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
slouken@481
   603
// Returns -1 if the file cannot be found.
slouken@481
   604
MINIZ_STATIC int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
slouken@481
   605
slouken@481
   606
// Extracts a archive file to a memory buffer using no memory allocation.
slouken@481
   607
MINIZ_STATIC mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
slouken@481
   608
MINIZ_STATIC mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
slouken@481
   609
slouken@481
   610
// Extracts a archive file to a memory buffer.
slouken@481
   611
MINIZ_STATIC mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
slouken@481
   612
MINIZ_STATIC mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
slouken@481
   613
slouken@481
   614
// Extracts a archive file to a dynamically allocated heap buffer.
slouken@481
   615
MINIZ_STATIC void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
slouken@481
   616
MINIZ_STATIC void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
slouken@481
   617
slouken@481
   618
// Extracts a archive file using a callback function to output the file's data.
slouken@481
   619
MINIZ_STATIC mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
slouken@481
   620
MINIZ_STATIC mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
slouken@481
   621
slouken@481
   622
#ifndef MINIZ_NO_STDIO
slouken@481
   623
// Extracts a archive file to a disk file and sets its last accessed and modified times.
slouken@481
   624
// This function only extracts files, not archive directory records.
slouken@481
   625
MINIZ_STATIC mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
slouken@481
   626
MINIZ_STATIC mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
slouken@481
   627
#endif
slouken@481
   628
slouken@481
   629
// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
slouken@481
   630
MINIZ_STATIC mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
slouken@481
   631
slouken@481
   632
// ZIP archive writing
slouken@481
   633
slouken@481
   634
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
slouken@481
   635
slouken@481
   636
// Inits a ZIP archive writer.
slouken@481
   637
MINIZ_STATIC mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
slouken@481
   638
MINIZ_STATIC mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
slouken@481
   639
slouken@481
   640
#ifndef MINIZ_NO_STDIO
slouken@481
   641
MINIZ_STATIC mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
slouken@481
   642
#endif
slouken@481
   643
slouken@481
   644
// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
slouken@481
   645
// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
slouken@481
   646
// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
slouken@481
   647
// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
slouken@481
   648
// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
slouken@481
   649
// the archive is finalized the file's central directory will be hosed.
slouken@481
   650
MINIZ_STATIC mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
slouken@481
   651
slouken@481
   652
// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
slouken@481
   653
// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
slouken@481
   654
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
slouken@481
   655
MINIZ_STATIC mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
slouken@481
   656
MINIZ_STATIC mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
slouken@481
   657
slouken@481
   658
#ifndef MINIZ_NO_STDIO
slouken@481
   659
// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
slouken@481
   660
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
slouken@481
   661
MINIZ_STATIC mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
slouken@481
   662
#endif
slouken@481
   663
slouken@481
   664
// Adds a file to an archive by fully cloning the data from another archive.
slouken@481
   665
// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
slouken@481
   666
MINIZ_STATIC mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
slouken@481
   667
slouken@481
   668
// Finalizes the archive by writing the central directory records followed by the end of central directory record.
slouken@481
   669
// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
slouken@481
   670
// An archive must be manually finalized by calling this function for it to be valid.
slouken@481
   671
MINIZ_STATIC mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
slouken@481
   672
MINIZ_STATIC mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
slouken@481
   673
slouken@481
   674
// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
slouken@481
   675
// Note for the archive to be valid, it must have been finalized before ending.
slouken@481
   676
MINIZ_STATIC mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
slouken@481
   677
slouken@481
   678
// Misc. high-level helper functions:
slouken@481
   679
slouken@481
   680
// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
slouken@481
   681
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
slouken@481
   682
MINIZ_STATIC mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
slouken@481
   683
slouken@481
   684
// Reads a single file from an archive into a heap block.
slouken@481
   685
// Returns NULL on failure.
slouken@481
   686
MINIZ_STATIC void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
slouken@481
   687
slouken@481
   688
#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
slouken@481
   689
slouken@481
   690
#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
slouken@481
   691
slouken@481
   692
// ------------------- Low-level Decompression API Definitions
slouken@481
   693
slouken@481
   694
// Decompression flags used by tinfl_decompress().
slouken@481
   695
// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
slouken@481
   696
// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
slouken@481
   697
// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
slouken@481
   698
// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
slouken@481
   699
enum
slouken@481
   700
{
slouken@481
   701
  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
slouken@481
   702
  TINFL_FLAG_HAS_MORE_INPUT = 2,
slouken@481
   703
  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
slouken@481
   704
  TINFL_FLAG_COMPUTE_ADLER32 = 8
slouken@481
   705
};
slouken@481
   706
slouken@481
   707
// High level decompression functions:
slouken@481
   708
// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
slouken@481
   709
// On entry:
slouken@481
   710
//  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
slouken@481
   711
// On return:
slouken@481
   712
//  Function returns a pointer to the decompressed data, or NULL on failure.
slouken@481
   713
//  *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
slouken@481
   714
//  The caller must call mz_free() on the returned block when it's no longer needed.
slouken@481
   715
MINIZ_STATIC void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
slouken@481
   716
slouken@481
   717
// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
slouken@481
   718
// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
slouken@481
   719
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
slouken@481
   720
MINIZ_STATIC size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
slouken@481
   721
slouken@481
   722
// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
slouken@481
   723
// Returns 1 on success or 0 on failure.
slouken@481
   724
typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
slouken@481
   725
MINIZ_STATIC int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
slouken@481
   726
slouken@481
   727
struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
slouken@481
   728
slouken@481
   729
// Max size of LZ dictionary.
slouken@481
   730
#define TINFL_LZ_DICT_SIZE 32768
slouken@481
   731
slouken@481
   732
// Return status.
slouken@481
   733
typedef enum
slouken@481
   734
{
slouken@481
   735
  TINFL_STATUS_BAD_PARAM = -3,
slouken@481
   736
  TINFL_STATUS_ADLER32_MISMATCH = -2,
slouken@481
   737
  TINFL_STATUS_FAILED = -1,
slouken@481
   738
  TINFL_STATUS_DONE = 0,
slouken@481
   739
  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
slouken@481
   740
  TINFL_STATUS_HAS_MORE_OUTPUT = 2
slouken@481
   741
} tinfl_status;
slouken@481
   742
slouken@481
   743
// Initializes the decompressor to its initial state.
slouken@481
   744
#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
slouken@481
   745
#define tinfl_get_adler32(r) (r)->m_check_adler32
slouken@481
   746
slouken@481
   747
// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
slouken@481
   748
// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
slouken@481
   749
MINIZ_STATIC tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
slouken@481
   750
slouken@481
   751
// Internal/private bits follow.
slouken@481
   752
enum
slouken@481
   753
{
slouken@481
   754
  TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
slouken@481
   755
  TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
slouken@481
   756
};
slouken@481
   757
slouken@481
   758
typedef struct
slouken@481
   759
{
slouken@481
   760
  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
slouken@481
   761
  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
slouken@481
   762
} tinfl_huff_table;
slouken@481
   763
slouken@481
   764
#if MINIZ_HAS_64BIT_REGISTERS
slouken@481
   765
  #define TINFL_USE_64BIT_BITBUF 1
slouken@481
   766
#endif
slouken@481
   767
slouken@481
   768
#if TINFL_USE_64BIT_BITBUF
slouken@481
   769
  typedef mz_uint64 tinfl_bit_buf_t;
slouken@481
   770
  #define TINFL_BITBUF_SIZE (64)
slouken@481
   771
#else
slouken@481
   772
  typedef mz_uint32 tinfl_bit_buf_t;
slouken@481
   773
  #define TINFL_BITBUF_SIZE (32)
slouken@481
   774
#endif
slouken@481
   775
slouken@481
   776
struct tinfl_decompressor_tag
slouken@481
   777
{
slouken@481
   778
  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
slouken@481
   779
  tinfl_bit_buf_t m_bit_buf;
slouken@481
   780
  size_t m_dist_from_out_buf_start;
slouken@481
   781
  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
slouken@481
   782
  mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
slouken@481
   783
};
slouken@481
   784
slouken@481
   785
// ------------------- Low-level Compression API Definitions
slouken@481
   786
slouken@481
   787
// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
slouken@481
   788
#define TDEFL_LESS_MEMORY 0
slouken@481
   789
slouken@481
   790
// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
slouken@481
   791
// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
slouken@481
   792
enum
slouken@481
   793
{
slouken@481
   794
  TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
slouken@481
   795
};
slouken@481
   796
slouken@481
   797
// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
slouken@481
   798
// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
slouken@481
   799
// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
slouken@481
   800
// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
slouken@481
   801
// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
slouken@481
   802
// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
slouken@481
   803
// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
slouken@481
   804
// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
slouken@481
   805
// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
slouken@481
   806
enum
slouken@481
   807
{
slouken@481
   808
  TDEFL_WRITE_ZLIB_HEADER             = 0x01000,
slouken@481
   809
  TDEFL_COMPUTE_ADLER32               = 0x02000,
slouken@481
   810
  TDEFL_GREEDY_PARSING_FLAG           = 0x04000,
slouken@481
   811
  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
slouken@481
   812
  TDEFL_RLE_MATCHES                   = 0x10000,
slouken@481
   813
  TDEFL_FILTER_MATCHES                = 0x20000,
slouken@481
   814
  TDEFL_FORCE_ALL_STATIC_BLOCKS       = 0x40000,
slouken@481
   815
  TDEFL_FORCE_ALL_RAW_BLOCKS          = 0x80000
slouken@481
   816
};
slouken@481
   817
slouken@481
   818
// High level compression functions:
slouken@481
   819
// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
slouken@481
   820
// On entry:
slouken@481
   821
//  pSrc_buf, src_buf_len: Pointer and size of source block to compress.
slouken@481
   822
//  flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
slouken@481
   823
// On return:
slouken@481
   824
//  Function returns a pointer to the compressed data, or NULL on failure.
slouken@481
   825
//  *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
slouken@481
   826
//  The caller must free() the returned block when it's no longer needed.
slouken@481
   827
MINIZ_STATIC void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
slouken@481
   828
slouken@481
   829
// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
slouken@481
   830
// Returns 0 on failure.
slouken@481
   831
MINIZ_STATIC size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
slouken@481
   832
slouken@481
   833
// Compresses an image to a compressed PNG file in memory.
slouken@481
   834
// On entry:
slouken@481
   835
//  pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. 
slouken@481
   836
//  The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
slouken@481
   837
//  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
slouken@481
   838
//  If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
slouken@481
   839
// On return:
slouken@481
   840
//  Function returns a pointer to the compressed data, or NULL on failure.
slouken@481
   841
//  *pLen_out will be set to the size of the PNG image file.
slouken@481
   842
//  The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
slouken@481
   843
MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out, mz_uint level, mz_bool flip);
slouken@481
   844
MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out);
slouken@481
   845
slouken@481
   846
// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
slouken@481
   847
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
slouken@481
   848
slouken@481
   849
// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
slouken@481
   850
MINIZ_STATIC mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
slouken@481
   851
slouken@481
   852
enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
slouken@481
   853
slouken@481
   854
// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
slouken@481
   855
#if TDEFL_LESS_MEMORY
slouken@481
   856
enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
slouken@481
   857
#else
slouken@481
   858
enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
slouken@481
   859
#endif
slouken@481
   860
slouken@481
   861
// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
slouken@481
   862
typedef enum
slouken@481
   863
{
slouken@481
   864
  TDEFL_STATUS_BAD_PARAM = -2,
slouken@481
   865
  TDEFL_STATUS_PUT_BUF_FAILED = -1,
slouken@481
   866
  TDEFL_STATUS_OKAY = 0,
slouken@481
   867
  TDEFL_STATUS_DONE = 1,
slouken@481
   868
} tdefl_status;
slouken@481
   869
slouken@481
   870
// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
slouken@481
   871
typedef enum
slouken@481
   872
{
slouken@481
   873
  TDEFL_NO_FLUSH = 0,
slouken@481
   874
  TDEFL_SYNC_FLUSH = 2,
slouken@481
   875
  TDEFL_FULL_FLUSH = 3,
slouken@481
   876
  TDEFL_FINISH = 4
slouken@481
   877
} tdefl_flush;
slouken@481
   878
slouken@481
   879
// tdefl's compression state structure.
slouken@481
   880
typedef struct
slouken@481
   881
{
slouken@481
   882
  tdefl_put_buf_func_ptr m_pPut_buf_func;
slouken@481
   883
  void *m_pPut_buf_user;
slouken@481
   884
  mz_uint m_flags, m_max_probes[2];
slouken@481
   885
  int m_greedy_parsing;
slouken@481
   886
  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
slouken@481
   887
  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
slouken@481
   888
  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
slouken@481
   889
  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
slouken@481
   890
  tdefl_status m_prev_return_status;
slouken@481
   891
  const void *m_pIn_buf;
slouken@481
   892
  void *m_pOut_buf;
slouken@481
   893
  size_t *m_pIn_buf_size, *m_pOut_buf_size;
slouken@481
   894
  tdefl_flush m_flush;
slouken@481
   895
  const mz_uint8 *m_pSrc;
slouken@481
   896
  size_t m_src_buf_left, m_out_buf_ofs;
slouken@481
   897
  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
slouken@481
   898
  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
slouken@481
   899
  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
slouken@481
   900
  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
slouken@481
   901
  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
slouken@481
   902
  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
slouken@481
   903
  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
slouken@481
   904
  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
slouken@481
   905
} tdefl_compressor;
slouken@481
   906
slouken@481
   907
// Initializes the compressor.
slouken@481
   908
// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
slouken@481
   909
// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
slouken@481
   910
// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
slouken@481
   911
// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
slouken@481
   912
MINIZ_STATIC tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
slouken@481
   913
slouken@481
   914
// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
slouken@481
   915
MINIZ_STATIC tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
slouken@481
   916
slouken@481
   917
// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
slouken@481
   918
// tdefl_compress_buffer() always consumes the entire input buffer.
slouken@481
   919
MINIZ_STATIC tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
slouken@481
   920
slouken@481
   921
MINIZ_STATIC tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
slouken@481
   922
MINIZ_STATIC mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
slouken@481
   923
slouken@481
   924
// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
slouken@481
   925
#ifndef MINIZ_NO_ZLIB_APIS
slouken@481
   926
// Create tdefl_compress() flags given zlib-style compression parameters.
slouken@481
   927
// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
slouken@481
   928
// window_bits may be -15 (raw deflate) or 15 (zlib)
slouken@481
   929
// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
slouken@481
   930
MINIZ_STATIC mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
slouken@481
   931
#endif // #ifndef MINIZ_NO_ZLIB_APIS
slouken@481
   932
slouken@481
   933
#ifdef __cplusplus
slouken@481
   934
}
slouken@481
   935
#endif
slouken@481
   936
slouken@481
   937
#endif // MINIZ_HEADER_INCLUDED
slouken@481
   938
slouken@481
   939
// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
slouken@481
   940
slouken@481
   941
#ifndef MINIZ_HEADER_FILE_ONLY
slouken@481
   942
slouken@481
   943
typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1];
slouken@481
   944
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1];
slouken@481
   945
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1];
slouken@481
   946
slouken@545
   947
/*#include <string.h>*/
slouken@545
   948
slouken@545
   949
#ifndef MZ_ASSERT
slouken@481
   950
#include <assert.h>
slouken@545
   951
#define MZ_ASSERT(x) assert(x)
slouken@545
   952
#endif
slouken@481
   953
slouken@481
   954
#ifdef MINIZ_NO_MALLOC
slouken@481
   955
  #define MZ_MALLOC(x) NULL
slouken@481
   956
  #define MZ_FREE(x) (void)x, ((void)0)
slouken@481
   957
  #define MZ_REALLOC(p, x) NULL
slouken@481
   958
#elif defined(MINIZ_SDL_MALLOC)
slouken@481
   959
  #define MZ_MALLOC(x) SDL_malloc(x)
slouken@481
   960
  #define MZ_FREE(x) SDL_free(x)
slouken@481
   961
  #define MZ_REALLOC(p, x) SDL_realloc(p, x)
slouken@481
   962
#else
slouken@481
   963
  #define MZ_MALLOC(x) malloc(x)
slouken@481
   964
  #define MZ_FREE(x) free(x)
slouken@481
   965
  #define MZ_REALLOC(p, x) realloc(p, x)
slouken@481
   966
#endif
slouken@481
   967
slouken@481
   968
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
slouken@481
   969
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
slouken@481
   970
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
slouken@481
   971
slouken@481
   972
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
slouken@481
   973
  #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
slouken@481
   974
  #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
slouken@481
   975
#else
slouken@481
   976
  #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
slouken@481
   977
  #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))
slouken@481
   978
#endif
slouken@481
   979
slouken@481
   980
#ifdef _MSC_VER
slouken@481
   981
  #define MZ_FORCEINLINE __forceinline
slouken@481
   982
#elif defined(__GNUC__)
slouken@481
   983
  #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
slouken@481
   984
#else
slouken@481
   985
  #define MZ_FORCEINLINE inline
slouken@481
   986
#endif
slouken@481
   987
slouken@481
   988
#ifdef __cplusplus
slouken@481
   989
  extern "C" {
slouken@481
   990
#endif
slouken@481
   991
slouken@481
   992
// ------------------- zlib-style API's
slouken@481
   993
slouken@481
   994
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
slouken@481
   995
{
slouken@481
   996
  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
slouken@481
   997
  if (!ptr) return MZ_ADLER32_INIT;
slouken@481
   998
  while (buf_len) {
slouken@481
   999
    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
slouken@481
  1000
      s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
slouken@481
  1001
      s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
slouken@481
  1002
    }
slouken@481
  1003
    for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
slouken@481
  1004
    s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
slouken@481
  1005
  }
slouken@481
  1006
  return (s2 << 16) + s1;
slouken@481
  1007
}
slouken@481
  1008
slouken@481
  1009
// 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/
slouken@481
  1010
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
slouken@481
  1011
{
slouken@481
  1012
  static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
slouken@481
  1013
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
slouken@481
  1014
  mz_uint32 crcu32 = (mz_uint32)crc;
slouken@481
  1015
  if (!ptr) return MZ_CRC32_INIT;
slouken@481
  1016
  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)]; }
slouken@481
  1017
  return ~crcu32;
slouken@481
  1018
}
slouken@481
  1019
slouken@481
  1020
MINIZ_STATIC void mz_free(void *p)
slouken@481
  1021
{
slouken@481
  1022
  MZ_FREE(p);
slouken@481
  1023
}
slouken@481
  1024
slouken@481
  1025
#ifndef MINIZ_NO_ZLIB_APIS
slouken@481
  1026
slouken@481
  1027
static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); }
slouken@481
  1028
static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
slouken@481
  1029
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); }
slouken@481
  1030
slouken@481
  1031
const char *mz_version(void)
slouken@481
  1032
{
slouken@481
  1033
  return MZ_VERSION;
slouken@481
  1034
}
slouken@481
  1035
slouken@481
  1036
int mz_deflateInit(mz_streamp pStream, int level)
slouken@481
  1037
{
slouken@481
  1038
  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
slouken@481
  1039
}
slouken@481
  1040
slouken@481
  1041
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
slouken@481
  1042
{
slouken@481
  1043
  tdefl_compressor *pComp;
slouken@481
  1044
  mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
slouken@481
  1045
slouken@481
  1046
  if (!pStream) return MZ_STREAM_ERROR;
slouken@481
  1047
  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;
slouken@481
  1048
slouken@481
  1049
  pStream->data_type = 0;
slouken@481
  1050
  pStream->adler = MZ_ADLER32_INIT;
slouken@481
  1051
  pStream->msg = NULL;
slouken@481
  1052
  pStream->reserved = 0;
slouken@481
  1053
  pStream->total_in = 0;
slouken@481
  1054
  pStream->total_out = 0;
slouken@481
  1055
  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
slouken@481
  1056
  if (!pStream->zfree) pStream->zfree = def_free_func;
slouken@481
  1057
slouken@481
  1058
  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
slouken@481
  1059
  if (!pComp)
slouken@481
  1060
    return MZ_MEM_ERROR;
slouken@481
  1061
slouken@481
  1062
  pStream->state = (struct mz_internal_state *)pComp;
slouken@481
  1063
slouken@481
  1064
  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
slouken@481
  1065
  {
slouken@481
  1066
    mz_deflateEnd(pStream);
slouken@481
  1067
    return MZ_PARAM_ERROR;
slouken@481
  1068
  }
slouken@481
  1069
slouken@481
  1070
  return MZ_OK;
slouken@481
  1071
}
slouken@481
  1072
slouken@481
  1073
int mz_deflateReset(mz_streamp pStream)
slouken@481
  1074
{
slouken@481
  1075
  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
slouken@481
  1076
  pStream->total_in = pStream->total_out = 0;
slouken@481
  1077
  tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
slouken@481
  1078
  return MZ_OK;
slouken@481
  1079
}
slouken@481
  1080
slouken@481
  1081
int mz_deflate(mz_streamp pStream, int flush)
slouken@481
  1082
{
slouken@481
  1083
  size_t in_bytes, out_bytes;
slouken@481
  1084
  mz_ulong orig_total_in, orig_total_out;
slouken@481
  1085
  int mz_status = MZ_OK;
slouken@481
  1086
slouken@481
  1087
  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
slouken@481
  1088
  if (!pStream->avail_out) return MZ_BUF_ERROR;
slouken@481
  1089
slouken@481
  1090
  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
slouken@481
  1091
slouken@481
  1092
  if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
slouken@481
  1093
    return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
slouken@481
  1094
slouken@481
  1095
  orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
slouken@481
  1096
  for ( ; ; )
slouken@481
  1097
  {
slouken@481
  1098
    tdefl_status defl_status;
slouken@481
  1099
    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
slouken@481
  1100
slouken@481
  1101
    defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
slouken@481
  1102
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
slouken@481
  1103
    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
slouken@481
  1104
slouken@481
  1105
    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
slouken@481
  1106
    pStream->total_out += (mz_uint)out_bytes;
slouken@481
  1107
slouken@481
  1108
    if (defl_status < 0)
slouken@481
  1109
    {
slouken@481
  1110
      mz_status = MZ_STREAM_ERROR;
slouken@481
  1111
      break;
slouken@481
  1112
    }
slouken@481
  1113
    else if (defl_status == TDEFL_STATUS_DONE)
slouken@481
  1114
    {
slouken@481
  1115
      mz_status = MZ_STREAM_END;
slouken@481
  1116
      break;
slouken@481
  1117
    }
slouken@481
  1118
    else if (!pStream->avail_out)
slouken@481
  1119
      break;
slouken@481
  1120
    else if ((!pStream->avail_in) && (flush != MZ_FINISH))
slouken@481
  1121
    {
slouken@481
  1122
      if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
slouken@481
  1123
        break;
slouken@481
  1124
      return MZ_BUF_ERROR; // Can't make forward progress without some input.
slouken@481
  1125
    }
slouken@481
  1126
  }
slouken@481
  1127
  return mz_status;
slouken@481
  1128
}
slouken@481
  1129
slouken@481
  1130
int mz_deflateEnd(mz_streamp pStream)
slouken@481
  1131
{
slouken@481
  1132
  if (!pStream) return MZ_STREAM_ERROR;
slouken@481
  1133
  if (pStream->state)
slouken@481
  1134
  {
slouken@481
  1135
    pStream->zfree(pStream->opaque, pStream->state);
slouken@481
  1136
    pStream->state = NULL;
slouken@481
  1137
  }
slouken@481
  1138
  return MZ_OK;
slouken@481
  1139
}
slouken@481
  1140
slouken@481
  1141
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
slouken@481
  1142
{
slouken@481
  1143
  (void)pStream;
slouken@481
  1144
  // 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.)
slouken@481
  1145
  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
slouken@481
  1146
}
slouken@481
  1147
slouken@481
  1148
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
slouken@481
  1149
{
slouken@481
  1150
  int status;
slouken@481
  1151
  mz_stream stream;
slouken@481
  1152
  memset(&stream, 0, sizeof(stream));
slouken@481
  1153
slouken@481
  1154
  // In case mz_ulong is 64-bits (argh I hate longs).
slouken@481
  1155
  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
slouken@481
  1156
slouken@481
  1157
  stream.next_in = pSource;
slouken@481
  1158
  stream.avail_in = (mz_uint32)source_len;
slouken@481
  1159
  stream.next_out = pDest;
slouken@481
  1160
  stream.avail_out = (mz_uint32)*pDest_len;
slouken@481
  1161
slouken@481
  1162
  status = mz_deflateInit(&stream, level);
slouken@481
  1163
  if (status != MZ_OK) return status;
slouken@481
  1164
slouken@481
  1165
  status = mz_deflate(&stream, MZ_FINISH);
slouken@481
  1166
  if (status != MZ_STREAM_END)
slouken@481
  1167
  {
slouken@481
  1168
    mz_deflateEnd(&stream);
slouken@481
  1169
    return (status == MZ_OK) ? MZ_BUF_ERROR : status;
slouken@481
  1170
  }
slouken@481
  1171
slouken@481
  1172
  *pDest_len = stream.total_out;
slouken@481
  1173
  return mz_deflateEnd(&stream);
slouken@481
  1174
}
slouken@481
  1175
slouken@481
  1176
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
slouken@481
  1177
{
slouken@481
  1178
  return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
slouken@481
  1179
}
slouken@481
  1180
slouken@481
  1181
mz_ulong mz_compressBound(mz_ulong source_len)
slouken@481
  1182
{
slouken@481
  1183
  return mz_deflateBound(NULL, source_len);
slouken@481
  1184
}
slouken@481
  1185
slouken@481
  1186
typedef struct
slouken@481
  1187
{
slouken@481
  1188
  tinfl_decompressor m_decomp;
slouken@481
  1189
  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
slouken@481
  1190
  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
slouken@481
  1191
  tinfl_status m_last_status;
slouken@481
  1192
} inflate_state;
slouken@481
  1193
slouken@481
  1194
int mz_inflateInit2(mz_streamp pStream, int window_bits)
slouken@481
  1195
{
slouken@481
  1196
  inflate_state *pDecomp;
slouken@481
  1197
  if (!pStream) return MZ_STREAM_ERROR;
slouken@481
  1198
  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
slouken@481
  1199
slouken@481
  1200
  pStream->data_type = 0;
slouken@481
  1201
  pStream->adler = 0;
slouken@481
  1202
  pStream->msg = NULL;
slouken@481
  1203
  pStream->total_in = 0;
slouken@481
  1204
  pStream->total_out = 0;
slouken@481
  1205
  pStream->reserved = 0;
slouken@481
  1206
  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
slouken@481
  1207
  if (!pStream->zfree) pStream->zfree = def_free_func;
slouken@481
  1208
slouken@481
  1209
  pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
slouken@481
  1210
  if (!pDecomp) return MZ_MEM_ERROR;
slouken@481
  1211
slouken@481
  1212
  pStream->state = (struct mz_internal_state *)pDecomp;
slouken@481
  1213
slouken@481
  1214
  tinfl_init(&pDecomp->m_decomp);
slouken@481
  1215
  pDecomp->m_dict_ofs = 0;
slouken@481
  1216
  pDecomp->m_dict_avail = 0;
slouken@481
  1217
  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
slouken@481
  1218
  pDecomp->m_first_call = 1;
slouken@481
  1219
  pDecomp->m_has_flushed = 0;
slouken@481
  1220
  pDecomp->m_window_bits = window_bits;
slouken@481
  1221
slouken@481
  1222
  return MZ_OK;
slouken@481
  1223
}
slouken@481
  1224
slouken@481
  1225
int mz_inflateInit(mz_streamp pStream)
slouken@481
  1226
{
slouken@481
  1227
   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
slouken@481
  1228
}
slouken@481
  1229
slouken@481
  1230
int mz_inflate(mz_streamp pStream, int flush)
slouken@481
  1231
{
slouken@481
  1232
  inflate_state* pState;
slouken@481
  1233
  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
slouken@481
  1234
  size_t in_bytes, out_bytes, orig_avail_in;
slouken@481
  1235
  tinfl_status status;
slouken@481
  1236
slouken@481
  1237
  if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
slouken@481
  1238
  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
slouken@481
  1239
  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
slouken@481
  1240
slouken@481
  1241
  pState = (inflate_state*)pStream->state;
slouken@481
  1242
  if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
slouken@481
  1243
  orig_avail_in = pStream->avail_in;
slouken@481
  1244
slouken@481
  1245
  first_call = pState->m_first_call; pState->m_first_call = 0;
slouken@481
  1246
  if (pState->m_last_status < 0) return MZ_DATA_ERROR;
slouken@481
  1247
slouken@481
  1248
  if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
slouken@481
  1249
  pState->m_has_flushed |= (flush == MZ_FINISH);
slouken@481
  1250
slouken@481
  1251
  if ((flush == MZ_FINISH) && (first_call))
slouken@481
  1252
  {
slouken@481
  1253
    // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file.
slouken@481
  1254
    decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
slouken@481
  1255
    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
slouken@481
  1256
    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
slouken@481
  1257
    pState->m_last_status = status;
slouken@481
  1258
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
slouken@481
  1259
    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
slouken@481
  1260
    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
slouken@481
  1261
slouken@481
  1262
    if (status < 0)
slouken@481
  1263
      return MZ_DATA_ERROR;
slouken@481
  1264
    else if (status != TINFL_STATUS_DONE)
slouken@481
  1265
    {
slouken@481
  1266
      pState->m_last_status = TINFL_STATUS_FAILED;
slouken@481
  1267
      return MZ_BUF_ERROR;
slouken@481
  1268
    }
slouken@481
  1269
    return MZ_STREAM_END;
slouken@481
  1270
  }
slouken@481
  1271
  // flush != MZ_FINISH then we must assume there's more input.
slouken@481
  1272
  if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
slouken@481
  1273
slouken@481
  1274
  if (pState->m_dict_avail)
slouken@481
  1275
  {
slouken@481
  1276
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
slouken@481
  1277
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
slouken@481
  1278
    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
slouken@481
  1279
    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
slouken@481
  1280
    return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
slouken@481
  1281
  }
slouken@481
  1282
slouken@481
  1283
  for ( ; ; )
slouken@481
  1284
  {
slouken@481
  1285
    in_bytes = pStream->avail_in;
slouken@481
  1286
    out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
slouken@481
  1287
slouken@481
  1288
    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);
slouken@481
  1289
    pState->m_last_status = status;
slouken@481
  1290
slouken@481
  1291
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
slouken@481
  1292
    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
slouken@481
  1293
slouken@481
  1294
    pState->m_dict_avail = (mz_uint)out_bytes;
slouken@481
  1295
slouken@481
  1296
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
slouken@481
  1297
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
slouken@481
  1298
    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
slouken@481
  1299
    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
slouken@481
  1300
slouken@481
  1301
    if (status < 0)
slouken@481
  1302
       return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
slouken@481
  1303
    else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
slouken@481
  1304
      return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH.
slouken@481
  1305
    else if (flush == MZ_FINISH)
slouken@481
  1306
    {
slouken@481
  1307
       // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
slouken@481
  1308
       if (status == TINFL_STATUS_DONE)
slouken@481
  1309
          return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
slouken@481
  1310
       // 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.
slouken@481
  1311
       else if (!pStream->avail_out)
slouken@481
  1312
          return MZ_BUF_ERROR;
slouken@481
  1313
    }
slouken@481
  1314
    else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
slouken@481
  1315
      break;
slouken@481
  1316
  }
slouken@481
  1317
slouken@481
  1318
  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
slouken@481
  1319
}
slouken@481
  1320
slouken@481
  1321
int mz_inflateEnd(mz_streamp pStream)
slouken@481
  1322
{
slouken@481
  1323
  if (!pStream)
slouken@481
  1324
    return MZ_STREAM_ERROR;
slouken@481
  1325
  if (pStream->state)
slouken@481
  1326
  {
slouken@481
  1327
    pStream->zfree(pStream->opaque, pStream->state);
slouken@481
  1328
    pStream->state = NULL;
slouken@481
  1329
  }
slouken@481
  1330
  return MZ_OK;
slouken@481
  1331
}
slouken@481
  1332
slouken@481
  1333
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
slouken@481
  1334
{
slouken@481
  1335
  mz_stream stream;
slouken@481
  1336
  int status;
slouken@481
  1337
  memset(&stream, 0, sizeof(stream));
slouken@481
  1338
slouken@481
  1339
  // In case mz_ulong is 64-bits (argh I hate longs).
slouken@481
  1340
  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
slouken@481
  1341
slouken@481
  1342
  stream.next_in = pSource;
slouken@481
  1343
  stream.avail_in = (mz_uint32)source_len;
slouken@481
  1344
  stream.next_out = pDest;
slouken@481
  1345
  stream.avail_out = (mz_uint32)*pDest_len;
slouken@481
  1346
slouken@481
  1347
  status = mz_inflateInit(&stream);
slouken@481
  1348
  if (status != MZ_OK)
slouken@481
  1349
    return status;
slouken@481
  1350
slouken@481
  1351
  status = mz_inflate(&stream, MZ_FINISH);
slouken@481
  1352
  if (status != MZ_STREAM_END)
slouken@481
  1353
  {
slouken@481
  1354
    mz_inflateEnd(&stream);
slouken@481
  1355
    return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
slouken@481
  1356
  }
slouken@481
  1357
  *pDest_len = stream.total_out;
slouken@481
  1358
slouken@481
  1359
  return mz_inflateEnd(&stream);
slouken@481
  1360
}
slouken@481
  1361
slouken@481
  1362
const char *mz_error(int err)
slouken@481
  1363
{
slouken@481
  1364
  static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
slouken@481
  1365
  {
slouken@481
  1366
    { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
slouken@481
  1367
    { 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" }
slouken@481
  1368
  };
slouken@481
  1369
  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;
slouken@481
  1370
  return NULL;
slouken@481
  1371
}
slouken@481
  1372
slouken@481
  1373
#endif //MINIZ_NO_ZLIB_APIS
slouken@481
  1374
slouken@481
  1375
// ------------------- Low-level Decompression (completely independent from all compression API's)
slouken@481
  1376
slouken@481
  1377
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
slouken@481
  1378
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
slouken@481
  1379
slouken@481
  1380
#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
slouken@481
  1381
#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
slouken@481
  1382
#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
slouken@481
  1383
#define TINFL_CR_FINISH }
slouken@481
  1384
slouken@481
  1385
// 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
slouken@481
  1386
// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
slouken@481
  1387
#define TINFL_GET_BYTE(state_index, c) do { \
slouken@481
  1388
  if (pIn_buf_cur >= pIn_buf_end) { \
slouken@481
  1389
    for ( ; ; ) { \
slouken@481
  1390
      if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
slouken@481
  1391
        TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
slouken@481
  1392
        if (pIn_buf_cur < pIn_buf_end) { \
slouken@481
  1393
          c = *pIn_buf_cur++; \
slouken@481
  1394
          break; \
slouken@481
  1395
        } \
slouken@481
  1396
      } else { \
slouken@481
  1397
        c = 0; \
slouken@481
  1398
        break; \
slouken@481
  1399
      } \
slouken@481
  1400
    } \
slouken@481
  1401
  } else c = *pIn_buf_cur++; } MZ_MACRO_END
slouken@481
  1402
slouken@481
  1403
#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))
slouken@481
  1404
#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
slouken@481
  1405
#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
slouken@481
  1406
slouken@481
  1407
// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
slouken@481
  1408
// 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
slouken@481
  1409
// 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
slouken@481
  1410
// bit buffer contains >=15 bits (deflate's max. Huffman code size).
slouken@481
  1411
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
slouken@481
  1412
  do { \
slouken@481
  1413
    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
slouken@481
  1414
    if (temp >= 0) { \
slouken@481
  1415
      code_len = temp >> 9; \
slouken@481
  1416
      if ((code_len) && (num_bits >= code_len)) \
slouken@481
  1417
      break; \
slouken@481
  1418
    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
slouken@481
  1419
       code_len = TINFL_FAST_LOOKUP_BITS; \
slouken@481
  1420
       do { \
slouken@481
  1421
          temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
slouken@481
  1422
       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
slouken@481
  1423
    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
slouken@481
  1424
  } while (num_bits < 15);
slouken@481
  1425
slouken@481
  1426
// 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
slouken@481
  1427
// 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
slouken@481
  1428
// 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.
slouken@481
  1429
// The slow path is only executed at the very end of the input buffer.
slouken@481
  1430
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
slouken@481
  1431
  int temp; mz_uint code_len, c; \
slouken@481
  1432
  if (num_bits < 15) { \
slouken@481
  1433
    if ((pIn_buf_end - pIn_buf_cur) < 2) { \
slouken@481
  1434
       TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
slouken@481
  1435
    } else { \
slouken@481
  1436
       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; \
slouken@481
  1437
    } \
slouken@481
  1438
  } \
slouken@481
  1439
  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
slouken@481
  1440
    code_len = temp >> 9, temp &= 511; \
slouken@481
  1441
  else { \
slouken@481
  1442
    code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
slouken@481
  1443
  } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
slouken@481
  1444
slouken@481
  1445
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)
slouken@481
  1446
{
slouken@481
  1447
  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 };
slouken@481
  1448
  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 };
slouken@481
  1449
  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};
slouken@481
  1450
  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};
slouken@481
  1451
  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 };
slouken@481
  1452
  static const int s_min_table_sizes[3] = { 257, 1, 4 };
slouken@481
  1453
slouken@481
  1454
  tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
slouken@481
  1455
  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
slouken@481
  1456
  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
slouken@481
  1457
  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;
slouken@481
  1458
slouken@481
  1459
  // 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).
slouken@481
  1460
  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; }
slouken@481
  1461
slouken@481
  1462
  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;
slouken@481
  1463
  TINFL_CR_BEGIN
slouken@481
  1464
slouken@481
  1465
  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
slouken@481
  1466
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
slouken@481
  1467
  {
slouken@481
  1468
    TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
slouken@481
  1469
    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
slouken@481
  1470
    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)))));
slouken@481
  1471
    if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
slouken@481
  1472
  }
slouken@481
  1473
slouken@481
  1474
  do
slouken@481
  1475
  {
slouken@481
  1476
    TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
slouken@481
  1477
    if (r->m_type == 0)
slouken@481
  1478
    {
slouken@481
  1479
      TINFL_SKIP_BITS(5, num_bits & 7);
slouken@481
  1480
      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]); }
slouken@481
  1481
      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); }
slouken@481
  1482
      while ((counter) && (num_bits))
slouken@481
  1483
      {
slouken@481
  1484
        TINFL_GET_BITS(51, dist, 8);
slouken@481
  1485
        while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1486
        *pOut_buf_cur++ = (mz_uint8)dist;
slouken@481
  1487
        counter--;
slouken@481
  1488
      }
slouken@481
  1489
      while (counter)
slouken@481
  1490
      {
slouken@481
  1491
        size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1492
        while (pIn_buf_cur >= pIn_buf_end)
slouken@481
  1493
        {
slouken@481
  1494
          if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
slouken@481
  1495
          {
slouken@481
  1496
            TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
slouken@481
  1497
          }
slouken@481
  1498
          else
slouken@481
  1499
          {
slouken@481
  1500
            TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
slouken@481
  1501
          }
slouken@481
  1502
        }
slouken@481
  1503
        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
slouken@481
  1504
        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
slouken@481
  1505
      }
slouken@481
  1506
    }
slouken@481
  1507
    else if (r->m_type == 3)
slouken@481
  1508
    {
slouken@481
  1509
      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
slouken@481
  1510
    }
slouken@481
  1511
    else
slouken@481
  1512
    {
slouken@481
  1513
      if (r->m_type == 1)
slouken@481
  1514
      {
slouken@481
  1515
        mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
slouken@481
  1516
        r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
slouken@481
  1517
        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;
slouken@481
  1518
      }
slouken@481
  1519
      else
slouken@481
  1520
      {
slouken@481
  1521
        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]; }
slouken@481
  1522
        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; }
slouken@481
  1523
        r->m_table_sizes[2] = 19;
slouken@481
  1524
      }
slouken@481
  1525
      for ( ; (int)r->m_type >= 0; r->m_type--)
slouken@481
  1526
      {
slouken@481
  1527
        int tree_next, tree_cur; tinfl_huff_table *pTable;
slouken@481
  1528
        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);
slouken@481
  1529
        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
slouken@481
  1530
        used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
slouken@481
  1531
        for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
slouken@481
  1532
        if ((65536 != total) && (used_syms > 1))
slouken@481
  1533
        {
slouken@481
  1534
          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
slouken@481
  1535
        }
slouken@481
  1536
        for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
slouken@481
  1537
        {
slouken@481
  1538
          mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
slouken@481
  1539
          cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
slouken@481
  1540
          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; }
slouken@481
  1541
          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; }
slouken@481
  1542
          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
slouken@481
  1543
          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
slouken@481
  1544
          {
slouken@481
  1545
            tree_cur -= ((rev_code >>= 1) & 1);
slouken@481
  1546
            if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
slouken@481
  1547
          }
slouken@481
  1548
          tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
slouken@481
  1549
        }
slouken@481
  1550
        if (r->m_type == 2)
slouken@481
  1551
        {
slouken@481
  1552
          for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
slouken@481
  1553
          {
slouken@481
  1554
            mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
slouken@481
  1555
            if ((dist == 16) && (!counter))
slouken@481
  1556
            {
slouken@481
  1557
              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
slouken@481
  1558
            }
slouken@481
  1559
            num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
slouken@481
  1560
            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
slouken@481
  1561
          }
slouken@481
  1562
          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
slouken@481
  1563
          {
slouken@481
  1564
            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
slouken@481
  1565
          }
slouken@481
  1566
          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]);
slouken@481
  1567
        }
slouken@481
  1568
      }
slouken@481
  1569
      for ( ; ; )
slouken@481
  1570
      {
slouken@481
  1571
        mz_uint8 *pSrc;
slouken@481
  1572
        for ( ; ; )
slouken@481
  1573
        {
slouken@481
  1574
          if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
slouken@481
  1575
          {
slouken@481
  1576
            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
slouken@481
  1577
            if (counter >= 256)
slouken@481
  1578
              break;
slouken@481
  1579
            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1580
            *pOut_buf_cur++ = (mz_uint8)counter;
slouken@481
  1581
          }
slouken@481
  1582
          else
slouken@481
  1583
          {
slouken@481
  1584
            int sym2; mz_uint code_len;
slouken@481
  1585
#if TINFL_USE_64BIT_BITBUF
slouken@481
  1586
            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; }
slouken@481
  1587
#else
slouken@481
  1588
            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; }
slouken@481
  1589
#endif
slouken@481
  1590
            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
slouken@481
  1591
              code_len = sym2 >> 9;
slouken@481
  1592
            else
slouken@481
  1593
            {
slouken@481
  1594
              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
slouken@481
  1595
            }
slouken@481
  1596
            counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
slouken@481
  1597
            if (counter & 256)
slouken@481
  1598
              break;
slouken@481
  1599
slouken@481
  1600
#if !TINFL_USE_64BIT_BITBUF
slouken@481
  1601
            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; }
slouken@481
  1602
#endif
slouken@481
  1603
            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
slouken@481
  1604
              code_len = sym2 >> 9;
slouken@481
  1605
            else
slouken@481
  1606
            {
slouken@481
  1607
              code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
slouken@481
  1608
            }
slouken@481
  1609
            bit_buf >>= code_len; num_bits -= code_len;
slouken@481
  1610
slouken@481
  1611
            pOut_buf_cur[0] = (mz_uint8)counter;
slouken@481
  1612
            if (sym2 & 256)
slouken@481
  1613
            {
slouken@481
  1614
              pOut_buf_cur++;
slouken@481
  1615
              counter = sym2;
slouken@481
  1616
              break;
slouken@481
  1617
            }
slouken@481
  1618
            pOut_buf_cur[1] = (mz_uint8)sym2;
slouken@481
  1619
            pOut_buf_cur += 2;
slouken@481
  1620
          }
slouken@481
  1621
        }
slouken@481
  1622
        if ((counter &= 511) == 256) break;
slouken@481
  1623
slouken@481
  1624
        num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
slouken@481
  1625
        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
slouken@481
  1626
slouken@481
  1627
        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
slouken@481
  1628
        num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
slouken@481
  1629
        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
slouken@481
  1630
slouken@481
  1631
        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
slouken@481
  1632
        if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
slouken@481
  1633
        {
slouken@481
  1634
          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
slouken@481
  1635
        }
slouken@481
  1636
slouken@481
  1637
        pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
slouken@481
  1638
slouken@481
  1639
        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
slouken@481
  1640
        {
slouken@481
  1641
          while (counter--)
slouken@481
  1642
          {
slouken@481
  1643
            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1644
            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
slouken@481
  1645
          }
slouken@481
  1646
          continue;
slouken@481
  1647
        }
slouken@481
  1648
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
slouken@481
  1649
        else if ((counter >= 9) && (counter <= dist))
slouken@481
  1650
        {
slouken@481
  1651
          const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
slouken@481
  1652
          do
slouken@481
  1653
          {
slouken@481
  1654
            ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
slouken@481
  1655
            ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
slouken@481
  1656
            pOut_buf_cur += 8;
slouken@481
  1657
          } while ((pSrc += 8) < pSrc_end);
slouken@481
  1658
          if ((counter &= 7) < 3)
slouken@481
  1659
          {
slouken@481
  1660
            if (counter)
slouken@481
  1661
            {
slouken@481
  1662
              pOut_buf_cur[0] = pSrc[0];
slouken@481
  1663
              if (counter > 1)
slouken@481
  1664
                pOut_buf_cur[1] = pSrc[1];
slouken@481
  1665
              pOut_buf_cur += counter;
slouken@481
  1666
            }
slouken@481
  1667
            continue;
slouken@481
  1668
          }
slouken@481
  1669
        }
slouken@481
  1670
#endif
slouken@481
  1671
        do
slouken@481
  1672
        {
slouken@481
  1673
          pOut_buf_cur[0] = pSrc[0];
slouken@481
  1674
          pOut_buf_cur[1] = pSrc[1];
slouken@481
  1675
          pOut_buf_cur[2] = pSrc[2];
slouken@481
  1676
          pOut_buf_cur += 3; pSrc += 3;
slouken@481
  1677
        } while ((int)(counter -= 3) > 2);
slouken@481
  1678
        if ((int)counter > 0)
slouken@481
  1679
        {
slouken@481
  1680
          pOut_buf_cur[0] = pSrc[0];
slouken@481
  1681
          if ((int)counter > 1)
slouken@481
  1682
            pOut_buf_cur[1] = pSrc[1];
slouken@481
  1683
          pOut_buf_cur += counter;
slouken@481
  1684
        }
slouken@481
  1685
      }
slouken@481
  1686
    }
slouken@481
  1687
  } while (!(r->m_final & 1));
slouken@481
  1688
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
slouken@481
  1689
  {
slouken@481
  1690
    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; }
slouken@481
  1691
  }
slouken@481
  1692
  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
slouken@481
  1693
  TINFL_CR_FINISH
slouken@481
  1694
slouken@481
  1695
common_exit:
slouken@481
  1696
  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;
slouken@481
  1697
  *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
slouken@481
  1698
  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
slouken@481
  1699
  {
slouken@481
  1700
    const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
slouken@481
  1701
    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
slouken@481
  1702
    while (buf_len)
slouken@481
  1703
    {
slouken@481
  1704
      for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
slouken@481
  1705
      {
slouken@481
  1706
        s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
slouken@481
  1707
        s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
slouken@481
  1708
      }
slouken@481
  1709
      for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
slouken@481
  1710
      s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
slouken@481
  1711
    }
slouken@481
  1712
    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;
slouken@481
  1713
  }
slouken@481
  1714
  return status;
slouken@481
  1715
}
slouken@481
  1716
slouken@481
  1717
// Higher level helper functions.
slouken@481
  1718
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
slouken@481
  1719
{
slouken@481
  1720
  tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
slouken@481
  1721
  *pOut_len = 0;
slouken@481
  1722
  tinfl_init(&decomp);
slouken@481
  1723
  for ( ; ; )
slouken@481
  1724
  {
slouken@481
  1725
    size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
slouken@481
  1726
    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,
slouken@481
  1727
      (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
slouken@481
  1728
    if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
slouken@481
  1729
    {
slouken@481
  1730
      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
slouken@481
  1731
    }
slouken@481
  1732
    src_buf_ofs += src_buf_size;
slouken@481
  1733
    *pOut_len += dst_buf_size;
slouken@481
  1734
    if (status == TINFL_STATUS_DONE) break;
slouken@481
  1735
    new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
slouken@481
  1736
    pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
slouken@481
  1737
    if (!pNew_buf)
slouken@481
  1738
    {
slouken@481
  1739
      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
slouken@481
  1740
    }
slouken@481
  1741
    pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
slouken@481
  1742
  }
slouken@481
  1743
  return pBuf;
slouken@481
  1744
}
slouken@481
  1745
slouken@481
  1746
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)
slouken@481
  1747
{
slouken@481
  1748
  tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
slouken@481
  1749
  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);
slouken@481
  1750
  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
slouken@481
  1751
}
slouken@481
  1752
slouken@481
  1753
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)
slouken@481
  1754
{
slouken@481
  1755
  int result = 0;
slouken@481
  1756
  tinfl_decompressor decomp;
slouken@481
  1757
  mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
slouken@481
  1758
  if (!pDict)
slouken@481
  1759
    return TINFL_STATUS_FAILED;
slouken@481
  1760
  tinfl_init(&decomp);
slouken@481
  1761
  for ( ; ; )
slouken@481
  1762
  {
slouken@481
  1763
    size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
slouken@481
  1764
    tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
slouken@481
  1765
      (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
slouken@481
  1766
    in_buf_ofs += in_buf_size;
slouken@481
  1767
    if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
slouken@481
  1768
      break;
slouken@481
  1769
    if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
slouken@481
  1770
    {
slouken@481
  1771
      result = (status == TINFL_STATUS_DONE);
slouken@481
  1772
      break;
slouken@481
  1773
    }
slouken@481
  1774
    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
slouken@481
  1775
  }
slouken@481
  1776
  MZ_FREE(pDict);
slouken@481
  1777
  *pIn_buf_size = in_buf_ofs;
slouken@481
  1778
  return result;
slouken@481
  1779
}
slouken@481
  1780
slouken@481
  1781
// ------------------- Low-level Compression (independent from all decompression API's)
slouken@481
  1782
slouken@481
  1783
// Purposely making these tables static for faster init and thread safety.
slouken@481
  1784
static const mz_uint16 s_tdefl_len_sym[256] = {
slouken@481
  1785
  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,
slouken@481
  1786
  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,
slouken@481
  1787
  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,
slouken@481
  1788
  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,
slouken@481
  1789
  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,
slouken@481
  1790
  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,
slouken@481
  1791
  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,
slouken@481
  1792
  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 };
slouken@481
  1793
slouken@481
  1794
static const mz_uint8 s_tdefl_len_extra[256] = {
slouken@481
  1795
  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,
slouken@481
  1796
  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,
slouken@481
  1797
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
slouken@481
  1798
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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 };
slouken@481
  1799
slouken@481
  1800
static const mz_uint8 s_tdefl_small_dist_sym[512] = {
slouken@481
  1801
  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,
slouken@481
  1802
  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,
slouken@481
  1803
  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,
slouken@481
  1804
  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,
slouken@481
  1805
  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,
slouken@481
  1806
  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,
slouken@481
  1807
  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,
slouken@481
  1808
  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,
slouken@481
  1809
  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,
slouken@481
  1810
  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,
slouken@481
  1811
  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,
slouken@481
  1812
  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 };
slouken@481
  1813
slouken@481
  1814
static const mz_uint8 s_tdefl_small_dist_extra[512] = {
slouken@481
  1815
  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,
slouken@481
  1816
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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,
slouken@481
  1817
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
slouken@481
  1818
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,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,
slouken@481
  1819
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
slouken@481
  1820
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
slouken@481
  1821
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
slouken@481
  1822
  7,7,7,7,7,7,7,7 };
slouken@481
  1823
slouken@481
  1824
static const mz_uint8 s_tdefl_large_dist_sym[128] = {
slouken@481
  1825
  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,
slouken@481
  1826
  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,
slouken@481
  1827
  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 };
slouken@481
  1828
slouken@481
  1829
static const mz_uint8 s_tdefl_large_dist_extra[128] = {
slouken@481
  1830
  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,
slouken@481
  1831
  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,
slouken@481
  1832
  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 };
slouken@481
  1833
slouken@481
  1834
// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
slouken@481
  1835
typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
slouken@481
  1836
static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
slouken@481
  1837
{
slouken@481
  1838
  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);
slouken@481
  1839
  for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
slouken@481
  1840
  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
slouken@481
  1841
  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
slouken@481
  1842
  {
slouken@481
  1843
    const mz_uint32* pHist = &hist[pass << 8];
slouken@481
  1844
    mz_uint offsets[256], cur_ofs = 0;
slouken@481
  1845
    for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
slouken@481
  1846
    for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
slouken@481
  1847
    { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
slouken@481
  1848
  }
slouken@481
  1849
  return pCur_syms;
slouken@481
  1850
}
slouken@481
  1851
slouken@481
  1852
// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
slouken@481
  1853
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
slouken@481
  1854
{
slouken@481
  1855
  int root, leaf, next, avbl, used, dpth;
slouken@481
  1856
  if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
slouken@481
  1857
  A[0].m_key += A[1].m_key; root = 0; leaf = 2;
slouken@481
  1858
  for (next=1; next < n-1; next++)
slouken@481
  1859
  {
slouken@481
  1860
    if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = (mz_uint16)next; } else A[next].m_key = A[leaf++].m_key;
slouken@481
  1861
    if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); A[root++].m_key = (mz_uint16)next; } else A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
slouken@481
  1862
  }
slouken@481
  1863
  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;
slouken@481
  1864
  avbl = 1; used = dpth = 0; root = n-2; next = n-1;
slouken@481
  1865
  while (avbl>0)
slouken@481
  1866
  {
slouken@481
  1867
    while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
slouken@481
  1868
    while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
slouken@481
  1869
    avbl = 2*used; dpth++; used = 0;
slouken@481
  1870
  }
slouken@481
  1871
}
slouken@481
  1872
slouken@481
  1873
// Limits canonical Huffman code table's max code size.
slouken@481
  1874
enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
slouken@481
  1875
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
slouken@481
  1876
{
slouken@481
  1877
  int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
slouken@481
  1878
  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
slouken@481
  1879
  for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
slouken@481
  1880
  while (total != (1UL << max_code_size))
slouken@481
  1881
  {
slouken@481
  1882
    pNum_codes[max_code_size]--;
slouken@481
  1883
    for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
slouken@481
  1884
    total--;
slouken@481
  1885
  }
slouken@481
  1886
}
slouken@481
  1887
slouken@481
  1888
static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
slouken@481
  1889
{
slouken@481
  1890
  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);
slouken@481
  1891
  if (static_table)
slouken@481
  1892
  {
slouken@481
  1893
    for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
slouken@481
  1894
  }
slouken@481
  1895
  else
slouken@481
  1896
  {
slouken@481
  1897
    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
slouken@481
  1898
    int num_used_syms = 0;
slouken@481
  1899
    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
slouken@481
  1900
    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; }
slouken@481
  1901
slouken@481
  1902
    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
slouken@481
  1903
slouken@481
  1904
    for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
slouken@481
  1905
slouken@481
  1906
    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
slouken@481
  1907
slouken@481
  1908
    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
slouken@481
  1909
    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
slouken@481
  1910
      for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
slouken@481
  1911
  }
slouken@481
  1912
slouken@481
  1913
  next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
slouken@481
  1914
slouken@481
  1915
  for (i = 0; i < table_len; i++)
slouken@481
  1916
  {
slouken@481
  1917
    mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
slouken@481
  1918
    code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
slouken@481
  1919
    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
slouken@481
  1920
  }
slouken@481
  1921
}
slouken@481
  1922
slouken@481
  1923
#define TDEFL_PUT_BITS(b, l) do { \
slouken@481
  1924
  mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
slouken@481
  1925
  d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
slouken@481
  1926
  while (d->m_bits_in >= 8) { \
slouken@481
  1927
    if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
slouken@481
  1928
      *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
slouken@481
  1929
      d->m_bit_buffer >>= 8; \
slouken@481
  1930
      d->m_bits_in -= 8; \
slouken@481
  1931
  } \
slouken@481
  1932
} MZ_MACRO_END
slouken@481
  1933
slouken@481
  1934
#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
slouken@481
  1935
  if (rle_repeat_count < 3) { \
slouken@481
  1936
    d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
slouken@481
  1937
    while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
slouken@481
  1938
  } else { \
slouken@481
  1939
    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); \
slouken@481
  1940
} rle_repeat_count = 0; } }
slouken@481
  1941
slouken@481
  1942
#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
slouken@481
  1943
  if (rle_z_count < 3) { \
slouken@481
  1944
    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; \
slouken@481
  1945
  } else if (rle_z_count <= 10) { \
slouken@481
  1946
    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); \
slouken@481
  1947
  } else { \
slouken@481
  1948
    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); \
slouken@481
  1949
} rle_z_count = 0; } }
slouken@481
  1950
slouken@481
  1951
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 };
slouken@481
  1952
slouken@481
  1953
static void tdefl_start_dynamic_block(tdefl_compressor *d)
slouken@481
  1954
{
slouken@481
  1955
  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;
slouken@481
  1956
  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;
slouken@481
  1957
slouken@481
  1958
  d->m_huff_count[0][256] = 1;
slouken@481
  1959
slouken@481
  1960
  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
slouken@481
  1961
  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
slouken@481
  1962
slouken@481
  1963
  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break;
slouken@481
  1964
  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break;
slouken@481
  1965
slouken@481
  1966
  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
slouken@481
  1967
  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
slouken@481
  1968
  total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0;
slouken@481
  1969
slouken@481
  1970
  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
slouken@481
  1971
  for (i = 0; i < total_code_sizes_to_pack; i++)
slouken@481
  1972
  {
slouken@481
  1973
    mz_uint8 code_size = code_sizes_to_pack[i];
slouken@481
  1974
    if (!code_size)
slouken@481
  1975
    {
slouken@481
  1976
      TDEFL_RLE_PREV_CODE_SIZE();
slouken@481
  1977
      if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
slouken@481
  1978
    }
slouken@481
  1979
    else
slouken@481
  1980
    {
slouken@481
  1981
      TDEFL_RLE_ZERO_CODE_SIZE();
slouken@481
  1982
      if (code_size != prev_code_size)
slouken@481
  1983
      {
slouken@481
  1984
        TDEFL_RLE_PREV_CODE_SIZE();
slouken@481
  1985
        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;
slouken@481
  1986
      }
slouken@481
  1987
      else if (++rle_repeat_count == 6)
slouken@481
  1988
      {
slouken@481
  1989
        TDEFL_RLE_PREV_CODE_SIZE();
slouken@481
  1990
      }
slouken@481
  1991
    }
slouken@481
  1992
    prev_code_size = code_size;
slouken@481
  1993
  }
slouken@481
  1994
  if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
slouken@481
  1995
slouken@481
  1996
  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
slouken@481
  1997
slouken@481
  1998
  TDEFL_PUT_BITS(2, 2);
slouken@481
  1999
slouken@481
  2000
  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
slouken@481
  2001
  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
slouken@481
  2002
slouken@481
  2003
  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;
slouken@481
  2004
  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
slouken@481
  2005
  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);
slouken@481
  2006
slouken@481
  2007
  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
slouken@481
  2008
  {
slouken@481
  2009
    mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
slouken@481
  2010
    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
slouken@481
  2011
    if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
slouken@481
  2012
  }
slouken@481
  2013
}
slouken@481
  2014
slouken@481
  2015
static void tdefl_start_static_block(tdefl_compressor *d)
slouken@481
  2016
{
slouken@481
  2017
  mz_uint i;
slouken@481
  2018
  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
slouken@481
  2019
slouken@481
  2020
  for (i = 0; i <= 143; ++i) *p++ = 8;
slouken@481
  2021
  for ( ; i <= 255; ++i) *p++ = 9;
slouken@481
  2022
  for ( ; i <= 279; ++i) *p++ = 7;
slouken@481
  2023
  for ( ; i <= 287; ++i) *p++ = 8;
slouken@481
  2024
slouken@481
  2025
  memset(d->m_huff_code_sizes[1], 5, 32);
slouken@481
  2026
slouken@481
  2027
  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
slouken@481
  2028
  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
slouken@481
  2029
slouken@481
  2030
  TDEFL_PUT_BITS(1, 2);
slouken@481
  2031
}
slouken@481
  2032
slouken@481
  2033
static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
slouken@481
  2034
slouken@481
  2035
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
slouken@481
  2036
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
slouken@481
  2037
{
slouken@481
  2038
  mz_uint flags;
slouken@481
  2039
  mz_uint8 *pLZ_codes;
slouken@481
  2040
  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
slouken@481
  2041
  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
slouken@481
  2042
  mz_uint64 bit_buffer = d->m_bit_buffer;
slouken@481
  2043
  mz_uint bits_in = d->m_bits_in;
slouken@481
  2044
slouken@481
  2045
#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
slouken@481
  2046
slouken@481
  2047
  flags = 1;
slouken@481
  2048
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
slouken@481
  2049
  {
slouken@481
  2050
    if (flags == 1)
slouken@481
  2051
      flags = *pLZ_codes++ | 0x100;
slouken@481
  2052
slouken@481
  2053
    if (flags & 1)
slouken@481
  2054
    {
slouken@481
  2055
      mz_uint s0, s1, n0, n1, sym, num_extra_bits;
slouken@481
  2056
      mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
slouken@481
  2057
slouken@481
  2058
      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
slouken@481
  2059
      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]]);
slouken@481
  2060
      TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
slouken@481
  2061
slouken@481
  2062
      // This sequence coaxes MSVC into using cmov's vs. jmp's.
slouken@481
  2063
      s0 = s_tdefl_small_dist_sym[match_dist & 511];
slouken@481
  2064
      n0 = s_tdefl_small_dist_extra[match_dist & 511];
slouken@481
  2065
      s1 = s_tdefl_large_dist_sym[match_dist >> 8];
slouken@481
  2066
      n1 = s_tdefl_large_dist_extra[match_dist >> 8];
slouken@481
  2067
      sym = (match_dist < 512) ? s0 : s1;
slouken@481
  2068
      num_extra_bits = (match_dist < 512) ? n0 : n1;
slouken@481
  2069
slouken@481
  2070
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
slouken@481
  2071
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
slouken@481
  2072
      TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
slouken@481
  2073
    }
slouken@481
  2074
    else
slouken@481
  2075
    {
slouken@481
  2076
      mz_uint lit = *pLZ_codes++;
slouken@481
  2077
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2078
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2079
slouken@481
  2080
      if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
slouken@481
  2081
      {
slouken@481
  2082
        flags >>= 1;
slouken@481
  2083
        lit = *pLZ_codes++;
slouken@481
  2084
        MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2085
        TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2086
slouken@481
  2087
        if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
slouken@481
  2088
        {
slouken@481
  2089
          flags >>= 1;
slouken@481
  2090
          lit = *pLZ_codes++;
slouken@481
  2091
          MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2092
          TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2093
        }
slouken@481
  2094
      }
slouken@481
  2095
    }
slouken@481
  2096
slouken@481
  2097
    if (pOutput_buf >= d->m_pOutput_buf_end)
slouken@481
  2098
      return MZ_FALSE;
slouken@481
  2099
slouken@481
  2100
    *(mz_uint64*)pOutput_buf = bit_buffer;
slouken@481
  2101
    pOutput_buf += (bits_in >> 3);
slouken@481
  2102
    bit_buffer >>= (bits_in & ~7);
slouken@481
  2103
    bits_in &= 7;
slouken@481
  2104
  }
slouken@481
  2105
slouken@481
  2106
#undef TDEFL_PUT_BITS_FAST
slouken@481
  2107
slouken@481
  2108
  d->m_pOutput_buf = pOutput_buf;
slouken@481
  2109
  d->m_bits_in = 0;
slouken@481
  2110
  d->m_bit_buffer = 0;
slouken@481
  2111
slouken@481
  2112
  while (bits_in)
slouken@481
  2113
  {
slouken@481
  2114
    mz_uint32 n = MZ_MIN(bits_in, 16);
slouken@481
  2115
    TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
slouken@481
  2116
    bit_buffer >>= n;
slouken@481
  2117
    bits_in -= n;
slouken@481
  2118
  }
slouken@481
  2119
slouken@481
  2120
  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
slouken@481
  2121
slouken@481
  2122
  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
slouken@481
  2123
}
slouken@481
  2124
#else
slouken@481
  2125
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
slouken@481
  2126
{
slouken@481
  2127
  mz_uint flags;
slouken@481
  2128
  mz_uint8 *pLZ_codes;
slouken@481
  2129
slouken@481
  2130
  flags = 1;
slouken@481
  2131
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
slouken@481
  2132
  {
slouken@481
  2133
    if (flags == 1)
slouken@481
  2134
      flags = *pLZ_codes++ | 0x100;
slouken@481
  2135
    if (flags & 1)
slouken@481
  2136
    {
slouken@481
  2137
      mz_uint sym, num_extra_bits;
slouken@481
  2138
      mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
slouken@481
  2139
slouken@481
  2140
      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
slouken@481
  2141
      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]]);
slouken@481
  2142
      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
slouken@481
  2143
slouken@481
  2144
      if (match_dist < 512)
slouken@481
  2145
      {
slouken@481
  2146
        sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
slouken@481
  2147
      }
slouken@481
  2148
      else
slouken@481
  2149
      {
slouken@481
  2150
        sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
slouken@481
  2151
      }
slouken@481
  2152
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
slouken@481
  2153
      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
slouken@481
  2154
      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
slouken@481
  2155
    }
slouken@481
  2156
    else
slouken@481
  2157
    {
slouken@481
  2158
      mz_uint lit = *pLZ_codes++;
slouken@481
  2159
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2160
      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2161
    }
slouken@481
  2162
  }
slouken@481
  2163
slouken@481
  2164
  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
slouken@481
  2165
slouken@481
  2166
  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
slouken@481
  2167
}
slouken@481
  2168
#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
slouken@481
  2169
slouken@481
  2170
static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
slouken@481
  2171
{
slouken@481
  2172
  if (static_block)
slouken@481
  2173
    tdefl_start_static_block(d);
slouken@481
  2174
  else
slouken@481
  2175
    tdefl_start_dynamic_block(d);
slouken@481
  2176
  return tdefl_compress_lz_codes(d);
slouken@481
  2177
}
slouken@481
  2178
slouken@481
  2179
static int tdefl_flush_block(tdefl_compressor *d, int flush)
slouken@481
  2180
{
slouken@481
  2181
  mz_uint saved_bit_buf, saved_bits_in;
slouken@481
  2182
  mz_uint8 *pSaved_output_buf;
slouken@481
  2183
  mz_bool comp_block_succeeded = MZ_FALSE;
slouken@481
  2184
  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;
slouken@481
  2185
  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;
slouken@481
  2186
slouken@481
  2187
  d->m_pOutput_buf = pOutput_buf_start;
slouken@481
  2188
  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
slouken@481
  2189
slouken@481
  2190
  MZ_ASSERT(!d->m_output_flush_remaining);
slouken@481
  2191
  d->m_output_flush_ofs = 0;
slouken@481
  2192
  d->m_output_flush_remaining = 0;
slouken@481
  2193
slouken@481
  2194
  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
slouken@481
  2195
  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
slouken@481
  2196
slouken@481
  2197
  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
slouken@481
  2198
  {
slouken@481
  2199
    TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
slouken@481
  2200
  }
slouken@481
  2201
slouken@481
  2202
  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
slouken@481
  2203
slouken@481
  2204
  pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
slouken@481
  2205
slouken@481
  2206
  if (!use_raw_block)
slouken@481
  2207
    comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
slouken@481
  2208
slouken@481
  2209
  // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
slouken@481
  2210
  if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
slouken@481
  2211
       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
slouken@481
  2212
  {
slouken@481
  2213
    mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
slouken@481
  2214
    TDEFL_PUT_BITS(0, 2);
slouken@481
  2215
    if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
slouken@481
  2216
    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
slouken@481
  2217
    {
slouken@481
  2218
      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
slouken@481
  2219
    }
slouken@481
  2220
    for (i = 0; i < d->m_total_lz_bytes; ++i)
slouken@481
  2221
    {
slouken@481
  2222
      TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
slouken@481
  2223
    }
slouken@481
  2224
  }
slouken@481
  2225
  // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes.
slouken@481
  2226
  else if (!comp_block_succeeded)
slouken@481
  2227
  {
slouken@481
  2228
    d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
slouken@481
  2229
    tdefl_compress_block(d, MZ_TRUE);
slouken@481
  2230
  }
slouken@481
  2231
slouken@481
  2232
  if (flush)
slouken@481
  2233
  {
slouken@481
  2234
    if (flush == TDEFL_FINISH)
slouken@481
  2235
    {
slouken@481
  2236
      if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
slouken@481
  2237
      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; } }
slouken@481
  2238
    }
slouken@481
  2239
    else
slouken@481
  2240
    {
slouken@481
  2241
      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); }
slouken@481
  2242
    }
slouken@481
  2243
  }
slouken@481
  2244
slouken@481
  2245
  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
slouken@481
  2246
slouken@481
  2247
  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
slouken@481
  2248
  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
slouken@481
  2249
slouken@481
  2250
  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++;
slouken@481
  2251
slouken@481
  2252
  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
slouken@481
  2253
  {
slouken@481
  2254
    if (d->m_pPut_buf_func)
slouken@481
  2255
    {
slouken@481
  2256
      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
slouken@481
  2257
      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
slouken@481
  2258
        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
slouken@481
  2259
    }
slouken@481
  2260
    else if (pOutput_buf_start == d->m_output_buf)
slouken@481
  2261
    {
slouken@481
  2262
      int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
slouken@481
  2263
      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
slouken@481
  2264
      d->m_out_buf_ofs += bytes_to_copy;
slouken@481
  2265
      if ((n -= bytes_to_copy) != 0)
slouken@481
  2266
      {
slouken@481
  2267
        d->m_output_flush_ofs = bytes_to_copy;
slouken@481
  2268
        d->m_output_flush_remaining = n;
slouken@481
  2269
      }
slouken@481
  2270
    }
slouken@481
  2271
    else
slouken@481
  2272
    {
slouken@481
  2273
      d->m_out_buf_ofs += n;
slouken@481
  2274
    }
slouken@481
  2275
  }
slouken@481
  2276
slouken@481
  2277
  return d->m_output_flush_remaining;
slouken@481
  2278
}
slouken@481
  2279
slouken@481
  2280
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
slouken@481
  2281
#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
slouken@481
  2282
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)
slouken@481
  2283
{
slouken@481
  2284
  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
slouken@481
  2285
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
slouken@481
  2286
  const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
slouken@481
  2287
  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
slouken@481
  2288
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
slouken@481
  2289
  for ( ; ; )
slouken@481
  2290
  {
slouken@481
  2291
    for ( ; ; )
slouken@481
  2292
    {
slouken@481
  2293
      if (--num_probes_left == 0) return;
slouken@481
  2294
      #define TDEFL_PROBE \
slouken@481
  2295
        next_probe_pos = d->m_next[probe_pos]; \
slouken@481
  2296
        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
slouken@481
  2297
        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
slouken@481
  2298
        if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
slouken@481
  2299
      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
slouken@481
  2300
    }
slouken@481
  2301
    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;
slouken@481
  2302
    do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
slouken@481
  2303
                   (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
slouken@481
  2304
    if (!probe_len)
slouken@481
  2305
    {
slouken@481
  2306
      *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
slouken@481
  2307
    }
slouken@481
  2308
    else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
slouken@481
  2309
    {
slouken@481
  2310
      *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
slouken@481
  2311
      c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
slouken@481
  2312
    }
slouken@481
  2313
  }
slouken@481
  2314
}
slouken@481
  2315
#else
slouken@481
  2316
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)
slouken@481
  2317
{
slouken@481
  2318
  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
slouken@481
  2319
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
slouken@481
  2320
  const mz_uint8 *s = d->m_dict + pos, *p, *q;
slouken@481
  2321
  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
slouken@481
  2322
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
slouken@481
  2323
  for ( ; ; )
slouken@481
  2324
  {
slouken@481
  2325
    for ( ; ; )
slouken@481
  2326
    {
slouken@481
  2327
      if (--num_probes_left == 0) return;
slouken@481
  2328
      #define TDEFL_PROBE \
slouken@481
  2329
        next_probe_pos = d->m_next[probe_pos]; \
slouken@481
  2330
        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
slouken@481
  2331
        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
slouken@481
  2332
        if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
slouken@481
  2333
      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
slouken@481
  2334
    }
slouken@481
  2335
    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;
slouken@481
  2336
    if (probe_len > match_len)
slouken@481
  2337
    {
slouken@481
  2338
      *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
slouken@481
  2339
      c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
slouken@481
  2340
    }
slouken@481
  2341
  }
slouken@481
  2342
}
slouken@481
  2343
#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
slouken@481
  2344
slouken@481
  2345
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
slouken@481
  2346
static mz_bool tdefl_compress_fast(tdefl_compressor *d)
slouken@481
  2347
{
slouken@481
  2348
  // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio.
slouken@481
  2349
  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;
slouken@481
  2350
  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
slouken@481
  2351
  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2352
slouken@481
  2353
  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
slouken@481
  2354
  {
slouken@481
  2355
    const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
slouken@481
  2356
    mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2357
    mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
slouken@481
  2358
    d->m_src_buf_left -= num_bytes_to_process;
slouken@481
  2359
    lookahead_size += num_bytes_to_process;
slouken@481
  2360
slouken@481
  2361
    while (num_bytes_to_process)
slouken@481
  2362
    {
slouken@481
  2363
      mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
slouken@481
  2364
      memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
slouken@481
  2365
      if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
slouken@481
  2366
        memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
slouken@481
  2367
      d->m_pSrc += n;
slouken@481
  2368
      dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2369
      num_bytes_to_process -= n;
slouken@481
  2370
    }
slouken@481
  2371
slouken@481
  2372
    dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
slouken@481
  2373
    if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
slouken@481
  2374
slouken@481
  2375
    while (lookahead_size >= 4)
slouken@481
  2376
    {
slouken@481
  2377
      mz_uint cur_match_dist, cur_match_len = 1;
slouken@481
  2378
      mz_uint8 *pCur_dict = d->m_dict + cur_pos;
slouken@481
  2379
      mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
slouken@481
  2380
      mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
slouken@481
  2381
      mz_uint probe_pos = d->m_hash[hash];
slouken@481
  2382
      d->m_hash[hash] = (mz_uint16)lookahead_pos;
slouken@481
  2383
slouken@481
  2384
      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))
slouken@481
  2385
      {
slouken@481
  2386
        const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
slouken@481
  2387
        const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
slouken@481
  2388
        mz_uint32 probe_len = 32;
slouken@481
  2389
        do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
slouken@481
  2390
          (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
slouken@481
  2391
        cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
slouken@481
  2392
        if (!probe_len)
slouken@481
  2393
          cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
slouken@481
  2394
slouken@481
  2395
        if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
slouken@481
  2396
        {
slouken@481
  2397
          cur_match_len = 1;
slouken@481
  2398
          *pLZ_code_buf++ = (mz_uint8)first_trigram;
slouken@481
  2399
          *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
slouken@481
  2400
          d->m_huff_count[0][(mz_uint8)first_trigram]++;
slouken@481
  2401
        }
slouken@481
  2402
        else
slouken@481
  2403
        {
slouken@481
  2404
          mz_uint32 s0, s1;
slouken@481
  2405
          cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
slouken@481
  2406
slouken@481
  2407
          MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
slouken@481
  2408
slouken@481
  2409
          cur_match_dist--;
slouken@481
  2410
slouken@481
  2411
          pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
slouken@481
  2412
          *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
slouken@481
  2413
          pLZ_code_buf += 3;
slouken@481
  2414
          *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
slouken@481
  2415
slouken@481
  2416
          s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
slouken@481
  2417
          s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
slouken@481
  2418
          d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
slouken@481
  2419
slouken@481
  2420
          d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
slouken@481
  2421
        }
slouken@481
  2422
      }
slouken@481
  2423
      else
slouken@481
  2424
      {
slouken@481
  2425
        *pLZ_code_buf++ = (mz_uint8)first_trigram;
slouken@481
  2426
        *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
slouken@481
  2427
        d->m_huff_count[0][(mz_uint8)first_trigram]++;
slouken@481
  2428
      }
slouken@481
  2429
slouken@481
  2430
      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
slouken@481
  2431
slouken@481
  2432
      total_lz_bytes += cur_match_len;
slouken@481
  2433
      lookahead_pos += cur_match_len;
slouken@481
  2434
      dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
slouken@481
  2435
      cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2436
      MZ_ASSERT(lookahead_size >= cur_match_len);
slouken@481
  2437
      lookahead_size -= cur_match_len;
slouken@481
  2438
slouken@481
  2439
      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
slouken@481
  2440
      {
slouken@481
  2441
        int n;
slouken@481
  2442
        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
slouken@481
  2443
        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;
slouken@481
  2444
        if ((n = tdefl_flush_block(d, 0)) != 0)
slouken@481
  2445
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
slouken@481
  2446
        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;
slouken@481
  2447
      }
slouken@481
  2448
    }
slouken@481
  2449
slouken@481
  2450
    while (lookahead_size)
slouken@481
  2451
    {
slouken@481
  2452
      mz_uint8 lit = d->m_dict[cur_pos];
slouken@481
  2453
slouken@481
  2454
      total_lz_bytes++;
slouken@481
  2455
      *pLZ_code_buf++ = lit;
slouken@481
  2456
      *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
slouken@481
  2457
      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
slouken@481
  2458
slouken@481
  2459
      d->m_huff_count[0][lit]++;
slouken@481
  2460
slouken@481
  2461
      lookahead_pos++;
slouken@481
  2462
      dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
slouken@481
  2463
      cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2464
      lookahead_size--;
slouken@481
  2465
slouken@481
  2466
      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
slouken@481
  2467
      {
slouken@481
  2468
        int n;
slouken@481
  2469
        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
slouken@481
  2470
        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;
slouken@481
  2471
        if ((n = tdefl_flush_block(d, 0)) != 0)
slouken@481
  2472
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
slouken@481
  2473
        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;
slouken@481
  2474
      }
slouken@481
  2475
    }
slouken@481
  2476
  }
slouken@481
  2477
slouken@481
  2478
  d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
slouken@481
  2479
  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;
slouken@481
  2480
  return MZ_TRUE;
slouken@481
  2481
}
slouken@481
  2482
#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
slouken@481
  2483
slouken@481
  2484
static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
slouken@481
  2485
{
slouken@481
  2486
  d->m_total_lz_bytes++;
slouken@481
  2487
  *d->m_pLZ_code_buf++ = lit;
slouken@481
  2488
  *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++; }
slouken@481
  2489
  d->m_huff_count[0][lit]++;
slouken@481
  2490
}
slouken@481
  2491
slouken@481
  2492
static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
slouken@481
  2493
{
slouken@481
  2494
  mz_uint32 s0, s1;
slouken@481
  2495
slouken@481
  2496
  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
slouken@481
  2497
slouken@481
  2498
  d->m_total_lz_bytes += match_len;
slouken@481
  2499
slouken@481
  2500
  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
slouken@481
  2501
slouken@481
  2502
  match_dist -= 1;
slouken@481
  2503
  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
slouken@481
  2504
  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
slouken@481
  2505
slouken@481
  2506
  *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++; }
slouken@481
  2507
slouken@481
  2508
  s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
slouken@481
  2509
  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
slouken@481
  2510
slouken@481
  2511
  if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
slouken@481
  2512
}
slouken@481
  2513
slouken@481
  2514
static mz_bool tdefl_compress_normal(tdefl_compressor *d)
slouken@481
  2515
{
slouken@481
  2516
  const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
slouken@481
  2517
  tdefl_flush flush = d->m_flush;
slouken@481
  2518
slouken@481
  2519
  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
slouken@481
  2520
  {
slouken@481
  2521
    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
slouken@481
  2522
    // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
slouken@481
  2523
    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
slouken@481
  2524
    {
slouken@481
  2525
      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;
slouken@481
  2526
      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];
slouken@481
  2527
      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
slouken@481
  2528
      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
slouken@481
  2529
      src_buf_left -= num_bytes_to_process;
slouken@481
  2530
      d->m_lookahead_size += num_bytes_to_process;
slouken@481
  2531
      while (pSrc != pSrc_end)
slouken@481
  2532
      {
slouken@481
  2533
        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;
slouken@481
  2534
        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
slouken@481
  2535
        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
slouken@481
  2536
        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
slouken@481
  2537
      }
slouken@481
  2538
    }
slouken@481
  2539
    else
slouken@481
  2540
    {
slouken@481
  2541
      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
slouken@481
  2542
      {
slouken@481
  2543
        mz_uint8 c = *pSrc++;
slouken@481
  2544
        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2545
        src_buf_left--;
slouken@481
  2546
        d->m_dict[dst_pos] = c;
slouken@481
  2547
        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
slouken@481
  2548
          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
slouken@481
  2549
        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
slouken@481
  2550
        {
slouken@481
  2551
          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
slouken@481
  2552
          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);
slouken@481
  2553
          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
slouken@481
  2554
        }
slouken@481
  2555
      }
slouken@481
  2556
    }
slouken@481
  2557
    d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
slouken@481
  2558
    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
slouken@481
  2559
      break;
slouken@481
  2560
slouken@481
  2561
    // Simple lazy/greedy parsing state machine.
slouken@481
  2562
    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;
slouken@481
  2563
    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
slouken@481
  2564
    {
slouken@481
  2565
      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
slouken@481
  2566
      {
slouken@481
  2567
        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
slouken@481
  2568
        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++; }
slouken@481
  2569
        if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
slouken@481
  2570
      }
slouken@481
  2571
    }
slouken@481
  2572
    else
slouken@481
  2573
    {
slouken@481
  2574
      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
slouken@481
  2575
    }
slouken@481
  2576
    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)))
slouken@481
  2577
    {
slouken@481
  2578
      cur_match_dist = cur_match_len = 0;
slouken@481
  2579
    }
slouken@481
  2580
    if (d->m_saved_match_len)
slouken@481
  2581
    {
slouken@481
  2582
      if (cur_match_len > d->m_saved_match_len)
slouken@481
  2583
      {
slouken@481
  2584
        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
slouken@481
  2585
        if (cur_match_len >= 128)
slouken@481
  2586
        {
slouken@481
  2587
          tdefl_record_match(d, cur_match_len, cur_match_dist);
slouken@481
  2588
          d->m_saved_match_len = 0; len_to_move = cur_match_len;
slouken@481
  2589
        }
slouken@481
  2590
        else
slouken@481
  2591
        {
slouken@481
  2592
          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;
slouken@481
  2593
        }
slouken@481
  2594
      }
slouken@481
  2595
      else
slouken@481
  2596
      {
slouken@481
  2597
        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
slouken@481
  2598
        len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
slouken@481
  2599
      }
slouken@481
  2600
    }
slouken@481
  2601
    else if (!cur_match_dist)
slouken@481
  2602
      tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
slouken@481
  2603
    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
slouken@481
  2604
    {
slouken@481
  2605
      tdefl_record_match(d, cur_match_len, cur_match_dist);
slouken@481
  2606
      len_to_move = cur_match_len;
slouken@481
  2607
    }
slouken@481
  2608
    else
slouken@481
  2609
    {
slouken@481
  2610
      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;
slouken@481
  2611
    }
slouken@481
  2612
    // Move the lookahead forward by len_to_move bytes.
slouken@481
  2613
    d->m_lookahead_pos += len_to_move;
slouken@481
  2614
    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
slouken@481
  2615
    d->m_lookahead_size -= len_to_move;
slouken@481
  2616
    d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
slouken@481
  2617
    // Check if it's time to flush the current LZ codes to the internal output buffer.
slouken@481
  2618
    if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
slouken@481
  2619
         ( (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))) )
slouken@481
  2620
    {
slouken@481
  2621
      int n;
slouken@481
  2622
      d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
slouken@481
  2623
      if ((n = tdefl_flush_block(d, 0)) != 0)
slouken@481
  2624
        return (n < 0) ? MZ_FALSE : MZ_TRUE;
slouken@481
  2625
    }
slouken@481
  2626
  }
slouken@481
  2627
slouken@481
  2628
  d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
slouken@481
  2629
  return MZ_TRUE;
slouken@481
  2630
}
slouken@481
  2631
slouken@481
  2632
static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
slouken@481
  2633
{
slouken@481
  2634
  if (d->m_pIn_buf_size)
slouken@481
  2635
  {
slouken@481
  2636
    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
slouken@481
  2637
  }
slouken@481
  2638
slouken@481
  2639
  if (d->m_pOut_buf_size)
slouken@481
  2640
  {
slouken@481
  2641
    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
slouken@481
  2642
    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
slouken@481
  2643
    d->m_output_flush_ofs += (mz_uint)n;
slouken@481
  2644
    d->m_output_flush_remaining -= (mz_uint)n;
slouken@481
  2645
    d->m_out_buf_ofs += n;
slouken@481
  2646
slouken@481
  2647
    *d->m_pOut_buf_size = d->m_out_buf_ofs;
slouken@481
  2648
  }
slouken@481
  2649
slouken@481
  2650
  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
slouken@481
  2651
}
slouken@481
  2652
slouken@481
  2653
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)