miniz.h
author Sam Lantinga <slouken@libsdl.org>
Sun, 01 Jan 2017 18:50:51 -0800
changeset 496 6332f9425dcc
parent 481 e77ad79ab3e0
child 505 b8a69b39a934
permissions -rw-r--r--
Updated copyright for 2017
<
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@481
   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@481
   947
#include <string.h>
slouken@481
   948
#include <assert.h>
slouken@481
   949
slouken@481
   950
// Defines to remove C runtime dependency
slouken@481
   951
#define memset SDL_memset
slouken@481
   952
#define memcpy SDL_memcpy
slouken@481
   953
slouken@481
   954
//#define MZ_ASSERT(x) assert(x)
slouken@481
   955
#define MZ_ASSERT(x) SDL_assert(x)
slouken@481
   956
slouken@481
   957
#ifdef MINIZ_NO_MALLOC
slouken@481
   958
  #define MZ_MALLOC(x) NULL
slouken@481
   959
  #define MZ_FREE(x) (void)x, ((void)0)
slouken@481
   960
  #define MZ_REALLOC(p, x) NULL
slouken@481
   961
#elif defined(MINIZ_SDL_MALLOC)
slouken@481
   962
  #define MZ_MALLOC(x) SDL_malloc(x)
slouken@481
   963
  #define MZ_FREE(x) SDL_free(x)
slouken@481
   964
  #define MZ_REALLOC(p, x) SDL_realloc(p, x)
slouken@481
   965
#else
slouken@481
   966
  #define MZ_MALLOC(x) malloc(x)
slouken@481
   967
  #define MZ_FREE(x) free(x)
slouken@481
   968
  #define MZ_REALLOC(p, x) realloc(p, x)
slouken@481
   969
#endif
slouken@481
   970
slouken@481
   971
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
slouken@481
   972
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
slouken@481
   973
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
slouken@481
   974
slouken@481
   975
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
slouken@481
   976
  #define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
slouken@481
   977
  #define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
slouken@481
   978
#else
slouken@481
   979
  #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
slouken@481
   980
  #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
   981
#endif
slouken@481
   982
slouken@481
   983
#ifdef _MSC_VER
slouken@481
   984
  #define MZ_FORCEINLINE __forceinline
slouken@481
   985
#elif defined(__GNUC__)
slouken@481
   986
  #define MZ_FORCEINLINE inline __attribute__((__always_inline__))
slouken@481
   987
#else
slouken@481
   988
  #define MZ_FORCEINLINE inline
slouken@481
   989
#endif
slouken@481
   990
slouken@481
   991
#ifdef __cplusplus
slouken@481
   992
  extern "C" {
slouken@481
   993
#endif
slouken@481
   994
slouken@481
   995
// ------------------- zlib-style API's
slouken@481
   996
slouken@481
   997
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
slouken@481
   998
{
slouken@481
   999
  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552;
slouken@481
  1000
  if (!ptr) return MZ_ADLER32_INIT;
slouken@481
  1001
  while (buf_len) {
slouken@481
  1002
    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
slouken@481
  1003
      s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
slouken@481
  1004
      s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
slouken@481
  1005
    }
slouken@481
  1006
    for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
slouken@481
  1007
    s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
slouken@481
  1008
  }
slouken@481
  1009
  return (s2 << 16) + s1;
slouken@481
  1010
}
slouken@481
  1011
slouken@481
  1012
// 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
  1013
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
slouken@481
  1014
{
slouken@481
  1015
  static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
slouken@481
  1016
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
slouken@481
  1017
  mz_uint32 crcu32 = (mz_uint32)crc;
slouken@481
  1018
  if (!ptr) return MZ_CRC32_INIT;
slouken@481
  1019
  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
  1020
  return ~crcu32;
slouken@481
  1021
}
slouken@481
  1022
slouken@481
  1023
MINIZ_STATIC void mz_free(void *p)
slouken@481
  1024
{
slouken@481
  1025
  MZ_FREE(p);
slouken@481
  1026
}
slouken@481
  1027
slouken@481
  1028
#ifndef MINIZ_NO_ZLIB_APIS
slouken@481
  1029
slouken@481
  1030
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
  1031
static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); }
slouken@481
  1032
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
  1033
slouken@481
  1034
const char *mz_version(void)
slouken@481
  1035
{
slouken@481
  1036
  return MZ_VERSION;
slouken@481
  1037
}
slouken@481
  1038
slouken@481
  1039
int mz_deflateInit(mz_streamp pStream, int level)
slouken@481
  1040
{
slouken@481
  1041
  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
slouken@481
  1042
}
slouken@481
  1043
slouken@481
  1044
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
slouken@481
  1045
{
slouken@481
  1046
  tdefl_compressor *pComp;
slouken@481
  1047
  mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
slouken@481
  1048
slouken@481
  1049
  if (!pStream) return MZ_STREAM_ERROR;
slouken@481
  1050
  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
  1051
slouken@481
  1052
  pStream->data_type = 0;
slouken@481
  1053
  pStream->adler = MZ_ADLER32_INIT;
slouken@481
  1054
  pStream->msg = NULL;
slouken@481
  1055
  pStream->reserved = 0;
slouken@481
  1056
  pStream->total_in = 0;
slouken@481
  1057
  pStream->total_out = 0;
slouken@481
  1058
  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
slouken@481
  1059
  if (!pStream->zfree) pStream->zfree = def_free_func;
slouken@481
  1060
slouken@481
  1061
  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
slouken@481
  1062
  if (!pComp)
slouken@481
  1063
    return MZ_MEM_ERROR;
slouken@481
  1064
slouken@481
  1065
  pStream->state = (struct mz_internal_state *)pComp;
slouken@481
  1066
slouken@481
  1067
  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
slouken@481
  1068
  {
slouken@481
  1069
    mz_deflateEnd(pStream);
slouken@481
  1070
    return MZ_PARAM_ERROR;
slouken@481
  1071
  }
slouken@481
  1072
slouken@481
  1073
  return MZ_OK;
slouken@481
  1074
}
slouken@481
  1075
slouken@481
  1076
int mz_deflateReset(mz_streamp pStream)
slouken@481
  1077
{
slouken@481
  1078
  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR;
slouken@481
  1079
  pStream->total_in = pStream->total_out = 0;
slouken@481
  1080
  tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags);
slouken@481
  1081
  return MZ_OK;
slouken@481
  1082
}
slouken@481
  1083
slouken@481
  1084
int mz_deflate(mz_streamp pStream, int flush)
slouken@481
  1085
{
slouken@481
  1086
  size_t in_bytes, out_bytes;
slouken@481
  1087
  mz_ulong orig_total_in, orig_total_out;
slouken@481
  1088
  int mz_status = MZ_OK;
slouken@481
  1089
slouken@481
  1090
  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR;
slouken@481
  1091
  if (!pStream->avail_out) return MZ_BUF_ERROR;
slouken@481
  1092
slouken@481
  1093
  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
slouken@481
  1094
slouken@481
  1095
  if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
slouken@481
  1096
    return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
slouken@481
  1097
slouken@481
  1098
  orig_total_in = pStream->total_in; orig_total_out = pStream->total_out;
slouken@481
  1099
  for ( ; ; )
slouken@481
  1100
  {
slouken@481
  1101
    tdefl_status defl_status;
slouken@481
  1102
    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
slouken@481
  1103
slouken@481
  1104
    defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
slouken@481
  1105
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
slouken@481
  1106
    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state);
slouken@481
  1107
slouken@481
  1108
    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes;
slouken@481
  1109
    pStream->total_out += (mz_uint)out_bytes;
slouken@481
  1110
slouken@481
  1111
    if (defl_status < 0)
slouken@481
  1112
    {
slouken@481
  1113
      mz_status = MZ_STREAM_ERROR;
slouken@481
  1114
      break;
slouken@481
  1115
    }
slouken@481
  1116
    else if (defl_status == TDEFL_STATUS_DONE)
slouken@481
  1117
    {
slouken@481
  1118
      mz_status = MZ_STREAM_END;
slouken@481
  1119
      break;
slouken@481
  1120
    }
slouken@481
  1121
    else if (!pStream->avail_out)
slouken@481
  1122
      break;
slouken@481
  1123
    else if ((!pStream->avail_in) && (flush != MZ_FINISH))
slouken@481
  1124
    {
slouken@481
  1125
      if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
slouken@481
  1126
        break;
slouken@481
  1127
      return MZ_BUF_ERROR; // Can't make forward progress without some input.
slouken@481
  1128
    }
slouken@481
  1129
  }
slouken@481
  1130
  return mz_status;
slouken@481
  1131
}
slouken@481
  1132
slouken@481
  1133
int mz_deflateEnd(mz_streamp pStream)
slouken@481
  1134
{
slouken@481
  1135
  if (!pStream) return MZ_STREAM_ERROR;
slouken@481
  1136
  if (pStream->state)
slouken@481
  1137
  {
slouken@481
  1138
    pStream->zfree(pStream->opaque, pStream->state);
slouken@481
  1139
    pStream->state = NULL;
slouken@481
  1140
  }
slouken@481
  1141
  return MZ_OK;
slouken@481
  1142
}
slouken@481
  1143
slouken@481
  1144
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
slouken@481
  1145
{
slouken@481
  1146
  (void)pStream;
slouken@481
  1147
  // 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
  1148
  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
slouken@481
  1149
}
slouken@481
  1150
slouken@481
  1151
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
slouken@481
  1152
{
slouken@481
  1153
  int status;
slouken@481
  1154
  mz_stream stream;
slouken@481
  1155
  memset(&stream, 0, sizeof(stream));
slouken@481
  1156
slouken@481
  1157
  // In case mz_ulong is 64-bits (argh I hate longs).
slouken@481
  1158
  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
slouken@481
  1159
slouken@481
  1160
  stream.next_in = pSource;
slouken@481
  1161
  stream.avail_in = (mz_uint32)source_len;
slouken@481
  1162
  stream.next_out = pDest;
slouken@481
  1163
  stream.avail_out = (mz_uint32)*pDest_len;
slouken@481
  1164
slouken@481
  1165
  status = mz_deflateInit(&stream, level);
slouken@481
  1166
  if (status != MZ_OK) return status;
slouken@481
  1167
slouken@481
  1168
  status = mz_deflate(&stream, MZ_FINISH);
slouken@481
  1169
  if (status != MZ_STREAM_END)
slouken@481
  1170
  {
slouken@481
  1171
    mz_deflateEnd(&stream);
slouken@481
  1172
    return (status == MZ_OK) ? MZ_BUF_ERROR : status;
slouken@481
  1173
  }
slouken@481
  1174
slouken@481
  1175
  *pDest_len = stream.total_out;
slouken@481
  1176
  return mz_deflateEnd(&stream);
slouken@481
  1177
}
slouken@481
  1178
slouken@481
  1179
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
slouken@481
  1180
{
slouken@481
  1181
  return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
slouken@481
  1182
}
slouken@481
  1183
slouken@481
  1184
mz_ulong mz_compressBound(mz_ulong source_len)
slouken@481
  1185
{
slouken@481
  1186
  return mz_deflateBound(NULL, source_len);
slouken@481
  1187
}
slouken@481
  1188
slouken@481
  1189
typedef struct
slouken@481
  1190
{
slouken@481
  1191
  tinfl_decompressor m_decomp;
slouken@481
  1192
  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
slouken@481
  1193
  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
slouken@481
  1194
  tinfl_status m_last_status;
slouken@481
  1195
} inflate_state;
slouken@481
  1196
slouken@481
  1197
int mz_inflateInit2(mz_streamp pStream, int window_bits)
slouken@481
  1198
{
slouken@481
  1199
  inflate_state *pDecomp;
slouken@481
  1200
  if (!pStream) return MZ_STREAM_ERROR;
slouken@481
  1201
  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
slouken@481
  1202
slouken@481
  1203
  pStream->data_type = 0;
slouken@481
  1204
  pStream->adler = 0;
slouken@481
  1205
  pStream->msg = NULL;
slouken@481
  1206
  pStream->total_in = 0;
slouken@481
  1207
  pStream->total_out = 0;
slouken@481
  1208
  pStream->reserved = 0;
slouken@481
  1209
  if (!pStream->zalloc) pStream->zalloc = def_alloc_func;
slouken@481
  1210
  if (!pStream->zfree) pStream->zfree = def_free_func;
slouken@481
  1211
slouken@481
  1212
  pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
slouken@481
  1213
  if (!pDecomp) return MZ_MEM_ERROR;
slouken@481
  1214
slouken@481
  1215
  pStream->state = (struct mz_internal_state *)pDecomp;
slouken@481
  1216
slouken@481
  1217
  tinfl_init(&pDecomp->m_decomp);
slouken@481
  1218
  pDecomp->m_dict_ofs = 0;
slouken@481
  1219
  pDecomp->m_dict_avail = 0;
slouken@481
  1220
  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
slouken@481
  1221
  pDecomp->m_first_call = 1;
slouken@481
  1222
  pDecomp->m_has_flushed = 0;
slouken@481
  1223
  pDecomp->m_window_bits = window_bits;
slouken@481
  1224
slouken@481
  1225
  return MZ_OK;
slouken@481
  1226
}
slouken@481
  1227
slouken@481
  1228
int mz_inflateInit(mz_streamp pStream)
slouken@481
  1229
{
slouken@481
  1230
   return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
slouken@481
  1231
}
slouken@481
  1232
slouken@481
  1233
int mz_inflate(mz_streamp pStream, int flush)
slouken@481
  1234
{
slouken@481
  1235
  inflate_state* pState;
slouken@481
  1236
  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
slouken@481
  1237
  size_t in_bytes, out_bytes, orig_avail_in;
slouken@481
  1238
  tinfl_status status;
slouken@481
  1239
slouken@481
  1240
  if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
slouken@481
  1241
  if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
slouken@481
  1242
  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
slouken@481
  1243
slouken@481
  1244
  pState = (inflate_state*)pStream->state;
slouken@481
  1245
  if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
slouken@481
  1246
  orig_avail_in = pStream->avail_in;
slouken@481
  1247
slouken@481
  1248
  first_call = pState->m_first_call; pState->m_first_call = 0;
slouken@481
  1249
  if (pState->m_last_status < 0) return MZ_DATA_ERROR;
slouken@481
  1250
slouken@481
  1251
  if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
slouken@481
  1252
  pState->m_has_flushed |= (flush == MZ_FINISH);
slouken@481
  1253
slouken@481
  1254
  if ((flush == MZ_FINISH) && (first_call))
slouken@481
  1255
  {
slouken@481
  1256
    // 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
  1257
    decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
slouken@481
  1258
    in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
slouken@481
  1259
    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
slouken@481
  1260
    pState->m_last_status = status;
slouken@481
  1261
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
slouken@481
  1262
    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
slouken@481
  1263
    pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
slouken@481
  1264
slouken@481
  1265
    if (status < 0)
slouken@481
  1266
      return MZ_DATA_ERROR;
slouken@481
  1267
    else if (status != TINFL_STATUS_DONE)
slouken@481
  1268
    {
slouken@481
  1269
      pState->m_last_status = TINFL_STATUS_FAILED;
slouken@481
  1270
      return MZ_BUF_ERROR;
slouken@481
  1271
    }
slouken@481
  1272
    return MZ_STREAM_END;
slouken@481
  1273
  }
slouken@481
  1274
  // flush != MZ_FINISH then we must assume there's more input.
slouken@481
  1275
  if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
slouken@481
  1276
slouken@481
  1277
  if (pState->m_dict_avail)
slouken@481
  1278
  {
slouken@481
  1279
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
slouken@481
  1280
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
slouken@481
  1281
    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
slouken@481
  1282
    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
slouken@481
  1283
    return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
slouken@481
  1284
  }
slouken@481
  1285
slouken@481
  1286
  for ( ; ; )
slouken@481
  1287
  {
slouken@481
  1288
    in_bytes = pStream->avail_in;
slouken@481
  1289
    out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
slouken@481
  1290
slouken@481
  1291
    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
  1292
    pState->m_last_status = status;
slouken@481
  1293
slouken@481
  1294
    pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
slouken@481
  1295
    pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
slouken@481
  1296
slouken@481
  1297
    pState->m_dict_avail = (mz_uint)out_bytes;
slouken@481
  1298
slouken@481
  1299
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
slouken@481
  1300
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
slouken@481
  1301
    pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
slouken@481
  1302
    pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
slouken@481
  1303
slouken@481
  1304
    if (status < 0)
slouken@481
  1305
       return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
slouken@481
  1306
    else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
slouken@481
  1307
      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
  1308
    else if (flush == MZ_FINISH)
slouken@481
  1309
    {
slouken@481
  1310
       // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH.
slouken@481
  1311
       if (status == TINFL_STATUS_DONE)
slouken@481
  1312
          return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
slouken@481
  1313
       // 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
  1314
       else if (!pStream->avail_out)
slouken@481
  1315
          return MZ_BUF_ERROR;
slouken@481
  1316
    }
slouken@481
  1317
    else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
slouken@481
  1318
      break;
slouken@481
  1319
  }
slouken@481
  1320
slouken@481
  1321
  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
slouken@481
  1322
}
slouken@481
  1323
slouken@481
  1324
int mz_inflateEnd(mz_streamp pStream)
slouken@481
  1325
{
slouken@481
  1326
  if (!pStream)
slouken@481
  1327
    return MZ_STREAM_ERROR;
slouken@481
  1328
  if (pStream->state)
slouken@481
  1329
  {
slouken@481
  1330
    pStream->zfree(pStream->opaque, pStream->state);
slouken@481
  1331
    pStream->state = NULL;
slouken@481
  1332
  }
slouken@481
  1333
  return MZ_OK;
slouken@481
  1334
}
slouken@481
  1335
slouken@481
  1336
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
slouken@481
  1337
{
slouken@481
  1338
  mz_stream stream;
slouken@481
  1339
  int status;
slouken@481
  1340
  memset(&stream, 0, sizeof(stream));
slouken@481
  1341
slouken@481
  1342
  // In case mz_ulong is 64-bits (argh I hate longs).
slouken@481
  1343
  if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR;
slouken@481
  1344
slouken@481
  1345
  stream.next_in = pSource;
slouken@481
  1346
  stream.avail_in = (mz_uint32)source_len;
slouken@481
  1347
  stream.next_out = pDest;
slouken@481
  1348
  stream.avail_out = (mz_uint32)*pDest_len;
slouken@481
  1349
slouken@481
  1350
  status = mz_inflateInit(&stream);
slouken@481
  1351
  if (status != MZ_OK)
slouken@481
  1352
    return status;
slouken@481
  1353
slouken@481
  1354
  status = mz_inflate(&stream, MZ_FINISH);
slouken@481
  1355
  if (status != MZ_STREAM_END)
slouken@481
  1356
  {
slouken@481
  1357
    mz_inflateEnd(&stream);
slouken@481
  1358
    return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
slouken@481
  1359
  }
slouken@481
  1360
  *pDest_len = stream.total_out;
slouken@481
  1361
slouken@481
  1362
  return mz_inflateEnd(&stream);
slouken@481
  1363
}
slouken@481
  1364
slouken@481
  1365
const char *mz_error(int err)
slouken@481
  1366
{
slouken@481
  1367
  static struct { int m_err; const char *m_pDesc; } s_error_descs[] =
slouken@481
  1368
  {
slouken@481
  1369
    { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" },
slouken@481
  1370
    { 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
  1371
  };
slouken@481
  1372
  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
  1373
  return NULL;
slouken@481
  1374
}
slouken@481
  1375
slouken@481
  1376
#endif //MINIZ_NO_ZLIB_APIS
slouken@481
  1377
slouken@481
  1378
// ------------------- Low-level Decompression (completely independent from all compression API's)
slouken@481
  1379
slouken@481
  1380
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
slouken@481
  1381
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
slouken@481
  1382
slouken@481
  1383
#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
slouken@481
  1384
#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
  1385
#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
slouken@481
  1386
#define TINFL_CR_FINISH }
slouken@481
  1387
slouken@481
  1388
// 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
  1389
// 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
  1390
#define TINFL_GET_BYTE(state_index, c) do { \
slouken@481
  1391
  if (pIn_buf_cur >= pIn_buf_end) { \
slouken@481
  1392
    for ( ; ; ) { \
slouken@481
  1393
      if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
slouken@481
  1394
        TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
slouken@481
  1395
        if (pIn_buf_cur < pIn_buf_end) { \
slouken@481
  1396
          c = *pIn_buf_cur++; \
slouken@481
  1397
          break; \
slouken@481
  1398
        } \
slouken@481
  1399
      } else { \
slouken@481
  1400
        c = 0; \
slouken@481
  1401
        break; \
slouken@481
  1402
      } \
slouken@481
  1403
    } \
slouken@481
  1404
  } else c = *pIn_buf_cur++; } MZ_MACRO_END
slouken@481
  1405
slouken@481
  1406
#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
  1407
#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
  1408
#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
  1409
slouken@481
  1410
// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
slouken@481
  1411
// 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
  1412
// 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
  1413
// bit buffer contains >=15 bits (deflate's max. Huffman code size).
slouken@481
  1414
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
slouken@481
  1415
  do { \
slouken@481
  1416
    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
slouken@481
  1417
    if (temp >= 0) { \
slouken@481
  1418
      code_len = temp >> 9; \
slouken@481
  1419
      if ((code_len) && (num_bits >= code_len)) \
slouken@481
  1420
      break; \
slouken@481
  1421
    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
slouken@481
  1422
       code_len = TINFL_FAST_LOOKUP_BITS; \
slouken@481
  1423
       do { \
slouken@481
  1424
          temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
slouken@481
  1425
       } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
slouken@481
  1426
    } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
slouken@481
  1427
  } while (num_bits < 15);
slouken@481
  1428
slouken@481
  1429
// 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
  1430
// 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
  1431
// 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
  1432
// The slow path is only executed at the very end of the input buffer.
slouken@481
  1433
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
slouken@481
  1434
  int temp; mz_uint code_len, c; \
slouken@481
  1435
  if (num_bits < 15) { \
slouken@481
  1436
    if ((pIn_buf_end - pIn_buf_cur) < 2) { \
slouken@481
  1437
       TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
slouken@481
  1438
    } else { \
slouken@481
  1439
       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
  1440
    } \
slouken@481
  1441
  } \
slouken@481
  1442
  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
slouken@481
  1443
    code_len = temp >> 9, temp &= 511; \
slouken@481
  1444
  else { \
slouken@481
  1445
    code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
slouken@481
  1446
  } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
slouken@481
  1447
slouken@481
  1448
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
  1449
{
slouken@481
  1450
  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
  1451
  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
  1452
  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
  1453
  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
  1454
  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
  1455
  static const int s_min_table_sizes[3] = { 257, 1, 4 };
slouken@481
  1456
slouken@481
  1457
  tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
slouken@481
  1458
  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
slouken@481
  1459
  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
slouken@481
  1460
  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
  1461
slouken@481
  1462
  // 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
  1463
  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
  1464
slouken@481
  1465
  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
  1466
  TINFL_CR_BEGIN
slouken@481
  1467
slouken@481
  1468
  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
  1469
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
slouken@481
  1470
  {
slouken@481
  1471
    TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
slouken@481
  1472
    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
slouken@481
  1473
    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
  1474
    if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
slouken@481
  1475
  }
slouken@481
  1476
slouken@481
  1477
  do
slouken@481
  1478
  {
slouken@481
  1479
    TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
slouken@481
  1480
    if (r->m_type == 0)
slouken@481
  1481
    {
slouken@481
  1482
      TINFL_SKIP_BITS(5, num_bits & 7);
slouken@481
  1483
      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
  1484
      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
  1485
      while ((counter) && (num_bits))
slouken@481
  1486
      {
slouken@481
  1487
        TINFL_GET_BITS(51, dist, 8);
slouken@481
  1488
        while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1489
        *pOut_buf_cur++ = (mz_uint8)dist;
slouken@481
  1490
        counter--;
slouken@481
  1491
      }
slouken@481
  1492
      while (counter)
slouken@481
  1493
      {
slouken@481
  1494
        size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1495
        while (pIn_buf_cur >= pIn_buf_end)
slouken@481
  1496
        {
slouken@481
  1497
          if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
slouken@481
  1498
          {
slouken@481
  1499
            TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
slouken@481
  1500
          }
slouken@481
  1501
          else
slouken@481
  1502
          {
slouken@481
  1503
            TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
slouken@481
  1504
          }
slouken@481
  1505
        }
slouken@481
  1506
        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
slouken@481
  1507
        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
slouken@481
  1508
      }
slouken@481
  1509
    }
slouken@481
  1510
    else if (r->m_type == 3)
slouken@481
  1511
    {
slouken@481
  1512
      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
slouken@481
  1513
    }
slouken@481
  1514
    else
slouken@481
  1515
    {
slouken@481
  1516
      if (r->m_type == 1)
slouken@481
  1517
      {
slouken@481
  1518
        mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
slouken@481
  1519
        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
  1520
        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
  1521
      }
slouken@481
  1522
      else
slouken@481
  1523
      {
slouken@481
  1524
        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
  1525
        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
  1526
        r->m_table_sizes[2] = 19;
slouken@481
  1527
      }
slouken@481
  1528
      for ( ; (int)r->m_type >= 0; r->m_type--)
slouken@481
  1529
      {
slouken@481
  1530
        int tree_next, tree_cur; tinfl_huff_table *pTable;
slouken@481
  1531
        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
  1532
        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
slouken@481
  1533
        used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
slouken@481
  1534
        for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
slouken@481
  1535
        if ((65536 != total) && (used_syms > 1))
slouken@481
  1536
        {
slouken@481
  1537
          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
slouken@481
  1538
        }
slouken@481
  1539
        for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
slouken@481
  1540
        {
slouken@481
  1541
          mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
slouken@481
  1542
          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
  1543
          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
  1544
          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
  1545
          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
slouken@481
  1546
          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
slouken@481
  1547
          {
slouken@481
  1548
            tree_cur -= ((rev_code >>= 1) & 1);
slouken@481
  1549
            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
  1550
          }
slouken@481
  1551
          tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
slouken@481
  1552
        }
slouken@481
  1553
        if (r->m_type == 2)
slouken@481
  1554
        {
slouken@481
  1555
          for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
slouken@481
  1556
          {
slouken@481
  1557
            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
  1558
            if ((dist == 16) && (!counter))
slouken@481
  1559
            {
slouken@481
  1560
              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
slouken@481
  1561
            }
slouken@481
  1562
            num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
slouken@481
  1563
            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
slouken@481
  1564
          }
slouken@481
  1565
          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
slouken@481
  1566
          {
slouken@481
  1567
            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
slouken@481
  1568
          }
slouken@481
  1569
          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
  1570
        }
slouken@481
  1571
      }
slouken@481
  1572
      for ( ; ; )
slouken@481
  1573
      {
slouken@481
  1574
        mz_uint8 *pSrc;
slouken@481
  1575
        for ( ; ; )
slouken@481
  1576
        {
slouken@481
  1577
          if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
slouken@481
  1578
          {
slouken@481
  1579
            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
slouken@481
  1580
            if (counter >= 256)
slouken@481
  1581
              break;
slouken@481
  1582
            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1583
            *pOut_buf_cur++ = (mz_uint8)counter;
slouken@481
  1584
          }
slouken@481
  1585
          else
slouken@481
  1586
          {
slouken@481
  1587
            int sym2; mz_uint code_len;
slouken@481
  1588
#if TINFL_USE_64BIT_BITBUF
slouken@481
  1589
            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
  1590
#else
slouken@481
  1591
            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
  1592
#endif
slouken@481
  1593
            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
slouken@481
  1594
              code_len = sym2 >> 9;
slouken@481
  1595
            else
slouken@481
  1596
            {
slouken@481
  1597
              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
  1598
            }
slouken@481
  1599
            counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
slouken@481
  1600
            if (counter & 256)
slouken@481
  1601
              break;
slouken@481
  1602
slouken@481
  1603
#if !TINFL_USE_64BIT_BITBUF
slouken@481
  1604
            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
  1605
#endif
slouken@481
  1606
            if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
slouken@481
  1607
              code_len = sym2 >> 9;
slouken@481
  1608
            else
slouken@481
  1609
            {
slouken@481
  1610
              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
  1611
            }
slouken@481
  1612
            bit_buf >>= code_len; num_bits -= code_len;
slouken@481
  1613
slouken@481
  1614
            pOut_buf_cur[0] = (mz_uint8)counter;
slouken@481
  1615
            if (sym2 & 256)
slouken@481
  1616
            {
slouken@481
  1617
              pOut_buf_cur++;
slouken@481
  1618
              counter = sym2;
slouken@481
  1619
              break;
slouken@481
  1620
            }
slouken@481
  1621
            pOut_buf_cur[1] = (mz_uint8)sym2;
slouken@481
  1622
            pOut_buf_cur += 2;
slouken@481
  1623
          }
slouken@481
  1624
        }
slouken@481
  1625
        if ((counter &= 511) == 256) break;
slouken@481
  1626
slouken@481
  1627
        num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
slouken@481
  1628
        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
slouken@481
  1629
slouken@481
  1630
        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
slouken@481
  1631
        num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
slouken@481
  1632
        if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
slouken@481
  1633
slouken@481
  1634
        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
slouken@481
  1635
        if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
slouken@481
  1636
        {
slouken@481
  1637
          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
slouken@481
  1638
        }
slouken@481
  1639
slouken@481
  1640
        pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
slouken@481
  1641
slouken@481
  1642
        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
slouken@481
  1643
        {
slouken@481
  1644
          while (counter--)
slouken@481
  1645
          {
slouken@481
  1646
            while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
slouken@481
  1647
            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
slouken@481
  1648
          }
slouken@481
  1649
          continue;
slouken@481
  1650
        }
slouken@481
  1651
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
slouken@481
  1652
        else if ((counter >= 9) && (counter <= dist))
slouken@481
  1653
        {
slouken@481
  1654
          const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
slouken@481
  1655
          do
slouken@481
  1656
          {
slouken@481
  1657
            ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
slouken@481
  1658
            ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
slouken@481
  1659
            pOut_buf_cur += 8;
slouken@481
  1660
          } while ((pSrc += 8) < pSrc_end);
slouken@481
  1661
          if ((counter &= 7) < 3)
slouken@481
  1662
          {
slouken@481
  1663
            if (counter)
slouken@481
  1664
            {
slouken@481
  1665
              pOut_buf_cur[0] = pSrc[0];
slouken@481
  1666
              if (counter > 1)
slouken@481
  1667
                pOut_buf_cur[1] = pSrc[1];
slouken@481
  1668
              pOut_buf_cur += counter;
slouken@481
  1669
            }
slouken@481
  1670
            continue;
slouken@481
  1671
          }
slouken@481
  1672
        }
slouken@481
  1673
#endif
slouken@481
  1674
        do
slouken@481
  1675
        {
slouken@481
  1676
          pOut_buf_cur[0] = pSrc[0];
slouken@481
  1677
          pOut_buf_cur[1] = pSrc[1];
slouken@481
  1678
          pOut_buf_cur[2] = pSrc[2];
slouken@481
  1679
          pOut_buf_cur += 3; pSrc += 3;
slouken@481
  1680
        } while ((int)(counter -= 3) > 2);
slouken@481
  1681
        if ((int)counter > 0)
slouken@481
  1682
        {
slouken@481
  1683
          pOut_buf_cur[0] = pSrc[0];
slouken@481
  1684
          if ((int)counter > 1)
slouken@481
  1685
            pOut_buf_cur[1] = pSrc[1];
slouken@481
  1686
          pOut_buf_cur += counter;
slouken@481
  1687
        }
slouken@481
  1688
      }
slouken@481
  1689
    }
slouken@481
  1690
  } while (!(r->m_final & 1));
slouken@481
  1691
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
slouken@481
  1692
  {
slouken@481
  1693
    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
  1694
  }
slouken@481
  1695
  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
slouken@481
  1696
  TINFL_CR_FINISH
slouken@481
  1697
slouken@481
  1698
common_exit:
slouken@481
  1699
  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
  1700
  *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
slouken@481
  1701
  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
slouken@481
  1702
  {
slouken@481
  1703
    const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
slouken@481
  1704
    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
slouken@481
  1705
    while (buf_len)
slouken@481
  1706
    {
slouken@481
  1707
      for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
slouken@481
  1708
      {
slouken@481
  1709
        s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
slouken@481
  1710
        s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
slouken@481
  1711
      }
slouken@481
  1712
      for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
slouken@481
  1713
      s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
slouken@481
  1714
    }
slouken@481
  1715
    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
  1716
  }
slouken@481
  1717
  return status;
slouken@481
  1718
}
slouken@481
  1719
slouken@481
  1720
// Higher level helper functions.
slouken@481
  1721
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
slouken@481
  1722
{
slouken@481
  1723
  tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
slouken@481
  1724
  *pOut_len = 0;
slouken@481
  1725
  tinfl_init(&decomp);
slouken@481
  1726
  for ( ; ; )
slouken@481
  1727
  {
slouken@481
  1728
    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
  1729
    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
  1730
      (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
slouken@481
  1731
    if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
slouken@481
  1732
    {
slouken@481
  1733
      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
slouken@481
  1734
    }
slouken@481
  1735
    src_buf_ofs += src_buf_size;
slouken@481
  1736
    *pOut_len += dst_buf_size;
slouken@481
  1737
    if (status == TINFL_STATUS_DONE) break;
slouken@481
  1738
    new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
slouken@481
  1739
    pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
slouken@481
  1740
    if (!pNew_buf)
slouken@481
  1741
    {
slouken@481
  1742
      MZ_FREE(pBuf); *pOut_len = 0; return NULL;
slouken@481
  1743
    }
slouken@481
  1744
    pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
slouken@481
  1745
  }
slouken@481
  1746
  return pBuf;
slouken@481
  1747
}
slouken@481
  1748
slouken@481
  1749
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
  1750
{
slouken@481
  1751
  tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
slouken@481
  1752
  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
  1753
  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
slouken@481
  1754
}
slouken@481
  1755
slouken@481
  1756
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
  1757
{
slouken@481
  1758
  int result = 0;
slouken@481
  1759
  tinfl_decompressor decomp;
slouken@481
  1760
  mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
slouken@481
  1761
  if (!pDict)
slouken@481
  1762
    return TINFL_STATUS_FAILED;
slouken@481
  1763
  tinfl_init(&decomp);
slouken@481
  1764
  for ( ; ; )
slouken@481
  1765
  {
slouken@481
  1766
    size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
slouken@481
  1767
    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
  1768
      (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
slouken@481
  1769
    in_buf_ofs += in_buf_size;
slouken@481
  1770
    if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
slouken@481
  1771
      break;
slouken@481
  1772
    if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
slouken@481
  1773
    {
slouken@481
  1774
      result = (status == TINFL_STATUS_DONE);
slouken@481
  1775
      break;
slouken@481
  1776
    }
slouken@481
  1777
    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
slouken@481
  1778
  }
slouken@481
  1779
  MZ_FREE(pDict);
slouken@481
  1780
  *pIn_buf_size = in_buf_ofs;
slouken@481
  1781
  return result;
slouken@481
  1782
}
slouken@481
  1783
slouken@481
  1784
// ------------------- Low-level Compression (independent from all decompression API's)
slouken@481
  1785
slouken@481
  1786
// Purposely making these tables static for faster init and thread safety.
slouken@481
  1787
static const mz_uint16 s_tdefl_len_sym[256] = {
slouken@481
  1788
  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
  1789
  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
  1790
  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
  1791
  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
  1792
  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
  1793
  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
  1794
  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
  1795
  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
  1796
slouken@481
  1797
static const mz_uint8 s_tdefl_len_extra[256] = {
slouken@481
  1798
  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
  1799
  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
  1800
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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
  1801
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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
  1802
slouken@481
  1803
static const mz_uint8 s_tdefl_small_dist_sym[512] = {
slouken@481
  1804
  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
  1805
  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
  1806
  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
  1807
  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
  1808
  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
  1809
  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
  1810
  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
  1811
  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
  1812
  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
  1813
  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
  1814
  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
  1815
  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
  1816
slouken@481
  1817
static const mz_uint8 s_tdefl_small_dist_extra[512] = {
slouken@481
  1818
  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
  1819
  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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
  1820
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,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
  1821
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,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
  1822
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,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
  1823
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,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
  1824
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,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
  1825
  7,7,7,7,7,7,7,7 };
slouken@481
  1826
slouken@481
  1827
static const mz_uint8 s_tdefl_large_dist_sym[128] = {
slouken@481
  1828
  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
  1829
  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
  1830
  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
  1831
slouken@481
  1832
static const mz_uint8 s_tdefl_large_dist_extra[128] = {
slouken@481
  1833
  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
  1834
  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
  1835
  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
  1836
slouken@481
  1837
// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values.
slouken@481
  1838
typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
slouken@481
  1839
static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1)
slouken@481
  1840
{
slouken@481
  1841
  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
  1842
  for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; }
slouken@481
  1843
  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
slouken@481
  1844
  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
slouken@481
  1845
  {
slouken@481
  1846
    const mz_uint32* pHist = &hist[pass << 8];
slouken@481
  1847
    mz_uint offsets[256], cur_ofs = 0;
slouken@481
  1848
    for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
slouken@481
  1849
    for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
slouken@481
  1850
    { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; }
slouken@481
  1851
  }
slouken@481
  1852
  return pCur_syms;
slouken@481
  1853
}
slouken@481
  1854
slouken@481
  1855
// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
slouken@481
  1856
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
slouken@481
  1857
{
slouken@481
  1858
  int root, leaf, next, avbl, used, dpth;
slouken@481
  1859
  if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
slouken@481
  1860
  A[0].m_key += A[1].m_key; root = 0; leaf = 2;
slouken@481
  1861
  for (next=1; next < n-1; next++)
slouken@481
  1862
  {
slouken@481
  1863
    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
  1864
    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
  1865
  }
slouken@481
  1866
  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
  1867
  avbl = 1; used = dpth = 0; root = n-2; next = n-1;
slouken@481
  1868
  while (avbl>0)
slouken@481
  1869
  {
slouken@481
  1870
    while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
slouken@481
  1871
    while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; }
slouken@481
  1872
    avbl = 2*used; dpth++; used = 0;
slouken@481
  1873
  }
slouken@481
  1874
}
slouken@481
  1875
slouken@481
  1876
// Limits canonical Huffman code table's max code size.
slouken@481
  1877
enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
slouken@481
  1878
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
slouken@481
  1879
{
slouken@481
  1880
  int i; mz_uint32 total = 0; if (code_list_len <= 1) return;
slouken@481
  1881
  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
slouken@481
  1882
  for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
slouken@481
  1883
  while (total != (1UL << max_code_size))
slouken@481
  1884
  {
slouken@481
  1885
    pNum_codes[max_code_size]--;
slouken@481
  1886
    for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
slouken@481
  1887
    total--;
slouken@481
  1888
  }
slouken@481
  1889
}
slouken@481
  1890
slouken@481
  1891
static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
slouken@481
  1892
{
slouken@481
  1893
  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
  1894
  if (static_table)
slouken@481
  1895
  {
slouken@481
  1896
    for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++;
slouken@481
  1897
  }
slouken@481
  1898
  else
slouken@481
  1899
  {
slouken@481
  1900
    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
slouken@481
  1901
    int num_used_syms = 0;
slouken@481
  1902
    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
slouken@481
  1903
    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
  1904
slouken@481
  1905
    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
slouken@481
  1906
slouken@481
  1907
    for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
slouken@481
  1908
slouken@481
  1909
    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
slouken@481
  1910
slouken@481
  1911
    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
slouken@481
  1912
    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
slouken@481
  1913
      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
  1914
  }
slouken@481
  1915
slouken@481
  1916
  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
  1917
slouken@481
  1918
  for (i = 0; i < table_len; i++)
slouken@481
  1919
  {
slouken@481
  1920
    mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue;
slouken@481
  1921
    code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
slouken@481
  1922
    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
slouken@481
  1923
  }
slouken@481
  1924
}
slouken@481
  1925
slouken@481
  1926
#define TDEFL_PUT_BITS(b, l) do { \
slouken@481
  1927
  mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \
slouken@481
  1928
  d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \
slouken@481
  1929
  while (d->m_bits_in >= 8) { \
slouken@481
  1930
    if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
slouken@481
  1931
      *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
slouken@481
  1932
      d->m_bit_buffer >>= 8; \
slouken@481
  1933
      d->m_bits_in -= 8; \
slouken@481
  1934
  } \
slouken@481
  1935
} MZ_MACRO_END
slouken@481
  1936
slouken@481
  1937
#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \
slouken@481
  1938
  if (rle_repeat_count < 3) { \
slouken@481
  1939
    d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
slouken@481
  1940
    while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
slouken@481
  1941
  } else { \
slouken@481
  1942
    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
  1943
} rle_repeat_count = 0; } }
slouken@481
  1944
slouken@481
  1945
#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \
slouken@481
  1946
  if (rle_z_count < 3) { \
slouken@481
  1947
    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
  1948
  } else if (rle_z_count <= 10) { \
slouken@481
  1949
    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
  1950
  } else { \
slouken@481
  1951
    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
  1952
} rle_z_count = 0; } }
slouken@481
  1953
slouken@481
  1954
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
  1955
slouken@481
  1956
static void tdefl_start_dynamic_block(tdefl_compressor *d)
slouken@481
  1957
{
slouken@481
  1958
  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
  1959
  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
  1960
slouken@481
  1961
  d->m_huff_count[0][256] = 1;
slouken@481
  1962
slouken@481
  1963
  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
slouken@481
  1964
  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
slouken@481
  1965
slouken@481
  1966
  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
  1967
  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
  1968
slouken@481
  1969
  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
slouken@481
  1970
  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
slouken@481
  1971
  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
  1972
slouken@481
  1973
  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
slouken@481
  1974
  for (i = 0; i < total_code_sizes_to_pack; i++)
slouken@481
  1975
  {
slouken@481
  1976
    mz_uint8 code_size = code_sizes_to_pack[i];
slouken@481
  1977
    if (!code_size)
slouken@481
  1978
    {
slouken@481
  1979
      TDEFL_RLE_PREV_CODE_SIZE();
slouken@481
  1980
      if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); }
slouken@481
  1981
    }
slouken@481
  1982
    else
slouken@481
  1983
    {
slouken@481
  1984
      TDEFL_RLE_ZERO_CODE_SIZE();
slouken@481
  1985
      if (code_size != prev_code_size)
slouken@481
  1986
      {
slouken@481
  1987
        TDEFL_RLE_PREV_CODE_SIZE();
slouken@481
  1988
        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
  1989
      }
slouken@481
  1990
      else if (++rle_repeat_count == 6)
slouken@481
  1991
      {
slouken@481
  1992
        TDEFL_RLE_PREV_CODE_SIZE();
slouken@481
  1993
      }
slouken@481
  1994
    }
slouken@481
  1995
    prev_code_size = code_size;
slouken@481
  1996
  }
slouken@481
  1997
  if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); }
slouken@481
  1998
slouken@481
  1999
  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
slouken@481
  2000
slouken@481
  2001
  TDEFL_PUT_BITS(2, 2);
slouken@481
  2002
slouken@481
  2003
  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
slouken@481
  2004
  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
slouken@481
  2005
slouken@481
  2006
  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
  2007
  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
slouken@481
  2008
  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
  2009
slouken@481
  2010
  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; )
slouken@481
  2011
  {
slouken@481
  2012
    mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
slouken@481
  2013
    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
slouken@481
  2014
    if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
slouken@481
  2015
  }
slouken@481
  2016
}
slouken@481
  2017
slouken@481
  2018
static void tdefl_start_static_block(tdefl_compressor *d)
slouken@481
  2019
{
slouken@481
  2020
  mz_uint i;
slouken@481
  2021
  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
slouken@481
  2022
slouken@481
  2023
  for (i = 0; i <= 143; ++i) *p++ = 8;
slouken@481
  2024
  for ( ; i <= 255; ++i) *p++ = 9;
slouken@481
  2025
  for ( ; i <= 279; ++i) *p++ = 7;
slouken@481
  2026
  for ( ; i <= 287; ++i) *p++ = 8;
slouken@481
  2027
slouken@481
  2028
  memset(d->m_huff_code_sizes[1], 5, 32);
slouken@481
  2029
slouken@481
  2030
  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
slouken@481
  2031
  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
slouken@481
  2032
slouken@481
  2033
  TDEFL_PUT_BITS(1, 2);
slouken@481
  2034
}
slouken@481
  2035
slouken@481
  2036
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
  2037
slouken@481
  2038
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
slouken@481
  2039
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
slouken@481
  2040
{
slouken@481
  2041
  mz_uint flags;
slouken@481
  2042
  mz_uint8 *pLZ_codes;
slouken@481
  2043
  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
slouken@481
  2044
  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
slouken@481
  2045
  mz_uint64 bit_buffer = d->m_bit_buffer;
slouken@481
  2046
  mz_uint bits_in = d->m_bits_in;
slouken@481
  2047
slouken@481
  2048
#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); }
slouken@481
  2049
slouken@481
  2050
  flags = 1;
slouken@481
  2051
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
slouken@481
  2052
  {
slouken@481
  2053
    if (flags == 1)
slouken@481
  2054
      flags = *pLZ_codes++ | 0x100;
slouken@481
  2055
slouken@481
  2056
    if (flags & 1)
slouken@481
  2057
    {
slouken@481
  2058
      mz_uint s0, s1, n0, n1, sym, num_extra_bits;
slouken@481
  2059
      mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3;
slouken@481
  2060
slouken@481
  2061
      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
slouken@481
  2062
      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
  2063
      TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
slouken@481
  2064
slouken@481
  2065
      // This sequence coaxes MSVC into using cmov's vs. jmp's.
slouken@481
  2066
      s0 = s_tdefl_small_dist_sym[match_dist & 511];
slouken@481
  2067
      n0 = s_tdefl_small_dist_extra[match_dist & 511];
slouken@481
  2068
      s1 = s_tdefl_large_dist_sym[match_dist >> 8];
slouken@481
  2069
      n1 = s_tdefl_large_dist_extra[match_dist >> 8];
slouken@481
  2070
      sym = (match_dist < 512) ? s0 : s1;
slouken@481
  2071
      num_extra_bits = (match_dist < 512) ? n0 : n1;
slouken@481
  2072
slouken@481
  2073
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
slouken@481
  2074
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
slouken@481
  2075
      TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
slouken@481
  2076
    }
slouken@481
  2077
    else
slouken@481
  2078
    {
slouken@481
  2079
      mz_uint lit = *pLZ_codes++;
slouken@481
  2080
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2081
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2082
slouken@481
  2083
      if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
slouken@481
  2084
      {
slouken@481
  2085
        flags >>= 1;
slouken@481
  2086
        lit = *pLZ_codes++;
slouken@481
  2087
        MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2088
        TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2089
slouken@481
  2090
        if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
slouken@481
  2091
        {
slouken@481
  2092
          flags >>= 1;
slouken@481
  2093
          lit = *pLZ_codes++;
slouken@481
  2094
          MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2095
          TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2096
        }
slouken@481
  2097
      }
slouken@481
  2098
    }
slouken@481
  2099
slouken@481
  2100
    if (pOutput_buf >= d->m_pOutput_buf_end)
slouken@481
  2101
      return MZ_FALSE;
slouken@481
  2102
slouken@481
  2103
    *(mz_uint64*)pOutput_buf = bit_buffer;
slouken@481
  2104
    pOutput_buf += (bits_in >> 3);
slouken@481
  2105
    bit_buffer >>= (bits_in & ~7);
slouken@481
  2106
    bits_in &= 7;
slouken@481
  2107
  }
slouken@481
  2108
slouken@481
  2109
#undef TDEFL_PUT_BITS_FAST
slouken@481
  2110
slouken@481
  2111
  d->m_pOutput_buf = pOutput_buf;
slouken@481
  2112
  d->m_bits_in = 0;
slouken@481
  2113
  d->m_bit_buffer = 0;
slouken@481
  2114
slouken@481
  2115
  while (bits_in)
slouken@481
  2116
  {
slouken@481
  2117
    mz_uint32 n = MZ_MIN(bits_in, 16);
slouken@481
  2118
    TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
slouken@481
  2119
    bit_buffer >>= n;
slouken@481
  2120
    bits_in -= n;
slouken@481
  2121
  }
slouken@481
  2122
slouken@481
  2123
  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
slouken@481
  2124
slouken@481
  2125
  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
slouken@481
  2126
}
slouken@481
  2127
#else
slouken@481
  2128
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
slouken@481
  2129
{
slouken@481
  2130
  mz_uint flags;
slouken@481
  2131
  mz_uint8 *pLZ_codes;
slouken@481
  2132
slouken@481
  2133
  flags = 1;
slouken@481
  2134
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
slouken@481
  2135
  {
slouken@481
  2136
    if (flags == 1)
slouken@481
  2137
      flags = *pLZ_codes++ | 0x100;
slouken@481
  2138
    if (flags & 1)
slouken@481
  2139
    {
slouken@481
  2140
      mz_uint sym, num_extra_bits;
slouken@481
  2141
      mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3;
slouken@481
  2142
slouken@481
  2143
      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
slouken@481
  2144
      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
  2145
      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
slouken@481
  2146
slouken@481
  2147
      if (match_dist < 512)
slouken@481
  2148
      {
slouken@481
  2149
        sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist];
slouken@481
  2150
      }
slouken@481
  2151
      else
slouken@481
  2152
      {
slouken@481
  2153
        sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
slouken@481
  2154
      }
slouken@481
  2155
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
slouken@481
  2156
      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
slouken@481
  2157
      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
slouken@481
  2158
    }
slouken@481
  2159
    else
slouken@481
  2160
    {
slouken@481
  2161
      mz_uint lit = *pLZ_codes++;
slouken@481
  2162
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
slouken@481
  2163
      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
slouken@481
  2164
    }
slouken@481
  2165
  }
slouken@481
  2166
slouken@481
  2167
  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
slouken@481
  2168
slouken@481
  2169
  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
slouken@481
  2170
}
slouken@481
  2171
#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
slouken@481
  2172
slouken@481
  2173
static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
slouken@481
  2174
{
slouken@481
  2175
  if (static_block)
slouken@481
  2176
    tdefl_start_static_block(d);
slouken@481
  2177
  else
slouken@481
  2178
    tdefl_start_dynamic_block(d);
slouken@481
  2179
  return tdefl_compress_lz_codes(d);
slouken@481
  2180
}
slouken@481
  2181
slouken@481
  2182
static int tdefl_flush_block(tdefl_compressor *d, int flush)
slouken@481
  2183
{
slouken@481
  2184
  mz_uint saved_bit_buf, saved_bits_in;
slouken@481
  2185
  mz_uint8 *pSaved_output_buf;
slouken@481
  2186
  mz_bool comp_block_succeeded = MZ_FALSE;
slouken@481
  2187
  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
  2188
  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
  2189
slouken@481
  2190
  d->m_pOutput_buf = pOutput_buf_start;
slouken@481
  2191
  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
slouken@481
  2192
slouken@481
  2193
  MZ_ASSERT(!d->m_output_flush_remaining);
slouken@481
  2194
  d->m_output_flush_ofs = 0;
slouken@481
  2195
  d->m_output_flush_remaining = 0;
slouken@481
  2196
slouken@481
  2197
  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
slouken@481
  2198
  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
slouken@481
  2199
slouken@481
  2200
  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
slouken@481
  2201
  {
slouken@481
  2202
    TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8);
slouken@481
  2203
  }
slouken@481
  2204
slouken@481
  2205
  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
slouken@481
  2206
slouken@481
  2207
  pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in;
slouken@481
  2208
slouken@481
  2209
  if (!use_raw_block)
slouken@481
  2210
    comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
slouken@481
  2211
slouken@481
  2212
  // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead.
slouken@481
  2213
  if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
slouken@481
  2214
       ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) )
slouken@481
  2215
  {
slouken@481
  2216
    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
  2217
    TDEFL_PUT_BITS(0, 2);
slouken@481
  2218
    if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
slouken@481
  2219
    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
slouken@481
  2220
    {
slouken@481
  2221
      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
slouken@481
  2222
    }
slouken@481
  2223
    for (i = 0; i < d->m_total_lz_bytes; ++i)
slouken@481
  2224
    {
slouken@481
  2225
      TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
slouken@481
  2226
    }
slouken@481
  2227
  }
slouken@481
  2228
  // 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
  2229
  else if (!comp_block_succeeded)
slouken@481
  2230
  {
slouken@481
  2231
    d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
slouken@481
  2232
    tdefl_compress_block(d, MZ_TRUE);
slouken@481
  2233
  }
slouken@481
  2234
slouken@481
  2235
  if (flush)
slouken@481
  2236
  {
slouken@481
  2237
    if (flush == TDEFL_FINISH)
slouken@481
  2238
    {
slouken@481
  2239
      if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); }
slouken@481
  2240
      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
  2241
    }
slouken@481
  2242
    else
slouken@481
  2243
    {
slouken@481
  2244
      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
  2245
    }
slouken@481
  2246
  }
slouken@481
  2247
slouken@481
  2248
  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
slouken@481
  2249
slouken@481
  2250
  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
slouken@481
  2251
  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
slouken@481
  2252
slouken@481
  2253
  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
  2254
slouken@481
  2255
  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
slouken@481
  2256
  {
slouken@481
  2257
    if (d->m_pPut_buf_func)
slouken@481
  2258
    {
slouken@481
  2259
      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
slouken@481
  2260
      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
slouken@481
  2261
        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
slouken@481
  2262
    }
slouken@481
  2263
    else if (pOutput_buf_start == d->m_output_buf)
slouken@481
  2264
    {
slouken@481
  2265
      int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
slouken@481
  2266
      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
slouken@481
  2267
      d->m_out_buf_ofs += bytes_to_copy;
slouken@481
  2268
      if ((n -= bytes_to_copy) != 0)
slouken@481
  2269
      {
slouken@481
  2270
        d->m_output_flush_ofs = bytes_to_copy;
slouken@481
  2271
        d->m_output_flush_remaining = n;
slouken@481
  2272
      }
slouken@481
  2273
    }
slouken@481
  2274
    else
slouken@481
  2275
    {
slouken@481
  2276
      d->m_out_buf_ofs += n;
slouken@481
  2277
    }
slouken@481
  2278
  }
slouken@481
  2279
slouken@481
  2280
  return d->m_output_flush_remaining;
slouken@481
  2281
}
slouken@481
  2282
slouken@481
  2283
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
slouken@481
  2284
#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p)
slouken@481
  2285
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
  2286
{
slouken@481
  2287
  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
  2288
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
slouken@481
  2289
  const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q;
slouken@481
  2290
  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s);
slouken@481
  2291
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
slouken@481
  2292
  for ( ; ; )
slouken@481
  2293
  {
slouken@481
  2294
    for ( ; ; )
slouken@481
  2295
    {
slouken@481
  2296
      if (--num_probes_left == 0) return;
slouken@481
  2297
      #define TDEFL_PROBE \
slouken@481
  2298
        next_probe_pos = d->m_next[probe_pos]; \
slouken@481
  2299
        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
slouken@481
  2300
        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
slouken@481
  2301
        if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
slouken@481
  2302
      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
slouken@481
  2303
    }
slouken@481
  2304
    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
  2305
    do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
slouken@481
  2306
                   (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
  2307
    if (!probe_len)
slouken@481
  2308
    {
slouken@481
  2309
      *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
slouken@481
  2310
    }
slouken@481
  2311
    else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
slouken@481
  2312
    {
slouken@481
  2313
      *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
slouken@481
  2314
      c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
slouken@481
  2315
    }
slouken@481
  2316
  }
slouken@481
  2317
}
slouken@481
  2318
#else
slouken@481
  2319
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
  2320
{
slouken@481
  2321
  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
  2322
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
slouken@481
  2323
  const mz_uint8 *s = d->m_dict + pos, *p, *q;
slouken@481
  2324
  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
slouken@481
  2325
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return;
slouken@481
  2326
  for ( ; ; )
slouken@481
  2327
  {
slouken@481
  2328
    for ( ; ; )
slouken@481
  2329
    {
slouken@481
  2330
      if (--num_probes_left == 0) return;
slouken@481
  2331
      #define TDEFL_PROBE \
slouken@481
  2332
        next_probe_pos = d->m_next[probe_pos]; \
slouken@481
  2333
        if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
slouken@481
  2334
        probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
slouken@481
  2335
        if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break;
slouken@481
  2336
      TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
slouken@481
  2337
    }
slouken@481
  2338
    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
  2339
    if (probe_len > match_len)
slouken@481
  2340
    {
slouken@481
  2341
      *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
slouken@481
  2342
      c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1];
slouken@481
  2343
    }
slouken@481
  2344
  }
slouken@481
  2345
}
slouken@481
  2346
#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
slouken@481
  2347
slouken@481
  2348
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
slouken@481
  2349
static mz_bool tdefl_compress_fast(tdefl_compressor *d)
slouken@481
  2350
{
slouken@481
  2351
  // 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
  2352
  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
  2353
  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
slouken@481
  2354
  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2355
slouken@481
  2356
  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
slouken@481
  2357
  {
slouken@481
  2358
    const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
slouken@481
  2359
    mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2360
    mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
slouken@481
  2361
    d->m_src_buf_left -= num_bytes_to_process;
slouken@481
  2362
    lookahead_size += num_bytes_to_process;
slouken@481
  2363
slouken@481
  2364
    while (num_bytes_to_process)
slouken@481
  2365
    {
slouken@481
  2366
      mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
slouken@481
  2367
      memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
slouken@481
  2368
      if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
slouken@481
  2369
        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
  2370
      d->m_pSrc += n;
slouken@481
  2371
      dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2372
      num_bytes_to_process -= n;
slouken@481
  2373
    }
slouken@481
  2374
slouken@481
  2375
    dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
slouken@481
  2376
    if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break;
slouken@481
  2377
slouken@481
  2378
    while (lookahead_size >= 4)
slouken@481
  2379
    {
slouken@481
  2380
      mz_uint cur_match_dist, cur_match_len = 1;
slouken@481
  2381
      mz_uint8 *pCur_dict = d->m_dict + cur_pos;
slouken@481
  2382
      mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
slouken@481
  2383
      mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
slouken@481
  2384
      mz_uint probe_pos = d->m_hash[hash];
slouken@481
  2385
      d->m_hash[hash] = (mz_uint16)lookahead_pos;
slouken@481
  2386
slouken@481
  2387
      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
  2388
      {
slouken@481
  2389
        const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
slouken@481
  2390
        const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
slouken@481
  2391
        mz_uint32 probe_len = 32;
slouken@481
  2392
        do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
slouken@481
  2393
          (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
  2394
        cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
slouken@481
  2395
        if (!probe_len)
slouken@481
  2396
          cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
slouken@481
  2397
slouken@481
  2398
        if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)))
slouken@481
  2399
        {
slouken@481
  2400
          cur_match_len = 1;
slouken@481
  2401
          *pLZ_code_buf++ = (mz_uint8)first_trigram;
slouken@481
  2402
          *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
slouken@481
  2403
          d->m_huff_count[0][(mz_uint8)first_trigram]++;
slouken@481
  2404
        }
slouken@481
  2405
        else
slouken@481
  2406
        {
slouken@481
  2407
          mz_uint32 s0, s1;
slouken@481
  2408
          cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
slouken@481
  2409
slouken@481
  2410
          MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
slouken@481
  2411
slouken@481
  2412
          cur_match_dist--;
slouken@481
  2413
slouken@481
  2414
          pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
slouken@481
  2415
          *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
slouken@481
  2416
          pLZ_code_buf += 3;
slouken@481
  2417
          *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
slouken@481
  2418
slouken@481
  2419
          s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
slouken@481
  2420
          s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
slouken@481
  2421
          d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
slouken@481
  2422
slouken@481
  2423
          d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
slouken@481
  2424
        }
slouken@481
  2425
      }
slouken@481
  2426
      else
slouken@481
  2427
      {
slouken@481
  2428
        *pLZ_code_buf++ = (mz_uint8)first_trigram;
slouken@481
  2429
        *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
slouken@481
  2430
        d->m_huff_count[0][(mz_uint8)first_trigram]++;
slouken@481
  2431
      }
slouken@481
  2432
slouken@481
  2433
      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
slouken@481
  2434
slouken@481
  2435
      total_lz_bytes += cur_match_len;
slouken@481
  2436
      lookahead_pos += cur_match_len;
slouken@481
  2437
      dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
slouken@481
  2438
      cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2439
      MZ_ASSERT(lookahead_size >= cur_match_len);
slouken@481
  2440
      lookahead_size -= cur_match_len;
slouken@481
  2441
slouken@481
  2442
      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
slouken@481
  2443
      {
slouken@481
  2444
        int n;
slouken@481
  2445
        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
slouken@481
  2446
        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
  2447
        if ((n = tdefl_flush_block(d, 0)) != 0)
slouken@481
  2448
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
slouken@481
  2449
        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
  2450
      }
slouken@481
  2451
    }
slouken@481
  2452
slouken@481
  2453
    while (lookahead_size)
slouken@481
  2454
    {
slouken@481
  2455
      mz_uint8 lit = d->m_dict[cur_pos];
slouken@481
  2456
slouken@481
  2457
      total_lz_bytes++;
slouken@481
  2458
      *pLZ_code_buf++ = lit;
slouken@481
  2459
      *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
slouken@481
  2460
      if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; }
slouken@481
  2461
slouken@481
  2462
      d->m_huff_count[0][lit]++;
slouken@481
  2463
slouken@481
  2464
      lookahead_pos++;
slouken@481
  2465
      dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
slouken@481
  2466
      cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2467
      lookahead_size--;
slouken@481
  2468
slouken@481
  2469
      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
slouken@481
  2470
      {
slouken@481
  2471
        int n;
slouken@481
  2472
        d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
slouken@481
  2473
        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
  2474
        if ((n = tdefl_flush_block(d, 0)) != 0)
slouken@481
  2475
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
slouken@481
  2476
        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
  2477
      }
slouken@481
  2478
    }
slouken@481
  2479
  }
slouken@481
  2480
slouken@481
  2481
  d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size;
slouken@481
  2482
  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
  2483
  return MZ_TRUE;
slouken@481
  2484
}
slouken@481
  2485
#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
slouken@481
  2486
slouken@481
  2487
static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
slouken@481
  2488
{
slouken@481
  2489
  d->m_total_lz_bytes++;
slouken@481
  2490
  *d->m_pLZ_code_buf++ = lit;
slouken@481
  2491
  *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
  2492
  d->m_huff_count[0][lit]++;
slouken@481
  2493
}
slouken@481
  2494
slouken@481
  2495
static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
slouken@481
  2496
{
slouken@481
  2497
  mz_uint32 s0, s1;
slouken@481
  2498
slouken@481
  2499
  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
slouken@481
  2500
slouken@481
  2501
  d->m_total_lz_bytes += match_len;
slouken@481
  2502
slouken@481
  2503
  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
slouken@481
  2504
slouken@481
  2505
  match_dist -= 1;
slouken@481
  2506
  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
slouken@481
  2507
  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3;
slouken@481
  2508
slouken@481
  2509
  *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
  2510
slouken@481
  2511
  s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
slouken@481
  2512
  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
slouken@481
  2513
slouken@481
  2514
  if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
slouken@481
  2515
}
slouken@481
  2516
slouken@481
  2517
static mz_bool tdefl_compress_normal(tdefl_compressor *d)
slouken@481
  2518
{
slouken@481
  2519
  const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left;
slouken@481
  2520
  tdefl_flush flush = d->m_flush;
slouken@481
  2521
slouken@481
  2522
  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
slouken@481
  2523
  {
slouken@481
  2524
    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
slouken@481
  2525
    // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN.
slouken@481
  2526
    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
slouken@481
  2527
    {
slouken@481
  2528
      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
  2529
      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
  2530
      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
slouken@481
  2531
      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
slouken@481
  2532
      src_buf_left -= num_bytes_to_process;
slouken@481
  2533
      d->m_lookahead_size += num_bytes_to_process;
slouken@481
  2534
      while (pSrc != pSrc_end)
slouken@481
  2535
      {
slouken@481
  2536
        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
  2537
        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
slouken@481
  2538
        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
slouken@481
  2539
        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++;
slouken@481
  2540
      }
slouken@481
  2541
    }
slouken@481
  2542
    else
slouken@481
  2543
    {
slouken@481
  2544
      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
slouken@481
  2545
      {
slouken@481
  2546
        mz_uint8 c = *pSrc++;
slouken@481
  2547
        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
slouken@481
  2548
        src_buf_left--;
slouken@481
  2549
        d->m_dict[dst_pos] = c;
slouken@481
  2550
        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
slouken@481
  2551
          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
slouken@481
  2552
        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
slouken@481
  2553
        {
slouken@481
  2554
          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
slouken@481
  2555
          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
  2556
          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos);
slouken@481
  2557
        }
slouken@481
  2558
      }
slouken@481
  2559
    }
slouken@481
  2560
    d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
slouken@481
  2561
    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
slouken@481
  2562
      break;
slouken@481
  2563
slouken@481
  2564
    // Simple lazy/greedy parsing state machine.
slouken@481
  2565
    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
  2566
    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
slouken@481
  2567
    {
slouken@481
  2568
      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
slouken@481
  2569
      {
slouken@481
  2570
        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
slouken@481
  2571
        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
  2572
        if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1;
slouken@481
  2573
      }
slouken@481
  2574
    }
slouken@481
  2575
    else
slouken@481
  2576
    {
slouken@481
  2577
      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
slouken@481
  2578
    }
slouken@481
  2579
    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
  2580
    {
slouken@481
  2581
      cur_match_dist = cur_match_len = 0;
slouken@481
  2582
    }
slouken@481
  2583
    if (d->m_saved_match_len)
slouken@481
  2584
    {
slouken@481
  2585
      if (cur_match_len > d->m_saved_match_len)
slouken@481
  2586
      {
slouken@481
  2587
        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
slouken@481
  2588
        if (cur_match_len >= 128)
slouken@481
  2589
        {
slouken@481
  2590
          tdefl_record_match(d, cur_match_len, cur_match_dist);
slouken@481
  2591
          d->m_saved_match_len = 0; len_to_move = cur_match_len;
slouken@481
  2592
        }
slouken@481
  2593
        else
slouken@481
  2594
        {
slouken@481
  2595
          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
  2596
        }
slouken@481
  2597
      }
slouken@481
  2598
      else
slouken@481
  2599
      {
slouken@481
  2600
        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
slouken@481
  2601
        len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0;
slouken@481
  2602
      }
slouken@481
  2603
    }
slouken@481
  2604
    else if (!cur_match_dist)
slouken@481
  2605
      tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
slouken@481
  2606
    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
slouken@481
  2607
    {
slouken@481
  2608
      tdefl_record_match(d, cur_match_len, cur_match_dist);
slouken@481
  2609
      len_to_move = cur_match_len;
slouken@481
  2610
    }
slouken@481
  2611
    else
slouken@481
  2612
    {
slouken@481
  2613
      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
  2614
    }
slouken@481
  2615
    // Move the lookahead forward by len_to_move bytes.
slouken@481
  2616
    d->m_lookahead_pos += len_to_move;
slouken@481
  2617
    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
slouken@481
  2618
    d->m_lookahead_size -= len_to_move;
slouken@481
  2619
    d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
slouken@481
  2620
    // Check if it's time to flush the current LZ codes to the internal output buffer.
slouken@481
  2621
    if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
slouken@481
  2622
         ( (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
  2623
    {
slouken@481
  2624
      int n;
slouken@481
  2625
      d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
slouken@481
  2626
      if ((n = tdefl_flush_block(d, 0)) != 0)
slouken@481
  2627
        return (n < 0) ? MZ_FALSE : MZ_TRUE;
slouken@481
  2628
    }
slouken@481
  2629
  }
slouken@481
  2630
slouken@481
  2631
  d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left;
slouken@481
  2632
  return MZ_TRUE;
slouken@481
  2633
}
slouken@481
  2634
slouken@481
  2635
static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
slouken@481
  2636
{
slouken@481
  2637
  if (d->m_pIn_buf_size)
slouken@481
  2638
  {
slouken@481
  2639
    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
slouken@481
  2640
  }
slouken@481
  2641
slouken@481
  2642
  if (d->m_pOut_buf_size)
slouken@481
  2643
  {
slouken@481
  2644
    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
slouken@481
  2645
    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
slouken@481
  2646
    d->m_output_flush_ofs += (mz_uint)n;
slouken@481
  2647
    d->m_output_flush_remaining -= (mz_uint)n;
slouken@481
  2648
    d->m_out_buf_ofs += n;
slouken@481
  2649
slouken@481
  2650
    *d->m_pOut_buf_size = d->m_out_buf_ofs;
slouken@481
  2651
  }
slouken@481
  2652
slouken@481
  2653
  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
slouken@481