Source file: /~heha/hsn/esptool.zip/miniz.cpp

/**************************************************************************
 * Copyright 2013-2014 RAD Game Tools and Valve Software
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
 **************************************************************************/

#include "miniz.h"

typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
typedef unsigned char mz_validate_uint64[sizeof(uint64_t) == 8 ? 1 : -1];

#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))

#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
#define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
#else
#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
#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))
#endif

#define MZ_READ_LE64(p) (((uint64_t)MZ_READ_LE32(p)) | (((uint64_t)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32))) << 32U))

#define MZ_UINT16_MAX (0xFFFFU)
#define MZ_UINT32_MAX (0xFFFFFFFFU)

/* ------------------- zlib-style API's */

unsigned mz_adler32(unsigned adler, const unsigned char *ptr, size_t buf_len) {
    mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
    size_t block_len = buf_len % 5552;
    if (!ptr)
        return 1;
    while (buf_len)
    {
        for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
        {
            s1 += ptr[0], s2 += s1;
            s1 += ptr[1], s2 += s1;
            s1 += ptr[2], s2 += s1;
            s1 += ptr[3], s2 += s1;
            s1 += ptr[4], s2 += s1;
            s1 += ptr[5], s2 += s1;
            s1 += ptr[6], s2 += s1;
            s1 += ptr[7], s2 += s1;
        }
        for (; i < block_len; ++i)
            s1 += *ptr++, s2 += s1;
        s1 %= 65521U, s2 %= 65521U;
        buf_len -= block_len;
        block_len = 5552;
    }
    return (s2 << 16) + s1;
}

unsigned mz_crc32(unsigned crc, const mz_uint8 *ptr, size_t buf_len) {
// 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/
#if 0
 static const mz_uint32 s_crc32[16] = {
	0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
	0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
 mz_uint32 crcu32 = (mz_uint32)crc;
 if (!ptr) return 0;
 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)];
 }
#else
// Faster, but larger CPU cache footprint
 static const mz_uint32 s_crc_table[256] = {
	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
	0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
	0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
	0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
	0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
	0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
	0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
	0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
	0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
	0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
	0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
	0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
	0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
	0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
	0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
	0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
	0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
	0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
	0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
	0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
	0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
	0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
	0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
	0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
	0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
	0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
	0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
	0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
	0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
	0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
	0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
 };

 mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
 const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
 while (buf_len >= 4) {
  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
  pByte_buf += 4;
  buf_len -= 4;
 }
 while (buf_len) {
  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
  ++pByte_buf;
  --buf_len;
 }
#endif
 return ~crc32;
}

/**************************************************************************
 * Copyright 2013-2014 RAD Game Tools and Valve Software
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
 **************************************************************************/

/* ------------------- Low-level Compression (independent from all decompression API's) */

/* Purposely making these tables static for faster init and thread safety. */
static const mz_uint16 s_tdefl_len_sym[256] = {
 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,
 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,
 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,
 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,
 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,
 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,
 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,
 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};

static const mz_uint8 s_tdefl_len_extra[256] = {
 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,
 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,
 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 5, 5, 5, 5, 5, 5, 5, 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};

static const mz_uint8 s_tdefl_small_dist_sym[512] = {
  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,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,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,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,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,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,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,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,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,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,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,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};

static const mz_uint8 s_tdefl_small_dist_extra[512] = {
 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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 5, 5, 5, 5, 5, 5, 5, 5, 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, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 6, 6, 6, 6, 6, 6, 6, 6, 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,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};

static const mz_uint8 s_tdefl_large_dist_sym[128] = {
  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,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,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};

static const mz_uint8 s_tdefl_large_dist_extra[128] = {
  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,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,
 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};

/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
struct tdefl_sym_freq {
 mz_uint16 m_key, m_sym_index;
};

static tdefl_sym_freq*tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq*pSyms0, tdefl_sym_freq*pSyms1) {
 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);
 for (i = 0; i < num_syms; i++) {
  mz_uint freq = pSyms0[i].m_key;
  hist[freq & 0xFF]++;
  hist[256 + ((freq >> 8) & 0xFF)]++;
 }
 while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
        total_passes--;
 for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
  const mz_uint32 *pHist = &hist[pass << 8];
  mz_uint offsets[256], cur_ofs = 0;
  for (i = 0; i < 256; i++) {
   offsets[i] = cur_ofs;
   cur_ofs += pHist[i];
  }
  for (i = 0; i < num_syms; i++)
	pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
  {
   tdefl_sym_freq *t = pCur_syms;
   pCur_syms = pNew_syms;
   pNew_syms = t;
  }
 }
 return pCur_syms;
}

/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
 int root, leaf, next, avbl, used, dpth;
 if (n == 0) return;
 else if (n == 1) {
  A[0].m_key = 1;
  return;
 }
 A[0].m_key += A[1].m_key;
 root = 0;
 leaf = 2;
 for (next = 1; next < n - 1; next++) {
  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;
  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);
 }
 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;
 avbl = 1;
 used = dpth = 0;
 root = n - 2;
 next = n - 1;
 while (avbl > 0) {
  while (root >= 0 && (int)A[root].m_key == dpth) {
   used++;
   root--;
  }
  while (avbl > used) {
   A[next--].m_key = (mz_uint16)(dpth);
   avbl--;
  }
  avbl = 2 * used;
  dpth++;
  used = 0;
 }
}

/* Limits canonical Huffman code table's max code size. */
enum{
 MAX_SUPPORTED_HUFF_CODESIZE = 32
};

static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) {
 int i;
 mz_uint32 total = 0;
 if (code_list_len <= 1) return;
 for (i = max_code_size + 1; i <= MAX_SUPPORTED_HUFF_CODESIZE; i++)
	pNum_codes[max_code_size] += pNum_codes[i];
 for (i = max_code_size; i > 0; i--)
	total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
 while (total != (1UL << max_code_size)) {
  pNum_codes[max_code_size]--;
  for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) {
   pNum_codes[i]--;
   pNum_codes[i + 1] += 2;
   break;
  }
  total--;
 }
}

void Deflate::optimize_huffman_table(int table_num, int table_len, int code_size_limit, bool static_table) {
 int i, j, l, num_codes[1 + MAX_SUPPORTED_HUFF_CODESIZE];
 mz_uint next_code[MAX_SUPPORTED_HUFF_CODESIZE + 1];
 MZ_CLEAR_OBJ(num_codes);
 if (static_table) for (i = 0; i < table_len; i++) num_codes[m_huff_code_sizes[table_num][i]]++;
 else{
  tdefl_sym_freq syms0[MAX_HUFF_SYMBOLS], syms1[MAX_HUFF_SYMBOLS], *pSyms;
  int num_used_syms = 0;
  const mz_uint16 *pSym_count = &m_huff_count[table_num][0];
  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;
  }
  pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
  tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
  for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++;
  tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
  MZ_CLEAR_OBJ(m_huff_code_sizes[table_num]);
  MZ_CLEAR_OBJ(m_huff_codes[table_num]);
  for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
	for (l = num_codes[i]; l > 0; l--)
		m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
 }
 next_code[1] = 0;
 for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1);
 for (i = 0; i < table_len; i++) {
  mz_uint rev_code = 0, code, code_size;
  if ((code_size = m_huff_code_sizes[table_num][i]) == 0) continue;
  code = next_code[code_size]++;
  for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1);
  m_huff_codes[table_num][i] = (mz_uint16)rev_code;
 }
}

#define PUT_BITS(b, l)					\
 do{							\
  mz_uint bits = b;					\
  mz_uint len = l;					\
  m_bit_buffer |= (bits << m_bits_in);			\
  m_bits_in += len;					\
  while (m_bits_in >= 8) {				\
   if (m_pOutput_buf < m_pOutput_buf_end)		\
	*m_pOutput_buf++ = (mz_uint8)(m_bit_buffer);	\
   m_bit_buffer >>= 8;					\
   m_bits_in -= 8;					\
  }							\
 }while(0)

#define RLE_PREV_CODE_SIZE()				\
 {							\
  if (rle_repeat_count) {				\
   if (rle_repeat_count < 3) {				\
    m_huff_count[2][prev_code_size] = (mz_uint16)(m_huff_count[2][prev_code_size] + rle_repeat_count);	\
    while (rle_repeat_count--)				\
	packed_code_sizes[num_packed_code_sizes++] = prev_code_size;					\
   }else{						\
    m_huff_count[2][16] = (mz_uint16)(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);			\
   }							\
   rle_repeat_count = 0;				\
  }							\
 }

#define RLE_ZERO_CODE_SIZE()				\
 {							\
  if (rle_z_count) {					\
   if (rle_z_count < 3) {				\
    m_huff_count[2][0] = (mz_uint16)(m_huff_count[2][0] + rle_z_count);		\
    while (rle_z_count--)				\
	packed_code_sizes[num_packed_code_sizes++] = 0;	\
   }else if (rle_z_count <= 10) {			\
    m_huff_count[2][17] = (mz_uint16)(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);	\
   }else{						\
    m_huff_count[2][18] = (mz_uint16)(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);	\
   }							\
   rle_z_count = 0;					\
  }							\
 }

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 };

void Deflate::start_dynamic_block() {
 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;
 mz_uint8 code_sizes_to_pack[MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1], packed_code_sizes[MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;

 m_huff_count[0][256] = 1;

 optimize_huffman_table(0, MAX_HUFF_SYMBOLS_0, 15, false);
 optimize_huffman_table(1, MAX_HUFF_SYMBOLS_1, 15, false);

 for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
	if (m_huff_code_sizes[0][num_lit_codes - 1]) break;
 for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
	if (m_huff_code_sizes[1][num_dist_codes - 1]) break;

 memcpy(code_sizes_to_pack, &m_huff_code_sizes[0][0], num_lit_codes);
 memcpy(code_sizes_to_pack + num_lit_codes, &m_huff_code_sizes[1][0], num_dist_codes);
 total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
 num_packed_code_sizes = 0;
 rle_z_count = 0;
 rle_repeat_count = 0;
 memset(&m_huff_count[2][0], 0, sizeof(m_huff_count[2][0]) * MAX_HUFF_SYMBOLS_2);
 for (i = 0; i < total_code_sizes_to_pack; i++) {
  mz_uint8 code_size = code_sizes_to_pack[i];
  if (!code_size) {
   RLE_PREV_CODE_SIZE();
   if (++rle_z_count == 138) {
    RLE_ZERO_CODE_SIZE();
   }
  }else{
   RLE_ZERO_CODE_SIZE();
   if (code_size != prev_code_size) {
    RLE_PREV_CODE_SIZE();
    m_huff_count[2][code_size] = (mz_uint16)(m_huff_count[2][code_size] + 1);
    packed_code_sizes[num_packed_code_sizes++] = code_size;
   }else if (++rle_repeat_count == 6) {
    RLE_PREV_CODE_SIZE();
   }
  }
  prev_code_size = code_size;
 }
 if (rle_repeat_count) {
  RLE_PREV_CODE_SIZE();
 }else{
  RLE_ZERO_CODE_SIZE();
 }
 optimize_huffman_table(2, MAX_HUFF_SYMBOLS_2, 7, false);
 PUT_BITS(2, 2);
 PUT_BITS(num_lit_codes - 257, 5);
 PUT_BITS(num_dist_codes - 1, 5);
 for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
	if (m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
            break;
 num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
 PUT_BITS(num_bit_lengths - 4, 4);
 for (i = 0; (int)i < num_bit_lengths; i++)
	PUT_BITS(m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
 for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) {
  mz_uint code = packed_code_sizes[packed_code_sizes_index++];
  PUT_BITS(m_huff_codes[2][code], m_huff_code_sizes[2][code]);
  if (code >= 16)
            PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
 }
}

void Deflate::start_static_block() {
 mz_uint i;
 mz_uint8 *p = &m_huff_code_sizes[0][0];
 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;
 memset(m_huff_code_sizes[1], 5, 32);
 optimize_huffman_table(0, 288, 15, true);
 optimize_huffman_table(1, 32, 15, true);
 PUT_BITS(1, 2);
}

static const mz_uint16 mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
bool Deflate::compress_lz_codes() {
 mz_uint flags;
 mz_uint8 *pLZ_codes;
 mz_uint8 *pOutput_buf = m_pOutput_buf;
 mz_uint8 *pLZ_code_buf_end = m_pLZ_code_buf;
 uint64_t bit_buffer = m_bit_buffer;
 mz_uint bits_in = m_bits_in;

#define PUT_BITS_FAST(b, l)			\
 {						\
  bit_buffer |= (((uint64_t)(b)) << bits_in);	\
  bits_in += (l);				\
 }

 flags = 1;
 for (pLZ_codes = m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) {
  if (flags == 1) flags = *pLZ_codes++ | 0x100;
  if (flags & 1) {
   mz_uint s0, s1, n0, n1, sym, num_extra_bits;
   mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
   pLZ_codes += 3;

   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]]);
   PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);

            /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
   s0 = s_tdefl_small_dist_sym[match_dist & 511];
   n0 = s_tdefl_small_dist_extra[match_dist & 511];
   s1 = s_tdefl_large_dist_sym[match_dist >> 8];
   n1 = s_tdefl_large_dist_extra[match_dist >> 8];
   sym = (match_dist < 512) ? s0 : s1;
   num_extra_bits = (match_dist < 512) ? n0 : n1;

   PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
   PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
  }else{
   mz_uint lit = *pLZ_codes++;
   PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
   if (!(flags&2) && pLZ_codes<pLZ_code_buf_end) {
    flags >>= 1;
    lit = *pLZ_codes++;
    PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
    if (!(flags&2) && pLZ_codes<pLZ_code_buf_end) {
     flags >>= 1;
     lit = *pLZ_codes++;
     PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
    }
   }
  }
  if (pOutput_buf >= m_pOutput_buf_end) return false;
  *(uint64_t *)pOutput_buf = bit_buffer;
  pOutput_buf += (bits_in >> 3);
  bit_buffer >>= (bits_in & ~7);
  bits_in &= 7;
 }

#undef PUT_BITS_FAST

 m_pOutput_buf = pOutput_buf;
 m_bits_in = 0;
 m_bit_buffer = 0;
 while (bits_in) {
  mz_uint32 n = MZ_MIN(bits_in, 16);
  PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
  bit_buffer >>= n;
  bits_in -= n;
 }
 PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
 return m_pOutput_buf < m_pOutput_buf_end;
}
#else
bool Deflate::compress_lz_codes() {
 mz_uint flags;
 mz_uint8 *pLZ_codes;

 flags = 1;
 for (pLZ_codes = m_lz_code_buf; pLZ_codes < m_pLZ_code_buf; flags >>= 1) {
  if (flags == 1) flags = *pLZ_codes++ | 0x100;
  if (flags & 1) {
   mz_uint sym, num_extra_bits;
   mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
   pLZ_codes += 3;
   PUT_BITS(m_huff_codes[0][s_tdefl_len_sym[match_len]], m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
   PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
   if (match_dist < 512) {
    sym = s_tdefl_small_dist_sym[match_dist];
    num_extra_bits = s_tdefl_small_dist_extra[match_dist];
   }else{
    sym = s_tdefl_large_dist_sym[match_dist >> 8];
    num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
   }
   PUT_BITS(m_huff_codes[1][sym], m_huff_code_sizes[1][sym]);
   PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
  }else{
   mz_uint lit = *pLZ_codes++;
   PUT_BITS(m_huff_codes[0][lit], m_huff_code_sizes[0][lit]);
  }
 }
 PUT_BITS(m_huff_codes[0][256], m_huff_code_sizes[0][256]);
 return (m_pOutput_buf < m_pOutput_buf_end);
}
#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */

bool Deflate::compress_block(bool static_block) {
 if (static_block) start_static_block();
 else start_dynamic_block();
 return compress_lz_codes();
}

int Deflate::flush_block(int flush) {
 mz_uint saved_bit_buf, saved_bits_in;
 mz_uint8 *pSaved_output_buf;
 bool comp_block_succeeded = false;
 int n, use_raw_block = ((m_flags & FORCE_ALL_RAW_BLOCKS) != 0) && (m_lookahead_pos - m_lz_code_buf_dict_pos) <= m_dict_size;
 mz_uint8 *pOutput_buf_start = ((m_pPut_buf_func == NULL) && ((*m_pOut_buf_size - m_out_buf_ofs) >= OUT_BUF_SIZE)) ? ((mz_uint8 *)m_pOut_buf + m_out_buf_ofs) : m_output_buf;

 m_pOutput_buf = pOutput_buf_start;
 m_pOutput_buf_end = m_pOutput_buf + OUT_BUF_SIZE - 16;

 m_output_flush_ofs = 0;
 m_output_flush_remaining = 0;

 *m_pLZ_flags = (mz_uint8)(*m_pLZ_flags >> m_num_flags_left);
 m_pLZ_code_buf -= (m_num_flags_left == 8);

 if ((m_flags & WRITE_ZLIB_HEADER) && (!m_block_index)) {
  PUT_BITS(0x78, 8);
  PUT_BITS(0x01, 8);
 }

 PUT_BITS(flush == FINISH, 1);

 pSaved_output_buf = m_pOutput_buf;
 saved_bit_buf = m_bit_buffer;
 saved_bits_in = m_bits_in;

 if (!use_raw_block)
  comp_block_succeeded = compress_block(m_flags&FORCE_ALL_STATIC_BLOCKS || m_total_lz_bytes<48);

    /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
 if (((use_raw_block) || ((m_total_lz_bytes) && ((m_pOutput_buf - pSaved_output_buf + 1U) >= m_total_lz_bytes))) &&
        ((m_lookahead_pos - m_lz_code_buf_dict_pos) <= m_dict_size)) {
  mz_uint i;
  m_pOutput_buf = pSaved_output_buf;
  m_bit_buffer = saved_bit_buf, m_bits_in = saved_bits_in;
  PUT_BITS(0, 2);
  if (m_bits_in) {
   PUT_BITS(0, 8 - m_bits_in);
  }
  for (i = 2; i; --i, m_total_lz_bytes ^= 0xFFFF) {
   PUT_BITS(m_total_lz_bytes & 0xFFFF, 16);
  }
  for (i = 0; i < m_total_lz_bytes; ++i) {
   PUT_BITS(m_dict[(m_lz_code_buf_dict_pos + i) & LZ_DICT_SIZE_MASK], 8);
  }
 }else if (!comp_block_succeeded) {
    /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
  m_pOutput_buf = pSaved_output_buf;
  m_bit_buffer = saved_bit_buf, m_bits_in = saved_bits_in;
  compress_block(true);
 }

 if (flush) {
  if (flush == FINISH) {
   if (m_bits_in) {
    PUT_BITS(0, 8 - m_bits_in);
   }
   if (m_flags & WRITE_ZLIB_HEADER) {
    mz_uint i, a = m_adler32;
    for (i = 0; i < 4; i++) {
     PUT_BITS((a >> 24) & 0xFF, 8);
     a <<= 8;
    }
   }
  }else{
   mz_uint i, z = 0;
   PUT_BITS(0, 3);
   if (m_bits_in) {
    PUT_BITS(0, 8 - m_bits_in);
   }
   for (i = 2; i; --i, z ^= 0xFFFF) {
    PUT_BITS(z & 0xFFFF, 16);
   }
  }
 }
 memset(&m_huff_count[0][0], 0, sizeof(m_huff_count[0][0]) * MAX_HUFF_SYMBOLS_0);
 memset(&m_huff_count[1][0], 0, sizeof(m_huff_count[1][0]) * MAX_HUFF_SYMBOLS_1);
 m_pLZ_code_buf = m_lz_code_buf + 1;
 m_pLZ_flags = m_lz_code_buf;
 m_num_flags_left = 8;
 m_lz_code_buf_dict_pos += m_total_lz_bytes;
 m_total_lz_bytes = 0;
 m_block_index++;

 if ((n = (int)(m_pOutput_buf - pOutput_buf_start)) != 0) {
  if (m_pPut_buf_func) {
   *m_pIn_buf_size = m_pSrc - (const mz_uint8 *)m_pIn_buf;
   if (!(*m_pPut_buf_func)(m_output_buf, n, m_pPut_buf_user))
                return (m_prev_return_status = STATUS_PUT_BUF_FAILED);
  }else if (pOutput_buf_start == m_output_buf) {
   int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*m_pOut_buf_size - m_out_buf_ofs));
   memcpy((mz_uint8 *)m_pOut_buf + m_out_buf_ofs, m_output_buf, bytes_to_copy);
   m_out_buf_ofs += bytes_to_copy;
   if ((n -= bytes_to_copy) != 0) {
    m_output_flush_ofs = bytes_to_copy;
    m_output_flush_remaining = n;
   }
  }else m_out_buf_ofs += n;
 }
 return m_output_flush_remaining;
}

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
static mz_uint16 READ_UNALIGNED_WORD(const mz_uint8* p) {
 mz_uint16 ret;
 memcpy(&ret, p, sizeof(mz_uint16));
 return ret;
}
static mz_uint16 READ_UNALIGNED_WORD2(const mz_uint16* p) {
 mz_uint16 ret;
 memcpy(&ret, p, sizeof(mz_uint16));
 return ret;
}
#else
#define READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
#define READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
#endif
void Deflate::find_match(mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) {
 mz_uint dist, pos = lookahead_pos & LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
 mz_uint num_probes_left = m_max_probes[match_len >= 32];
 const mz_uint16 *s = (const mz_uint16 *)(m_dict + pos), *p, *q;
 mz_uint16 c01 = READ_UNALIGNED_WORD(&m_dict[pos + match_len - 1]), s01 = READ_UNALIGNED_WORD2(s);
 if (max_match_len <= match_len) return;
 for (;;) {
  for (;;) {
   if (--num_probes_left == 0) return;

#define PROBE					\
 next_probe_pos = m_next[probe_pos];		\
 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
 probe_pos = next_probe_pos & LZ_DICT_SIZE_MASK; \
 if (READ_UNALIGNED_WORD(&m_dict[probe_pos + match_len - 1]) == c01) break;

   PROBE;
   PROBE;
   PROBE;
  }
  if (!dist) break;
  q = (const mz_uint16 *)(m_dict + probe_pos);
  if (READ_UNALIGNED_WORD2(q) != s01) continue;
  p = s;
  probe_len = 32;
  do{
  }while ((READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) && (READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) &&
                 (READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) && (READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
  if (!probe_len) {
   *pMatch_dist = dist;
   *pMatch_len = MZ_MIN(max_match_len, (mz_uint)MAX_MATCH_LEN);
   break;
  }else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len) {
   *pMatch_dist = dist;
   if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break;
   c01 = READ_UNALIGNED_WORD(&m_dict[pos + match_len - 1]);
  }
 }
}
#else
void Deflate::find_match(mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) {
 mz_uint dist, pos = lookahead_pos & LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
 mz_uint num_probes_left = m_max_probes[match_len >= 32];
 const mz_uint8 *s = m_dict + pos, *p, *q;
 mz_uint8 c0 = m_dict[pos + match_len], c1 = m_dict[pos + match_len - 1];
 if (max_match_len <= match_len) return;
 for (;;) {
  for (;;) {
   if (--num_probes_left == 0) return;

#define PROBE					\
 next_probe_pos = m_next[probe_pos];		\
 if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \
 probe_pos = next_probe_pos & LZ_DICT_SIZE_MASK; \
 if ((m_dict[probe_pos + match_len] == c0) && (m_dict[probe_pos + match_len - 1] == c1)) break;

   PROBE;
   PROBE;
   PROBE;
  }
  if (!dist) break;
  p = s;
  q = m_dict + probe_pos;
  for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
  if (probe_len > match_len) {
   *pMatch_dist = dist;
   if ((*pMatch_len = match_len = probe_len) == max_match_len) return;
   c0 = m_dict[pos + match_len];
   c1 = m_dict[pos + match_len - 1];
  }
 }
}
#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
static mz_uint32 READ_UNALIGNED_WORD32(const mz_uint8* p) {
 mz_uint32 ret;
 memcpy(&ret, p, sizeof(mz_uint32));
 return ret;
}
#else
#define READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
#endif
static bool tdefl_compress_fast(Deflate *d) {
    /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
 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;
 mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
 mz_uint cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK;

 while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
  const mz_uint COMP_FAST_LOOKAHEAD_SIZE = 4096;
  mz_uint dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK;
  mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
  d->m_src_buf_left -= num_bytes_to_process;
  lookahead_size += num_bytes_to_process;

  while (num_bytes_to_process) {
   mz_uint32 n = MZ_MIN(LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
   memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
   if (dst_pos < (MAX_MATCH_LEN - 1))
	memcpy(d->m_dict + LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (MAX_MATCH_LEN - 1) - dst_pos));
   d->m_pSrc += n;
   dst_pos = (dst_pos + n) & LZ_DICT_SIZE_MASK;
   num_bytes_to_process -= n;
  }

  dict_size = MZ_MIN(LZ_DICT_SIZE - lookahead_size, dict_size);
  if ((!d->m_flush) && (lookahead_size < COMP_FAST_LOOKAHEAD_SIZE)) break;

  while (lookahead_size >= 4) {
   mz_uint cur_match_dist, cur_match_len = 1;
   mz_uint8 *pCur_dict = d->m_dict + cur_pos;
   mz_uint first_trigram = READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
   mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (LZ_HASH_BITS - 8)))) & LEVEL1_HASH_SIZE_MASK;
   mz_uint probe_pos = d->m_hash[hash];
   d->m_hash[hash] = (mz_uint16)lookahead_pos;

   if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) {
    const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
    const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
    mz_uint32 probe_len = 32;
    do{
    }while ((READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) && (READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) &&
                         (READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) && (READ_UNALIGNED_WORD2(++p) == READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
    cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
    if (!probe_len) cur_match_len = cur_match_dist ? MAX_MATCH_LEN : 0;

    if ((cur_match_len < MIN_MATCH_LEN) || ((cur_match_len == MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) {
     cur_match_len = 1;
     *pLZ_code_buf++ = (mz_uint8)first_trigram;
     *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
     d->m_huff_count[0][(mz_uint8)first_trigram]++;
    }else{
     mz_uint32 s0, s1;
     cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
     cur_match_dist--;
     pLZ_code_buf[0] = (mz_uint8)(cur_match_len - MIN_MATCH_LEN);
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
     memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
#else
     *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
#endif
     pLZ_code_buf += 3;
     *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
     s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
     s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
     d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
     d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - MIN_MATCH_LEN]]++;
    }
   }else{
    *pLZ_code_buf++ = (mz_uint8)first_trigram;
    *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
    d->m_huff_count[0][(mz_uint8)first_trigram]++;
   }
   if (--num_flags_left == 0) {
    num_flags_left = 8;
    pLZ_flags = pLZ_code_buf++;
   }
   total_lz_bytes += cur_match_len;
   lookahead_pos += cur_match_len;
   dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)LZ_DICT_SIZE);
   cur_pos = (cur_pos + cur_match_len) & LZ_DICT_SIZE_MASK;
   lookahead_size -= cur_match_len;
   if (pLZ_code_buf > &d->m_lz_code_buf[LZ_CODE_BUF_SIZE - 8]) {
    int n;
    d->m_lookahead_pos = lookahead_pos;
    d->m_lookahead_size = lookahead_size;
    d->m_dict_size = dict_size;
    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;
    if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? false: true;
    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;
   }
  }
  while (lookahead_size) {
   mz_uint8 lit = d->m_dict[cur_pos];
   total_lz_bytes++;
   *pLZ_code_buf++ = lit;
   *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
   if (--num_flags_left == 0) {
    num_flags_left = 8;
    pLZ_flags = pLZ_code_buf++;
   }
   d->m_huff_count[0][lit]++;
   lookahead_pos++;
   dict_size = MZ_MIN(dict_size + 1, (mz_uint)LZ_DICT_SIZE);
   cur_pos = (cur_pos + 1) & LZ_DICT_SIZE_MASK;
   lookahead_size--;
   if (pLZ_code_buf > &d->m_lz_code_buf[LZ_CODE_BUF_SIZE - 8]) {
    int n;
    d->m_lookahead_pos = lookahead_pos;
    d->m_lookahead_size = lookahead_size;
    d->m_dict_size = dict_size;
    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;
    if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? false: true;
    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;
   }
  }
 }
 d->m_lookahead_pos = lookahead_pos;
 d->m_lookahead_size = lookahead_size;
 d->m_dict_size = dict_size;
 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;
 return true;
}
#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */

void Deflate::record_literal(mz_uint8 lit) {
 m_total_lz_bytes++;
 *m_pLZ_code_buf++ = lit;
 *m_pLZ_flags = (mz_uint8)(*m_pLZ_flags >> 1);
 if (--m_num_flags_left == 0) {
  m_num_flags_left = 8;
  m_pLZ_flags = m_pLZ_code_buf++;
 }
 m_huff_count[0][lit]++;
}

void Deflate::record_match(mz_uint match_len, mz_uint match_dist) {
 mz_uint32 s0, s1;
 m_total_lz_bytes += match_len;
 m_pLZ_code_buf[0] = (mz_uint8)(match_len - MIN_MATCH_LEN);
 match_dist -= 1;
 m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
 m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
 m_pLZ_code_buf += 3;
 *m_pLZ_flags = (mz_uint8)((*m_pLZ_flags >> 1) | 0x80);
 if (--m_num_flags_left == 0) {
  m_num_flags_left = 8;
  m_pLZ_flags = m_pLZ_code_buf++;
 }
 s0 = s_tdefl_small_dist_sym[match_dist & 511];
 s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
 m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
 if (match_len >= MIN_MATCH_LEN)
	m_huff_count[0][s_tdefl_len_sym[match_len - MIN_MATCH_LEN]]++;
}

bool Deflate::compress_normal() {
 const mz_uint8 *pSrc = m_pSrc;
 size_t src_buf_left = m_src_buf_left;
 tdefl_flush flush = m_flush;

 while ((src_buf_left) || ((flush) && (m_lookahead_size))) {
  mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
        /* Update dictionary and hash chains. Keeps the lookahead size equal to MAX_MATCH_LEN. */
  if ((m_lookahead_size + m_dict_size) >= (MIN_MATCH_LEN - 1)) {
   mz_uint dst_pos = (m_lookahead_pos + m_lookahead_size) & LZ_DICT_SIZE_MASK, ins_pos = m_lookahead_pos + m_lookahead_size - 2;
   mz_uint hash = (m_dict[ins_pos & LZ_DICT_SIZE_MASK] << LZ_HASH_SHIFT) ^ m_dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK];
   mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, MAX_MATCH_LEN - m_lookahead_size);
   const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
   src_buf_left -= num_bytes_to_process;
   m_lookahead_size += num_bytes_to_process;
   while (pSrc != pSrc_end) {
    mz_uint8 c = *pSrc++;
    m_dict[dst_pos] = c;
    if (dst_pos < (MAX_MATCH_LEN - 1))
                    m_dict[LZ_DICT_SIZE + dst_pos] = c;
    hash = ((hash << LZ_HASH_SHIFT) ^ c) & (LZ_HASH_SIZE - 1);
    m_next[ins_pos & LZ_DICT_SIZE_MASK] = m_hash[hash];
    m_hash[hash] = (mz_uint16)(ins_pos);
    dst_pos = (dst_pos + 1) & LZ_DICT_SIZE_MASK;
    ins_pos++;
   }
  }else{
   while ((src_buf_left) && (m_lookahead_size < MAX_MATCH_LEN)) {
    mz_uint8 c = *pSrc++;
    mz_uint dst_pos = (m_lookahead_pos + m_lookahead_size) & LZ_DICT_SIZE_MASK;
    src_buf_left--;
    m_dict[dst_pos] = c;
    if (dst_pos < (MAX_MATCH_LEN - 1))
                    m_dict[LZ_DICT_SIZE + dst_pos] = c;
    if ((++m_lookahead_size + m_dict_size) >= MIN_MATCH_LEN) {
     mz_uint ins_pos = m_lookahead_pos + (m_lookahead_size - 1) - 2;
     mz_uint hash = ((m_dict[ins_pos & LZ_DICT_SIZE_MASK] << (LZ_HASH_SHIFT * 2)) ^ (m_dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK] << LZ_HASH_SHIFT) ^ c) & (LZ_HASH_SIZE - 1);
     m_next[ins_pos & LZ_DICT_SIZE_MASK] = m_hash[hash];
     m_hash[hash] = (mz_uint16)(ins_pos);
    }
   }
  }
  m_dict_size = MZ_MIN(LZ_DICT_SIZE - m_lookahead_size, m_dict_size);
  if ((!flush) && (m_lookahead_size < MAX_MATCH_LEN)) break;

        /* Simple lazy/greedy parsing state machine. */
  len_to_move = 1;
  cur_match_dist = 0;
  cur_match_len = m_saved_match_len ? m_saved_match_len : (MIN_MATCH_LEN - 1);
  cur_pos = m_lookahead_pos & LZ_DICT_SIZE_MASK;
  if (m_flags & (RLE_MATCHES | FORCE_ALL_RAW_BLOCKS)) {
   if ((m_dict_size) && (!(m_flags & FORCE_ALL_RAW_BLOCKS))) {
    mz_uint8 c = m_dict[(cur_pos - 1) & LZ_DICT_SIZE_MASK];
    cur_match_len = 0;
    while (cur_match_len < m_lookahead_size) {
     if (m_dict[cur_pos + cur_match_len] != c) break;
     cur_match_len++;
    }
    if (cur_match_len < MIN_MATCH_LEN) cur_match_len = 0;
    else cur_match_dist = 1;
   }
  }else{
   find_match(m_lookahead_pos, m_dict_size, m_lookahead_size, &cur_match_dist, &cur_match_len);
  }
  if (((cur_match_len == MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((m_flags & FILTER_MATCHES) && (cur_match_len <= 5)))
  {
   cur_match_dist = cur_match_len = 0;
  }
  if (m_saved_match_len) {
   if (cur_match_len > m_saved_match_len) {
    record_literal((mz_uint8)m_saved_lit);
    if (cur_match_len >= 128) {
     record_match(cur_match_len, cur_match_dist);
     m_saved_match_len = 0;
     len_to_move = cur_match_len;
    }else{
     m_saved_lit = m_dict[cur_pos];
     m_saved_match_dist = cur_match_dist;
     m_saved_match_len = cur_match_len;
    }
   }else{
    record_match(m_saved_match_len, m_saved_match_dist);
    len_to_move = m_saved_match_len - 1;
    m_saved_match_len = 0;
   }
  }else if (!cur_match_dist)
            record_literal(m_dict[MZ_MIN(cur_pos, sizeof(m_dict) - 1)]);
  else if ((m_greedy_parsing) || (m_flags & RLE_MATCHES) || (cur_match_len >= 128)) {
   record_match(cur_match_len, cur_match_dist);
   len_to_move = cur_match_len;
  }else{
   m_saved_lit = m_dict[MZ_MIN(cur_pos, sizeof(m_dict) - 1)];
   m_saved_match_dist = cur_match_dist;
   m_saved_match_len = cur_match_len;
  }
        /* Move the lookahead forward by len_to_move bytes. */
  m_lookahead_pos += len_to_move;
  m_lookahead_size -= len_to_move;
  m_dict_size = MZ_MIN(m_dict_size + len_to_move, (mz_uint)LZ_DICT_SIZE);
        /* Check if it's time to flush the current LZ codes to the internal output buffer. */
  if ((m_pLZ_code_buf > &m_lz_code_buf[LZ_CODE_BUF_SIZE - 8]) ||
    ((m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(m_pLZ_code_buf - m_lz_code_buf) * 115) >> 7) >= m_total_lz_bytes) || (m_flags & FORCE_ALL_RAW_BLOCKS))))
        {
   int n;
   m_pSrc = pSrc;
   m_src_buf_left = src_buf_left;
   if ((n = flush_block(0)) != 0) return n<0 ? false : true;
  }
 }
 m_pSrc = pSrc;
 m_src_buf_left = src_buf_left;
 return true;
}

Deflate::Dstatus Deflate::flush_output_buffer() {
 if (m_pIn_buf_size) {
  *m_pIn_buf_size = m_pSrc - (const mz_uint8*)m_pIn_buf;
 }
 if (m_pOut_buf_size) {
  size_t n = MZ_MIN(*m_pOut_buf_size - m_out_buf_ofs, m_output_flush_remaining);
  memcpy((mz_uint8 *)m_pOut_buf + m_out_buf_ofs, m_output_buf + m_output_flush_ofs, n);
  m_output_flush_ofs += (mz_uint)n;
  m_output_flush_remaining -= (mz_uint)n;
  m_out_buf_ofs += n;
  *m_pOut_buf_size = m_out_buf_ofs;
 }
 return m_finished && !m_output_flush_remaining ? STATUS_DONE : STATUS_OKAY;
}

Deflate::Dstatus Deflate::compress(const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) {
 if (!this) {
  if (pIn_buf_size) *pIn_buf_size = 0;
  if (pOut_buf_size) *pOut_buf_size = 0;
  return STATUS_BAD_PARAM;
 }
 m_pIn_buf = pIn_buf;
 m_pIn_buf_size = pIn_buf_size;
 m_pOut_buf = pOut_buf;
 m_pOut_buf_size = pOut_buf_size;
 m_pSrc = (const mz_uint8 *)(pIn_buf);
 m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
 m_out_buf_ofs = 0;
 m_flush = flush;

 if (((m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (m_prev_return_status != STATUS_OKAY) ||
        (m_wants_to_finish && (flush != FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
    {
  if (pIn_buf_size) *pIn_buf_size = 0;
  if (pOut_buf_size) *pOut_buf_size = 0;
  return m_prev_return_status = STATUS_BAD_PARAM;
 }
 m_wants_to_finish |= (flush == FINISH);

 if (m_output_flush_remaining || m_finished)
        return m_prev_return_status = flush_output_buffer();

#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
 if (((m_flags & MAX_PROBES_MASK) == 1) &&
        ((m_flags & GREEDY_PARSING_FLAG) != 0) &&
        ((m_flags & (FILTER_MATCHES | FORCE_ALL_RAW_BLOCKS | RLE_MATCHES)) == 0)) {
  if (!tdefl_compress_fast(d)) return m_prev_return_status;
 }else
#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
    {
        if (!compress_normal()) return m_prev_return_status;
    }

 if ((m_flags & (WRITE_ZLIB_HEADER | COMPUTE_ADLER32)) && (pIn_buf))
	m_adler32 = (mz_uint32)mz_adler32(m_adler32, (const mz_uint8 *)pIn_buf, m_pSrc - (const mz_uint8 *)pIn_buf);
 if (flush && !m_lookahead_size && !m_src_buf_left && !m_output_flush_remaining) {
  if (flush_block(flush) < 0) return m_prev_return_status;
  m_finished = (flush == FINISH);
  if (flush == FULL_FLUSH) {
   MZ_CLEAR_OBJ(m_hash);
   MZ_CLEAR_OBJ(m_next);
   m_dict_size = 0;
  }
 }
 return m_prev_return_status = flush_output_buffer();
}

Deflate::Dstatus Deflate::compress_buffer(const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) {
 return compress(pIn_buf, &in_buf_size, NULL, NULL, flush);
}

Deflate::Deflate(cb_t cb, void*cbd, int flags) {
 m_pPut_buf_func = cb;
 m_pPut_buf_user = cbd;
 m_flags = (mz_uint)(flags);
 m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
 m_greedy_parsing = (flags & GREEDY_PARSING_FLAG) != 0;
 m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
 if (!(flags & NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(m_hash);
 m_lookahead_pos = m_lookahead_size = m_dict_size = m_total_lz_bytes = m_lz_code_buf_dict_pos = m_bits_in = 0;
 m_output_flush_ofs = m_output_flush_remaining = m_finished = m_block_index = m_bit_buffer = m_wants_to_finish = 0;
 m_pLZ_code_buf = m_lz_code_buf + 1;
 m_pLZ_flags = m_lz_code_buf;
 m_num_flags_left = 8;
 m_pOutput_buf = m_output_buf;
 m_pOutput_buf_end = m_output_buf;
 m_prev_return_status = STATUS_OKAY;
 m_saved_match_dist = m_saved_match_len = m_saved_lit = 0;
 m_adler32 = 1;
 m_pIn_buf = NULL;
 m_pOut_buf = NULL;
 m_pIn_buf_size = NULL;
 m_pOut_buf_size = NULL;
 m_flush = NO_FLUSH;
 m_pSrc = NULL;
 m_src_buf_left = 0;
 m_out_buf_ofs = 0;
 if (!(flags & NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(m_dict);
 memset(&m_huff_count[0][0], 0, sizeof(m_huff_count[0][0]) * MAX_HUFF_SYMBOLS_0);
 memset(&m_huff_count[1][0], 0, sizeof(m_huff_count[1][0]) * MAX_HUFF_SYMBOLS_1);
}

Deflate::Dstatus Deflate::get_prev_return_status() {
 return m_prev_return_status;
}

mz_uint32 Deflate::get_adler32() {
 return m_adler32;
}

bool Deflate::mem_to_output(const void*pBuf, size_t buf_len, cb_t cb, void*cbd, int flags) {
 if (buf_len && !pBuf || !cb) return false;
 Deflate comp(cb,cbd,flags);
 return comp.compress_buffer(pBuf, buf_len, Deflate::FINISH) == Deflate::STATUS_DONE;
}

// Merely an output stream with expandable or non-expandable output buffer...
class Deflate_output_buffer{
 friend class Deflate;	// All private, even the constructor. Only useable by Deflate class members.
 size_t m_size, m_capacity;
 mz_uint8*m_pBuf;
 bool m_fixed;
 Deflate_output_buffer() {MZ_CLEAR_OBJ(*this);}
 Deflate_output_buffer(void*buf,size_t cap):
	m_size(0),
	m_capacity(cap),
	m_pBuf(reinterpret_cast<mz_uint8*>(buf)),
	m_fixed(true) {}
 static bool putter(const void*buf,int len,void*cbd) {
  return reinterpret_cast<Deflate_output_buffer*>(cbd)->putter(buf,len);
 }
 bool putter(const void*buf,int len);
};

bool Deflate_output_buffer::putter(const void *pBuf, int len) {
 size_t new_size = m_size + len;
 if (new_size > m_capacity) {
  size_t new_capacity = m_capacity;
  mz_uint8 *pNew_buf;
  if (m_fixed) return false;
  do{
   new_capacity = MZ_MAX(128U, new_capacity<<1);
  }while (new_size > new_capacity);
  pNew_buf = (mz_uint8*)realloc(m_pBuf, new_capacity);
  if (!pNew_buf) return false;
  m_pBuf = pNew_buf;
  m_capacity = new_capacity;
 }
 memcpy((mz_uint8*)m_pBuf + m_size, pBuf, len);
 m_size = new_size;
 return true;
}

void* Deflate::mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t&Out_len, int flags) {
 Out_len = 0;
 Deflate_output_buffer out_buf;
 if (!mem_to_output(pSrc_buf, src_buf_len, out_buf.putter, &out_buf, flags)) return NULL;
 Out_len = out_buf.m_size;
 return out_buf.m_pBuf;
}

size_t Deflate::mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) {
 if (!pOut_buf) return 0;
 Deflate_output_buffer out_buf(pOut_buf,out_buf_len);
 if (!mem_to_output(pSrc_buf, src_buf_len, out_buf.putter, &out_buf, flags)) return 0;
 return out_buf.m_size;
}

unsigned Deflate::create_comp_flags_from_zip_params(int level, int window_bits, int strategy) {
/* level may actually range from [0,10] (10 is a "hidden" max level,
   where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
 static const mz_uint16 s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };

 unsigned f = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? GREEDY_PARSING_FLAG : 0);
 if (window_bits > 0)	f |= WRITE_ZLIB_HEADER;
 if (!level)		f |= FORCE_ALL_RAW_BLOCKS;
 else switch (strategy) {
  case MZ_FILTERED:	f |= FILTER_MATCHES; break;
  case MZ_HUFFMAN_ONLY:	f &= ~MAX_PROBES_MASK; break;
  case MZ_FIXED:	f |= FORCE_ALL_STATIC_BLOCKS; break;
  case MZ_RLE:		f |= RLE_MATCHES; break;
 }
 return f;
}

/**************************************************************************
 * Copyright 2013-2014 RAD Game Tools and Valve Software
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
 **************************************************************************/

/* ------------------- Low-level Decompression (completely independent from all compression API's) */

#define TINFL_CR_BEGIN				\
 switch (m_state) {				\
  case 0:

#define TINFL_CR_RETURN(state_index, result)	\
 do{						\
  status = result;				\
  m_state = state_index;			\
  goto common_exit;				\
  case state_index:;				\
 }						\
 while(0)

#define TINFL_CR_RETURN_FOREVER(state_index, result) \
 do{						\
  for (;;) {					\
   TINFL_CR_RETURN(state_index, result);	\
  }						\
 }while(0)

#define TINFL_CR_FINISH }

#define TINFL_GET_BYTE(state_index, c)		\
 do{						\
  while (pIn_buf_cur >= pIn_buf_end) {		\
   TINFL_CR_RETURN(state_index, (decomp_flags & HAS_MORE_INPUT) ? STATUS_NEEDS_MORE_INPUT : STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
  }						\
  c = *pIn_buf_cur++;				\
 }while(0)

#define TINFL_NEED_BITS(state_index, n)		\
 do{						\
  mz_uint c;					\
  TINFL_GET_BYTE(state_index, c);		\
  bit_buf |= (((bitbuf_t)c) << num_bits);	\
  num_bits += 8;				\
 }while (num_bits < (mz_uint)(n))

#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);				\
 }						\
 while(0)

#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);				\
 }while(0)

/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
/* 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 */
/* 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 */
/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
 do{						\
  temp = (pHuff)->m_look_up[bit_buf & (FAST_LOOKUP_SIZE - 1)];	\
  if (temp >= 0) {				\
   code_len = temp >> 9;			\
   if ((code_len) && (num_bits >= code_len)) break; \
  }else if (num_bits > FAST_LOOKUP_BITS) {	\
   code_len = FAST_LOOKUP_BITS;			\
   do{						\
    temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
   } while ((temp < 0) && (num_bits >= (code_len + 1))); \
   if (temp >= 0) break;			\
  }						\
  TINFL_GET_BYTE(state_index, c);		\
  bit_buf |= (((bitbuf_t)c) << num_bits);	\
  num_bits += 8;				\
 }while (num_bits < 15);

/* 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 */
/* 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 */
/* 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. */
/* The slow path is only executed at the very end of the input buffer. */
/* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */
/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) \
 do{						\
  int temp;					\
  mz_uint code_len, c;				\
  if (num_bits < 15) {				\
   if ((pIn_buf_end - pIn_buf_cur) < 2) {	\
    TINFL_HUFF_BITBUF_FILL(state_index, pHuff);	\
   }else{					\
    bit_buf |= (((bitbuf_t)pIn_buf_cur[0]) << num_bits) | (((bitbuf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
    pIn_buf_cur += 2;				\
    num_bits += 16;				\
   }						\
  }						\
  if ((temp = (pHuff)->m_look_up[bit_buf & (FAST_LOOKUP_SIZE - 1)]) >= 0) \
	code_len = temp >> 9, temp &= 511;	\
  else{						\
   code_len = FAST_LOOKUP_BITS;			\
   do{						\
    temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
   } while (temp < 0);				\
  }						\
  sym = temp;					\
  bit_buf >>= code_len;				\
  num_bits -= code_len;				\
 }while(0)

Inflate::Status Inflate::decompress(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) {
 static const mz_uint16 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 };
 static const mz_uint8 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 };
 static const mz_uint16 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 };
 static const mz_uint8 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 };
 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 };
 static const mz_uint16 s_min_table_sizes[3] = { 257, 1, 4 };

 Status status = STATUS_FAILED;
 mz_uint32 num_bits, dist, counter, num_extra;
 bitbuf_t bit_buf;
 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
 mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
 size_t out_buf_size_mask = (decomp_flags & USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
    /* 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). */
 if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) {
  *pIn_buf_size = *pOut_buf_size = 0;
  return STATUS_BAD_PARAM;
 }
 num_bits = m_num_bits;
 bit_buf = m_bit_buf;
 dist = m_dist;
 counter = m_counter;
 num_extra = m_num_extra;
 dist_from_out_buf_start = m_dist_from_out_buf_start;
 TINFL_CR_BEGIN
 bit_buf = num_bits = dist = counter = num_extra = m_zhdr0 = m_zhdr1 = 0;
 m_z_adler32 = m_check_adler32 = 1;
 if (decomp_flags & PARSE_ZLIB_HEADER) {
  TINFL_GET_BYTE(1, m_zhdr0);
  TINFL_GET_BYTE(2, m_zhdr1);
  counter = (((m_zhdr0 * 256 + m_zhdr1) % 31 != 0) || (m_zhdr1 & 32) || ((m_zhdr0 & 15) != 8));
  if (!(decomp_flags & USING_NON_WRAPPING_OUTPUT_BUF))
            counter |= (((1U << (8U + (m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (m_zhdr0 >> 4)))));
  if (counter) {
   TINFL_CR_RETURN_FOREVER(36, STATUS_FAILED);
  }
 }
 do{
  TINFL_GET_BITS(3, m_final, 3);
  m_type = m_final >> 1;
  if (m_type == 0) {
   TINFL_SKIP_BITS(5, num_bits & 7);
   for (counter = 0; counter < 4; ++counter) {
    if (num_bits) TINFL_GET_BITS(6, m_raw_header[counter], 8);
    else TINFL_GET_BYTE(7, m_raw_header[counter]);
   }
   if ((counter = (m_raw_header[0] | (m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (m_raw_header[2] | (m_raw_header[3] << 8))))
   {
    TINFL_CR_RETURN_FOREVER(39, STATUS_FAILED);
   }
   while ((counter) && (num_bits)) {
    TINFL_GET_BITS(51, dist, 8);
    while (pOut_buf_cur >= pOut_buf_end) {
     TINFL_CR_RETURN(52, STATUS_HAS_MORE_OUTPUT);
    }
    *pOut_buf_cur++ = (mz_uint8)dist;
    counter--;
   }
   while (counter) {
    size_t n;
    while (pOut_buf_cur >= pOut_buf_end) {
     TINFL_CR_RETURN(9, STATUS_HAS_MORE_OUTPUT);
    }
    while (pIn_buf_cur >= pIn_buf_end) {
     TINFL_CR_RETURN(38, (decomp_flags & HAS_MORE_INPUT) ? STATUS_NEEDS_MORE_INPUT : STATUS_FAILED_CANNOT_MAKE_PROGRESS);
    }
    n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
    memcpy(pOut_buf_cur, pIn_buf_cur, n);
    pIn_buf_cur += n;
    pOut_buf_cur += n;
    counter -= (mz_uint)n;
   }
  }else if (m_type == 3) {
   TINFL_CR_RETURN_FOREVER(10, STATUS_FAILED);
  }else{
   if (m_type == 1) {
    mz_uint8 *p = m_tables[0].m_code_size;
    mz_uint i;
    m_table_sizes[0] = 288;
    m_table_sizes[1] = 32;
    memset(m_tables[1].m_code_size, 5, 32);
    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;
   }else{
    for (counter = 0; counter < 3; counter++) {
     TINFL_GET_BITS(11, m_table_sizes[counter], "\05\05\04"[counter]);
     m_table_sizes[counter] += s_min_table_sizes[counter];
    }
    MZ_CLEAR_OBJ(m_tables[2].m_code_size);
    for (counter = 0; counter < m_table_sizes[2]; counter++) {
     mz_uint s;
     TINFL_GET_BITS(14, s, 3);
     m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
    }
    m_table_sizes[2] = 19;
   }
   for (; (int)m_type >= 0; m_type--) {
    int tree_next, tree_cur;
    huff_table *pTable;
    mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
    pTable = &m_tables[m_type];
    MZ_CLEAR_OBJ(total_syms);
    MZ_CLEAR_OBJ(pTable->m_look_up);
    MZ_CLEAR_OBJ(pTable->m_tree);
    for (i = 0; i < m_table_sizes[m_type]; ++i)
                    total_syms[pTable->m_code_size[i]]++;
    used_syms = 0, total = 0;
    next_code[0] = next_code[1] = 0;
    for (i = 1; i <= 15; ++i) {
     used_syms += total_syms[i];
     next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
    }
    if ((65536 != total) && (used_syms > 1)) {
     TINFL_CR_RETURN_FOREVER(35, STATUS_FAILED);
    }
    for (tree_next = -1, sym_index = 0; sym_index < m_table_sizes[m_type]; ++sym_index) {
     mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
     if (!code_size) continue;
     cur_code = next_code[code_size]++;
     for (l = code_size; l > 0; l--, cur_code >>= 1)
                        rev_code = (rev_code << 1) | (cur_code & 1);
     if (code_size <= FAST_LOOKUP_BITS) {
      mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
      while (rev_code < FAST_LOOKUP_SIZE) {
       pTable->m_look_up[rev_code] = k;
       rev_code += (1 << code_size);
      }
      continue;
     }
     if (0 == (tree_cur = pTable->m_look_up[rev_code & (FAST_LOOKUP_SIZE - 1)])) {
      pTable->m_look_up[rev_code & (FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
      tree_cur = tree_next;
      tree_next -= 2;
     }
     rev_code >>= (FAST_LOOKUP_BITS - 1);
     for (j = code_size; j > (FAST_LOOKUP_BITS + 1); j--) {
      tree_cur -= ((rev_code >>= 1) & 1);
      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];
     }
     tree_cur -= ((rev_code >>= 1) & 1);
     pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
    }
    if (m_type == 2) {
     for (counter = 0; counter < (m_table_sizes[0] + m_table_sizes[1]);) {
      mz_uint s;
      TINFL_HUFF_DECODE(16, dist, &m_tables[2]);
      if (dist < 16) {
       m_len_codes[counter++] = (mz_uint8)dist;
       continue;
      }
      if ((dist == 16) && (!counter)) {
       TINFL_CR_RETURN_FOREVER(17, STATUS_FAILED);
      }
      num_extra = "\02\03\07"[dist - 16];
      TINFL_GET_BITS(18, s, num_extra);
      s += "\03\03\013"[dist - 16];
      memset(m_len_codes + counter, (dist == 16) ? m_len_codes[counter - 1] : 0, s);
      counter += s;
     }
     if ((m_table_sizes[0] + m_table_sizes[1]) != counter) {
      TINFL_CR_RETURN_FOREVER(21, STATUS_FAILED);
     }
     memcpy(m_tables[0].m_code_size, m_len_codes, m_table_sizes[0]);
     memcpy(m_tables[1].m_code_size, m_len_codes + m_table_sizes[0], m_table_sizes[1]);
    }
   }
   for (;;) {
    mz_uint8 *pSrc;
    for (;;) {
     if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) {
      TINFL_HUFF_DECODE(23, counter, &m_tables[0]);
      if (counter >= 256) break;
      while (pOut_buf_cur >= pOut_buf_end) {
       TINFL_CR_RETURN(24, STATUS_HAS_MORE_OUTPUT);
      }
      *pOut_buf_cur++ = (mz_uint8)counter;
     }else{
      int sym2;
      mz_uint code_len;
#if TINFL_USE_64BIT_BITBUF
      if (num_bits < 30) {
       bit_buf |= (((bitbuf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
       pIn_buf_cur += 4;
       num_bits += 32;
      }
#else
      if (num_bits < 15) {
       bit_buf |= (((bitbuf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
       pIn_buf_cur += 2;
       num_bits += 16;
      }
#endif
      if ((sym2 = m_tables[0].m_look_up[bit_buf & (FAST_LOOKUP_SIZE - 1)]) >= 0)
	code_len = sym2 >> 9;
      else{
       code_len = FAST_LOOKUP_BITS;
       do{
        sym2 = m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
       }while (sym2 < 0);
      }
      counter = sym2;
      bit_buf >>= code_len;
      num_bits -= code_len;
      if (counter & 256) break;
#if !TINFL_USE_64BIT_BITBUF
      if (num_bits < 15) {
       bit_buf |= (((bitbuf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
       pIn_buf_cur += 2;
       num_bits += 16;
      }
#endif
      if ((sym2 = m_tables[0].m_look_up[bit_buf & (FAST_LOOKUP_SIZE - 1)]) >= 0)
	code_len = sym2 >> 9;
      else{
       code_len = FAST_LOOKUP_BITS;
       do{
        sym2 = m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
       }while (sym2 < 0);
      }
      bit_buf >>= code_len;
      num_bits -= code_len;
      pOut_buf_cur[0] = (mz_uint8)counter;
      if (sym2 & 256) {
       pOut_buf_cur++;
       counter = sym2;
       break;
      }
      pOut_buf_cur[1] = (mz_uint8)sym2;
      pOut_buf_cur += 2;
     }
    }
    if ((counter &= 511) == 256) break;
    num_extra = s_length_extra[counter - 257];
    counter = s_length_base[counter - 257];
    if (num_extra) {
     mz_uint extra_bits;
     TINFL_GET_BITS(25, extra_bits, num_extra);
     counter += extra_bits;
    }
    TINFL_HUFF_DECODE(26, dist, &m_tables[1]);
    num_extra = s_dist_extra[dist];
    dist = s_dist_base[dist];
    if (num_extra) {
     mz_uint extra_bits;
     TINFL_GET_BITS(27, extra_bits, num_extra);
     dist += extra_bits;
    }
    dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
    if ((dist > dist_from_out_buf_start) && (decomp_flags & USING_NON_WRAPPING_OUTPUT_BUF)) {
     TINFL_CR_RETURN_FOREVER(37, STATUS_FAILED);
    }
    pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
    if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
    while (counter--) {
     while (pOut_buf_cur >= pOut_buf_end) {
      TINFL_CR_RETURN(53, STATUS_HAS_MORE_OUTPUT);
     }
     *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
    }
    continue;
   }
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
    else if ((counter >= 9) && (counter <= dist)) {
     const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
     do{
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
      memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
#else
      ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
      ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
#endif
      pOut_buf_cur += 8;
     }while ((pSrc += 8) < pSrc_end);
     if ((counter &= 7) < 3) {
      if (counter) {
       pOut_buf_cur[0] = pSrc[0];
       if (counter > 1) pOut_buf_cur[1] = pSrc[1];
       pOut_buf_cur += counter;
      }
      continue;
     }
    }
#endif
    while(counter>2) {
     pOut_buf_cur[0] = pSrc[0];
     pOut_buf_cur[1] = pSrc[1];
     pOut_buf_cur[2] = pSrc[2];
     pOut_buf_cur += 3;
     pSrc += 3;
     counter -= 3;
    }
    if (counter > 0) {
     pOut_buf_cur[0] = pSrc[0];
     if (counter > 1) pOut_buf_cur[1] = pSrc[1];
     pOut_buf_cur += counter;
    }
   }
  }
 }while (!(m_final & 1));
    /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
    /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */
 TINFL_SKIP_BITS(32, num_bits & 7);
 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) {
  --pIn_buf_cur;
  num_bits -= 8;
 }
 bit_buf &= (bitbuf_t)((((uint64_t)1) << num_bits) - (uint64_t)1);
 if (decomp_flags & PARSE_ZLIB_HEADER) {
  for (counter = 0; counter < 4; ++counter) {
   mz_uint s;
   if (num_bits) TINFL_GET_BITS(41, s, 8);
   else TINFL_GET_BYTE(42, s);
   m_z_adler32 = (m_z_adler32 << 8) | s;
  }
 }
 TINFL_CR_RETURN_FOREVER(34, STATUS_DONE);
 TINFL_CR_FINISH
common_exit:
    /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
    /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
    /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */
 if ((status != STATUS_NEEDS_MORE_INPUT) && (status != STATUS_FAILED_CANNOT_MAKE_PROGRESS)) {
  while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) {
   --pIn_buf_cur;
   num_bits -= 8;
  }
 }
 m_num_bits = num_bits;
 m_bit_buf = bit_buf & (bitbuf_t)((((uint64_t)1) << num_bits) - (uint64_t)1);
 m_dist = dist;
 m_counter = counter;
 m_num_extra = num_extra;
 m_dist_from_out_buf_start = dist_from_out_buf_start;
 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
 if ((decomp_flags & (PARSE_ZLIB_HEADER | COMPUTE_ADLER32)) && (status >= 0)) {
  const mz_uint8 *ptr = pOut_buf_next;
  size_t buf_len = *pOut_buf_size;
  mz_uint32 i, s1 = m_check_adler32 & 0xffff, s2 = m_check_adler32 >> 16;
  size_t block_len = buf_len % 5552;
  while (buf_len) {
   for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
    s1 += ptr[0], s2 += s1;
    s1 += ptr[1], s2 += s1;
    s1 += ptr[2], s2 += s1;
    s1 += ptr[3], s2 += s1;
    s1 += ptr[4], s2 += s1;
    s1 += ptr[5], s2 += s1;
    s1 += ptr[6], s2 += s1;
    s1 += ptr[7], s2 += s1;
   }
   for (; i < block_len; ++i) s1 += *ptr++, s2 += s1;
   s1 %= 65521U, s2 %= 65521U;
   buf_len -= block_len;
   block_len = 5552;
  }
  m_check_adler32 = (s2 << 16) + s1;
  if ((status == STATUS_DONE) && (decomp_flags & PARSE_ZLIB_HEADER) && (m_check_adler32 != m_z_adler32))
	status = STATUS_ADLER32_MISMATCH;
 }
 return status;
}

/* Higher level helper functions. */
void* Inflate::mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t&Out_len, int flags) {
 void *pBuf = NULL, *pNew_buf;
 size_t src_buf_ofs = 0, out_buf_capacity = 0;
 Out_len = 0;
 Inflate decomp;
 for (;;) {
  size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - Out_len, new_out_buf_capacity;
  Status status = decomp.decompress((const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
		(mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + Out_len : NULL, &dst_buf_size,
                flags&~HAS_MORE_INPUT|USING_NON_WRAPPING_OUTPUT_BUF);
  if ((status < 0) || (status == STATUS_NEEDS_MORE_INPUT)) {
   free(pBuf);
   Out_len = 0;
   return NULL;
  }
  src_buf_ofs += src_buf_size;
  Out_len += dst_buf_size;
  if (status == STATUS_DONE) break;
  new_out_buf_capacity = out_buf_capacity * 2;
  if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
  pNew_buf = realloc(pBuf, new_out_buf_capacity);
  if (!pNew_buf) {
   free(pBuf);
   Out_len = 0;
   return NULL;
  }
  pBuf = pNew_buf;
  out_buf_capacity = new_out_buf_capacity;
 }
 return pBuf;
}

size_t Inflate::mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) {
 Inflate decomp;
 Status status = decomp.decompress((const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
	(flags & ~HAS_MORE_INPUT) | USING_NON_WRAPPING_OUTPUT_BUF);
 return status != STATUS_DONE ? MEM_TO_MEM_FAILED : out_buf_len;
}

int Inflate::mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, cb_t cb, void*cbd, int flags) {
 int result = 0;
 mz_uint8 dict[LZ_DICT_SIZE];
 size_t in_buf_ofs = 0, dict_ofs = 0;
 Inflate decomp;
 for (;;) {
  size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = Inflate::LZ_DICT_SIZE - dict_ofs;
  Status status = decomp.decompress((const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, dict, dict + dict_ofs, &dst_buf_size,
                                               (flags & ~(HAS_MORE_INPUT | USING_NON_WRAPPING_OUTPUT_BUF)));
  in_buf_ofs += in_buf_size;
  if (dst_buf_size && !cb(dict+dict_ofs,(int)dst_buf_size,cbd)) break;
  if (status != STATUS_HAS_MORE_OUTPUT) {
   result = status == Inflate::STATUS_DONE;
   break;
  }
  dict_ofs = dict_ofs+dst_buf_size & LZ_DICT_SIZE-1;
 }
 *pIn_buf_size = in_buf_ofs;
 return result;
}

Detected encoding: ASCII (7 bit)2