cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

miniz.c (319839B)


      1#include "miniz.h"
      2/**************************************************************************
      3 *
      4 * Copyright 2013-2014 RAD Game Tools and Valve Software
      5 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
      6 * All Rights Reserved.
      7 *
      8 * Permission is hereby granted, free of charge, to any person obtaining a copy
      9 * of this software and associated documentation files (the "Software"), to deal
     10 * in the Software without restriction, including without limitation the rights
     11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     12 * copies of the Software, and to permit persons to whom the Software is
     13 * furnished to do so, subject to the following conditions:
     14 *
     15 * The above copyright notice and this permission notice shall be included in
     16 * all copies or substantial portions of the Software.
     17 *
     18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     24 * THE SOFTWARE.
     25 *
     26 **************************************************************************/
     27
     28
     29
     30typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
     31typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
     32typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
     33
     34#ifdef __cplusplus
     35extern "C" {
     36#endif
     37
     38/* ------------------- zlib-style API's */
     39
     40mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
     41{
     42    mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
     43    size_t block_len = buf_len % 5552;
     44    if (!ptr)
     45        return MZ_ADLER32_INIT;
     46    while (buf_len)
     47    {
     48        for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
     49        {
     50            s1 += ptr[0], s2 += s1;
     51            s1 += ptr[1], s2 += s1;
     52            s1 += ptr[2], s2 += s1;
     53            s1 += ptr[3], s2 += s1;
     54            s1 += ptr[4], s2 += s1;
     55            s1 += ptr[5], s2 += s1;
     56            s1 += ptr[6], s2 += s1;
     57            s1 += ptr[7], s2 += s1;
     58        }
     59        for (; i < block_len; ++i)
     60            s1 += *ptr++, s2 += s1;
     61        s1 %= 65521U, s2 %= 65521U;
     62        buf_len -= block_len;
     63        block_len = 5552;
     64    }
     65    return (s2 << 16) + s1;
     66}
     67
     68/* 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/ */
     69#if 0
     70    mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
     71    {
     72        static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
     73                                               0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
     74        mz_uint32 crcu32 = (mz_uint32)crc;
     75        if (!ptr)
     76            return MZ_CRC32_INIT;
     77        crcu32 = ~crcu32;
     78        while (buf_len--)
     79        {
     80            mz_uint8 b = *ptr++;
     81            crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
     82            crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
     83        }
     84        return ~crcu32;
     85    }
     86#elif defined(USE_EXTERNAL_MZCRC)
     87/* If USE_EXTERNAL_CRC is defined, an external module will export the
     88 * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version.
     89 * Depending on the impl, it may be necessary to ~ the input/output crc values.
     90 */
     91mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
     92#else
     93/* Faster, but larger CPU cache footprint.
     94 */
     95mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
     96{
     97    static const mz_uint32 s_crc_table[256] =
     98        {
     99          0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
    100          0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
    101          0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
    102          0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
    103          0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
    104          0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
    105          0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
    106          0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
    107          0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
    108          0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
    109          0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
    110          0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
    111          0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
    112          0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
    113          0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
    114          0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
    115          0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
    116          0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
    117          0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
    118          0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
    119          0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
    120          0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
    121          0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
    122          0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
    123          0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
    124          0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
    125          0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
    126          0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
    127          0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
    128          0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
    129          0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
    130          0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
    131          0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
    132          0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
    133          0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
    134          0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
    135          0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
    136        };
    137
    138    mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
    139    const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
    140
    141    while (buf_len >= 4)
    142    {
    143        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
    144        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
    145        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
    146        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
    147        pByte_buf += 4;
    148        buf_len -= 4;
    149    }
    150
    151    while (buf_len)
    152    {
    153        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
    154        ++pByte_buf;
    155        --buf_len;
    156    }
    157
    158    return ~crc32;
    159}
    160#endif
    161
    162void mz_free(void *p)
    163{
    164    MZ_FREE(p);
    165}
    166
    167MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
    168{
    169    (void)opaque, (void)items, (void)size;
    170    return MZ_MALLOC(items * size);
    171}
    172MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address)
    173{
    174    (void)opaque, (void)address;
    175    MZ_FREE(address);
    176}
    177MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
    178{
    179    (void)opaque, (void)address, (void)items, (void)size;
    180    return MZ_REALLOC(address, items * size);
    181}
    182
    183const char *mz_version(void)
    184{
    185    return MZ_VERSION;
    186}
    187
    188#ifndef MINIZ_NO_ZLIB_APIS
    189
    190int mz_deflateInit(mz_streamp pStream, int level)
    191{
    192    return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
    193}
    194
    195int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
    196{
    197    tdefl_compressor *pComp;
    198    mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
    199
    200    if (!pStream)
    201        return MZ_STREAM_ERROR;
    202    if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
    203        return MZ_PARAM_ERROR;
    204
    205    pStream->data_type = 0;
    206    pStream->adler = MZ_ADLER32_INIT;
    207    pStream->msg = NULL;
    208    pStream->reserved = 0;
    209    pStream->total_in = 0;
    210    pStream->total_out = 0;
    211    if (!pStream->zalloc)
    212        pStream->zalloc = miniz_def_alloc_func;
    213    if (!pStream->zfree)
    214        pStream->zfree = miniz_def_free_func;
    215
    216    pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
    217    if (!pComp)
    218        return MZ_MEM_ERROR;
    219
    220    pStream->state = (struct mz_internal_state *)pComp;
    221
    222    if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
    223    {
    224        mz_deflateEnd(pStream);
    225        return MZ_PARAM_ERROR;
    226    }
    227
    228    return MZ_OK;
    229}
    230
    231int mz_deflateReset(mz_streamp pStream)
    232{
    233    if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
    234        return MZ_STREAM_ERROR;
    235    pStream->total_in = pStream->total_out = 0;
    236    tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
    237    return MZ_OK;
    238}
    239
    240int mz_deflate(mz_streamp pStream, int flush)
    241{
    242    size_t in_bytes, out_bytes;
    243    mz_ulong orig_total_in, orig_total_out;
    244    int mz_status = MZ_OK;
    245
    246    if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
    247        return MZ_STREAM_ERROR;
    248    if (!pStream->avail_out)
    249        return MZ_BUF_ERROR;
    250
    251    if (flush == MZ_PARTIAL_FLUSH)
    252        flush = MZ_SYNC_FLUSH;
    253
    254    if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
    255        return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
    256
    257    orig_total_in = pStream->total_in;
    258    orig_total_out = pStream->total_out;
    259    for (;;)
    260    {
    261        tdefl_status defl_status;
    262        in_bytes = pStream->avail_in;
    263        out_bytes = pStream->avail_out;
    264
    265        defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
    266        pStream->next_in += (mz_uint)in_bytes;
    267        pStream->avail_in -= (mz_uint)in_bytes;
    268        pStream->total_in += (mz_uint)in_bytes;
    269        pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
    270
    271        pStream->next_out += (mz_uint)out_bytes;
    272        pStream->avail_out -= (mz_uint)out_bytes;
    273        pStream->total_out += (mz_uint)out_bytes;
    274
    275        if (defl_status < 0)
    276        {
    277            mz_status = MZ_STREAM_ERROR;
    278            break;
    279        }
    280        else if (defl_status == TDEFL_STATUS_DONE)
    281        {
    282            mz_status = MZ_STREAM_END;
    283            break;
    284        }
    285        else if (!pStream->avail_out)
    286            break;
    287        else if ((!pStream->avail_in) && (flush != MZ_FINISH))
    288        {
    289            if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
    290                break;
    291            return MZ_BUF_ERROR; /* Can't make forward progress without some input.
    292 */
    293        }
    294    }
    295    return mz_status;
    296}
    297
    298int mz_deflateEnd(mz_streamp pStream)
    299{
    300    if (!pStream)
    301        return MZ_STREAM_ERROR;
    302    if (pStream->state)
    303    {
    304        pStream->zfree(pStream->opaque, pStream->state);
    305        pStream->state = NULL;
    306    }
    307    return MZ_OK;
    308}
    309
    310mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
    311{
    312    (void)pStream;
    313    /* 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.) */
    314    return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
    315}
    316
    317int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
    318{
    319    int status;
    320    mz_stream stream;
    321    memset(&stream, 0, sizeof(stream));
    322
    323    /* In case mz_ulong is 64-bits (argh I hate longs). */
    324    if ((source_len | *pDest_len) > 0xFFFFFFFFU)
    325        return MZ_PARAM_ERROR;
    326
    327    stream.next_in = pSource;
    328    stream.avail_in = (mz_uint32)source_len;
    329    stream.next_out = pDest;
    330    stream.avail_out = (mz_uint32)*pDest_len;
    331
    332    status = mz_deflateInit(&stream, level);
    333    if (status != MZ_OK)
    334        return status;
    335
    336    status = mz_deflate(&stream, MZ_FINISH);
    337    if (status != MZ_STREAM_END)
    338    {
    339        mz_deflateEnd(&stream);
    340        return (status == MZ_OK) ? MZ_BUF_ERROR : status;
    341    }
    342
    343    *pDest_len = stream.total_out;
    344    return mz_deflateEnd(&stream);
    345}
    346
    347int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
    348{
    349    return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
    350}
    351
    352mz_ulong mz_compressBound(mz_ulong source_len)
    353{
    354    return mz_deflateBound(NULL, source_len);
    355}
    356
    357typedef struct
    358{
    359    tinfl_decompressor m_decomp;
    360    mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
    361    int m_window_bits;
    362    mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
    363    tinfl_status m_last_status;
    364} inflate_state;
    365
    366int mz_inflateInit2(mz_streamp pStream, int window_bits)
    367{
    368    inflate_state *pDecomp;
    369    if (!pStream)
    370        return MZ_STREAM_ERROR;
    371    if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
    372        return MZ_PARAM_ERROR;
    373
    374    pStream->data_type = 0;
    375    pStream->adler = 0;
    376    pStream->msg = NULL;
    377    pStream->total_in = 0;
    378    pStream->total_out = 0;
    379    pStream->reserved = 0;
    380    if (!pStream->zalloc)
    381        pStream->zalloc = miniz_def_alloc_func;
    382    if (!pStream->zfree)
    383        pStream->zfree = miniz_def_free_func;
    384
    385    pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
    386    if (!pDecomp)
    387        return MZ_MEM_ERROR;
    388
    389    pStream->state = (struct mz_internal_state *)pDecomp;
    390
    391    tinfl_init(&pDecomp->m_decomp);
    392    pDecomp->m_dict_ofs = 0;
    393    pDecomp->m_dict_avail = 0;
    394    pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
    395    pDecomp->m_first_call = 1;
    396    pDecomp->m_has_flushed = 0;
    397    pDecomp->m_window_bits = window_bits;
    398
    399    return MZ_OK;
    400}
    401
    402int mz_inflateInit(mz_streamp pStream)
    403{
    404    return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
    405}
    406
    407int mz_inflateReset(mz_streamp pStream)
    408{
    409    inflate_state *pDecomp;
    410    if (!pStream)
    411        return MZ_STREAM_ERROR;
    412
    413    pStream->data_type = 0;
    414    pStream->adler = 0;
    415    pStream->msg = NULL;
    416    pStream->total_in = 0;
    417    pStream->total_out = 0;
    418    pStream->reserved = 0;
    419
    420    pDecomp = (inflate_state *)pStream->state;
    421
    422    tinfl_init(&pDecomp->m_decomp);
    423    pDecomp->m_dict_ofs = 0;
    424    pDecomp->m_dict_avail = 0;
    425    pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
    426    pDecomp->m_first_call = 1;
    427    pDecomp->m_has_flushed = 0;
    428    /* pDecomp->m_window_bits = window_bits */;
    429
    430    return MZ_OK;
    431}
    432
    433int mz_inflate(mz_streamp pStream, int flush)
    434{
    435    inflate_state *pState;
    436    mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
    437    size_t in_bytes, out_bytes, orig_avail_in;
    438    tinfl_status status;
    439
    440    if ((!pStream) || (!pStream->state))
    441        return MZ_STREAM_ERROR;
    442    if (flush == MZ_PARTIAL_FLUSH)
    443        flush = MZ_SYNC_FLUSH;
    444    if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
    445        return MZ_STREAM_ERROR;
    446
    447    pState = (inflate_state *)pStream->state;
    448    if (pState->m_window_bits > 0)
    449        decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
    450    orig_avail_in = pStream->avail_in;
    451
    452    first_call = pState->m_first_call;
    453    pState->m_first_call = 0;
    454    if (pState->m_last_status < 0)
    455        return MZ_DATA_ERROR;
    456
    457    if (pState->m_has_flushed && (flush != MZ_FINISH))
    458        return MZ_STREAM_ERROR;
    459    pState->m_has_flushed |= (flush == MZ_FINISH);
    460
    461    if ((flush == MZ_FINISH) && (first_call))
    462    {
    463        /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
    464        decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
    465        in_bytes = pStream->avail_in;
    466        out_bytes = pStream->avail_out;
    467        status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
    468        pState->m_last_status = status;
    469        pStream->next_in += (mz_uint)in_bytes;
    470        pStream->avail_in -= (mz_uint)in_bytes;
    471        pStream->total_in += (mz_uint)in_bytes;
    472        pStream->adler = tinfl_get_adler32(&pState->m_decomp);
    473        pStream->next_out += (mz_uint)out_bytes;
    474        pStream->avail_out -= (mz_uint)out_bytes;
    475        pStream->total_out += (mz_uint)out_bytes;
    476
    477        if (status < 0)
    478            return MZ_DATA_ERROR;
    479        else if (status != TINFL_STATUS_DONE)
    480        {
    481            pState->m_last_status = TINFL_STATUS_FAILED;
    482            return MZ_BUF_ERROR;
    483        }
    484        return MZ_STREAM_END;
    485    }
    486    /* flush != MZ_FINISH then we must assume there's more input. */
    487    if (flush != MZ_FINISH)
    488        decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
    489
    490    if (pState->m_dict_avail)
    491    {
    492        n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
    493        memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
    494        pStream->next_out += n;
    495        pStream->avail_out -= n;
    496        pStream->total_out += n;
    497        pState->m_dict_avail -= n;
    498        pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
    499        return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
    500    }
    501
    502    for (;;)
    503    {
    504        in_bytes = pStream->avail_in;
    505        out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
    506
    507        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);
    508        pState->m_last_status = status;
    509
    510        pStream->next_in += (mz_uint)in_bytes;
    511        pStream->avail_in -= (mz_uint)in_bytes;
    512        pStream->total_in += (mz_uint)in_bytes;
    513        pStream->adler = tinfl_get_adler32(&pState->m_decomp);
    514
    515        pState->m_dict_avail = (mz_uint)out_bytes;
    516
    517        n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
    518        memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
    519        pStream->next_out += n;
    520        pStream->avail_out -= n;
    521        pStream->total_out += n;
    522        pState->m_dict_avail -= n;
    523        pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
    524
    525        if (status < 0)
    526            return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
    527        else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
    528            return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
    529        else if (flush == MZ_FINISH)
    530        {
    531            /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
    532            if (status == TINFL_STATUS_DONE)
    533                return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
    534            /* 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. */
    535            else if (!pStream->avail_out)
    536                return MZ_BUF_ERROR;
    537        }
    538        else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
    539            break;
    540    }
    541
    542    return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
    543}
    544
    545int mz_inflateEnd(mz_streamp pStream)
    546{
    547    if (!pStream)
    548        return MZ_STREAM_ERROR;
    549    if (pStream->state)
    550    {
    551        pStream->zfree(pStream->opaque, pStream->state);
    552        pStream->state = NULL;
    553    }
    554    return MZ_OK;
    555}
    556int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len)
    557{
    558    mz_stream stream;
    559    int status;
    560    memset(&stream, 0, sizeof(stream));
    561
    562    /* In case mz_ulong is 64-bits (argh I hate longs). */
    563    if ((*pSource_len | *pDest_len) > 0xFFFFFFFFU)
    564        return MZ_PARAM_ERROR;
    565
    566    stream.next_in = pSource;
    567    stream.avail_in = (mz_uint32)*pSource_len;
    568    stream.next_out = pDest;
    569    stream.avail_out = (mz_uint32)*pDest_len;
    570
    571    status = mz_inflateInit(&stream);
    572    if (status != MZ_OK)
    573        return status;
    574
    575    status = mz_inflate(&stream, MZ_FINISH);
    576    *pSource_len = *pSource_len - stream.avail_in;
    577    if (status != MZ_STREAM_END)
    578    {
    579        mz_inflateEnd(&stream);
    580        return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
    581    }
    582    *pDest_len = stream.total_out;
    583
    584    return mz_inflateEnd(&stream);
    585}
    586
    587int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
    588{
    589    return mz_uncompress2(pDest, pDest_len, pSource, &source_len);
    590}
    591
    592const char *mz_error(int err)
    593{
    594    static struct
    595    {
    596        int m_err;
    597        const char *m_pDesc;
    598    } s_error_descs[] =
    599        {
    600          { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { 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" }
    601        };
    602    mz_uint i;
    603    for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
    604        if (s_error_descs[i].m_err == err)
    605            return s_error_descs[i].m_pDesc;
    606    return NULL;
    607}
    608
    609#endif /*MINIZ_NO_ZLIB_APIS */
    610
    611#ifdef __cplusplus
    612}
    613#endif
    614
    615/*
    616  This is free and unencumbered software released into the public domain.
    617
    618  Anyone is free to copy, modify, publish, use, compile, sell, or
    619  distribute this software, either in source code form or as a compiled
    620  binary, for any purpose, commercial or non-commercial, and by any
    621  means.
    622
    623  In jurisdictions that recognize copyright laws, the author or authors
    624  of this software dedicate any and all copyright interest in the
    625  software to the public domain. We make this dedication for the benefit
    626  of the public at large and to the detriment of our heirs and
    627  successors. We intend this dedication to be an overt act of
    628  relinquishment in perpetuity of all present and future rights to this
    629  software under copyright law.
    630
    631  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    632  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    633  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    634  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    635  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    636  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    637  OTHER DEALINGS IN THE SOFTWARE.
    638
    639  For more information, please refer to <http://unlicense.org/>
    640*/
    641/**************************************************************************
    642 *
    643 * Copyright 2013-2014 RAD Game Tools and Valve Software
    644 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
    645 * All Rights Reserved.
    646 *
    647 * Permission is hereby granted, free of charge, to any person obtaining a copy
    648 * of this software and associated documentation files (the "Software"), to deal
    649 * in the Software without restriction, including without limitation the rights
    650 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    651 * copies of the Software, and to permit persons to whom the Software is
    652 * furnished to do so, subject to the following conditions:
    653 *
    654 * The above copyright notice and this permission notice shall be included in
    655 * all copies or substantial portions of the Software.
    656 *
    657 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    658 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    659 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    660 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    661 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    662 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    663 * THE SOFTWARE.
    664 *
    665 **************************************************************************/
    666
    667
    668
    669#ifdef __cplusplus
    670extern "C" {
    671#endif
    672
    673/* ------------------- Low-level Compression (independent from all decompression API's) */
    674
    675/* Purposely making these tables static for faster init and thread safety. */
    676static const mz_uint16 s_tdefl_len_sym[256] =
    677    {
    678      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,
    679      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,
    680      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,
    681      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,
    682      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,
    683      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,
    684      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,
    685      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
    686    };
    687
    688static const mz_uint8 s_tdefl_len_extra[256] =
    689    {
    690      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,
    691      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,
    692      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    693      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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
    694    };
    695
    696static const mz_uint8 s_tdefl_small_dist_sym[512] =
    697    {
    698      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,
    699      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,
    700      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,
    701      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,
    702      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,
    703      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,
    704      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    705      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    706      16, 16, 16, 16, 16, 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,
    707      17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    708      17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
    709      17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
    710    };
    711
    712static const mz_uint8 s_tdefl_small_dist_extra[512] =
    713    {
    714      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,
    715      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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,
    716      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    717      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 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,
    718      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    719      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    720      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    721      7, 7, 7, 7, 7, 7, 7, 7
    722    };
    723
    724static const mz_uint8 s_tdefl_large_dist_sym[128] =
    725    {
    726      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,
    727      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,
    728      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
    729    };
    730
    731static const mz_uint8 s_tdefl_large_dist_extra[128] =
    732    {
    733      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,
    734      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,
    735      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
    736    };
    737
    738/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
    739typedef struct
    740{
    741    mz_uint16 m_key, m_sym_index;
    742} tdefl_sym_freq;
    743static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
    744{
    745    mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
    746    tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
    747    MZ_CLEAR_OBJ(hist);
    748    for (i = 0; i < num_syms; i++)
    749    {
    750        mz_uint freq = pSyms0[i].m_key;
    751        hist[freq & 0xFF]++;
    752        hist[256 + ((freq >> 8) & 0xFF)]++;
    753    }
    754    while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
    755        total_passes--;
    756    for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
    757    {
    758        const mz_uint32 *pHist = &hist[pass << 8];
    759        mz_uint offsets[256], cur_ofs = 0;
    760        for (i = 0; i < 256; i++)
    761        {
    762            offsets[i] = cur_ofs;
    763            cur_ofs += pHist[i];
    764        }
    765        for (i = 0; i < num_syms; i++)
    766            pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
    767        {
    768            tdefl_sym_freq *t = pCur_syms;
    769            pCur_syms = pNew_syms;
    770            pNew_syms = t;
    771        }
    772    }
    773    return pCur_syms;
    774}
    775
    776/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
    777static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
    778{
    779    int root, leaf, next, avbl, used, dpth;
    780    if (n == 0)
    781        return;
    782    else if (n == 1)
    783    {
    784        A[0].m_key = 1;
    785        return;
    786    }
    787    A[0].m_key += A[1].m_key;
    788    root = 0;
    789    leaf = 2;
    790    for (next = 1; next < n - 1; next++)
    791    {
    792        if (leaf >= n || A[root].m_key < A[leaf].m_key)
    793        {
    794            A[next].m_key = A[root].m_key;
    795            A[root++].m_key = (mz_uint16)next;
    796        }
    797        else
    798            A[next].m_key = A[leaf++].m_key;
    799        if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
    800        {
    801            A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
    802            A[root++].m_key = (mz_uint16)next;
    803        }
    804        else
    805            A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
    806    }
    807    A[n - 2].m_key = 0;
    808    for (next = n - 3; next >= 0; next--)
    809        A[next].m_key = A[A[next].m_key].m_key + 1;
    810    avbl = 1;
    811    used = dpth = 0;
    812    root = n - 2;
    813    next = n - 1;
    814    while (avbl > 0)
    815    {
    816        while (root >= 0 && (int)A[root].m_key == dpth)
    817        {
    818            used++;
    819            root--;
    820        }
    821        while (avbl > used)
    822        {
    823            A[next--].m_key = (mz_uint16)(dpth);
    824            avbl--;
    825        }
    826        avbl = 2 * used;
    827        dpth++;
    828        used = 0;
    829    }
    830}
    831
    832/* Limits canonical Huffman code table's max code size. */
    833enum
    834{
    835    TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32
    836};
    837static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
    838{
    839    int i;
    840    mz_uint32 total = 0;
    841    if (code_list_len <= 1)
    842        return;
    843    for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
    844        pNum_codes[max_code_size] += pNum_codes[i];
    845    for (i = max_code_size; i > 0; i--)
    846        total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
    847    while (total != (1UL << max_code_size))
    848    {
    849        pNum_codes[max_code_size]--;
    850        for (i = max_code_size - 1; i > 0; i--)
    851            if (pNum_codes[i])
    852            {
    853                pNum_codes[i]--;
    854                pNum_codes[i + 1] += 2;
    855                break;
    856            }
    857        total--;
    858    }
    859}
    860
    861static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
    862{
    863    int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
    864    mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
    865    MZ_CLEAR_OBJ(num_codes);
    866    if (static_table)
    867    {
    868        for (i = 0; i < table_len; i++)
    869            num_codes[d->m_huff_code_sizes[table_num][i]]++;
    870    }
    871    else
    872    {
    873        tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
    874        int num_used_syms = 0;
    875        const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
    876        for (i = 0; i < table_len; i++)
    877            if (pSym_count[i])
    878            {
    879                syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
    880                syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
    881            }
    882
    883        pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
    884        tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
    885
    886        for (i = 0; i < num_used_syms; i++)
    887            num_codes[pSyms[i].m_key]++;
    888
    889        tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
    890
    891        MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
    892        MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
    893        for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
    894            for (l = num_codes[i]; l > 0; l--)
    895                d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
    896    }
    897
    898    next_code[1] = 0;
    899    for (j = 0, i = 2; i <= code_size_limit; i++)
    900        next_code[i] = j = ((j + num_codes[i - 1]) << 1);
    901
    902    for (i = 0; i < table_len; i++)
    903    {
    904        mz_uint rev_code = 0, code, code_size;
    905        if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
    906            continue;
    907        code = next_code[code_size]++;
    908        for (l = code_size; l > 0; l--, code >>= 1)
    909            rev_code = (rev_code << 1) | (code & 1);
    910        d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
    911    }
    912}
    913
    914#define TDEFL_PUT_BITS(b, l)                                       \
    915    do                                                             \
    916    {                                                              \
    917        mz_uint bits = b;                                          \
    918        mz_uint len = l;                                           \
    919        MZ_ASSERT(bits <= ((1U << len) - 1U));                     \
    920        d->m_bit_buffer |= (bits << d->m_bits_in);                 \
    921        d->m_bits_in += len;                                       \
    922        while (d->m_bits_in >= 8)                                  \
    923        {                                                          \
    924            if (d->m_pOutput_buf < d->m_pOutput_buf_end)           \
    925                *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
    926            d->m_bit_buffer >>= 8;                                 \
    927            d->m_bits_in -= 8;                                     \
    928        }                                                          \
    929    }                                                              \
    930    MZ_MACRO_END
    931
    932#define TDEFL_RLE_PREV_CODE_SIZE()                                                                                       \
    933    {                                                                                                                    \
    934        if (rle_repeat_count)                                                                                            \
    935        {                                                                                                                \
    936            if (rle_repeat_count < 3)                                                                                    \
    937            {                                                                                                            \
    938                d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
    939                while (rle_repeat_count--)                                                                               \
    940                    packed_code_sizes[num_packed_code_sizes++] = prev_code_size;                                         \
    941            }                                                                                                            \
    942            else                                                                                                         \
    943            {                                                                                                            \
    944                d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);                                        \
    945                packed_code_sizes[num_packed_code_sizes++] = 16;                                                         \
    946                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3);                           \
    947            }                                                                                                            \
    948            rle_repeat_count = 0;                                                                                        \
    949        }                                                                                                                \
    950    }
    951
    952#define TDEFL_RLE_ZERO_CODE_SIZE()                                                         \
    953    {                                                                                      \
    954        if (rle_z_count)                                                                   \
    955        {                                                                                  \
    956            if (rle_z_count < 3)                                                           \
    957            {                                                                              \
    958                d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);  \
    959                while (rle_z_count--)                                                      \
    960                    packed_code_sizes[num_packed_code_sizes++] = 0;                        \
    961            }                                                                              \
    962            else if (rle_z_count <= 10)                                                    \
    963            {                                                                              \
    964                d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);          \
    965                packed_code_sizes[num_packed_code_sizes++] = 17;                           \
    966                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3);  \
    967            }                                                                              \
    968            else                                                                           \
    969            {                                                                              \
    970                d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);          \
    971                packed_code_sizes[num_packed_code_sizes++] = 18;                           \
    972                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
    973            }                                                                              \
    974            rle_z_count = 0;                                                               \
    975        }                                                                                  \
    976    }
    977
    978static 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 };
    979
    980static void tdefl_start_dynamic_block(tdefl_compressor *d)
    981{
    982    int num_lit_codes, num_dist_codes, num_bit_lengths;
    983    mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
    984    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;
    985
    986    d->m_huff_count[0][256] = 1;
    987
    988    tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
    989    tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
    990
    991    for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
    992        if (d->m_huff_code_sizes[0][num_lit_codes - 1])
    993            break;
    994    for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
    995        if (d->m_huff_code_sizes[1][num_dist_codes - 1])
    996            break;
    997
    998    memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
    999    memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
   1000    total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
   1001    num_packed_code_sizes = 0;
   1002    rle_z_count = 0;
   1003    rle_repeat_count = 0;
   1004
   1005    memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
   1006    for (i = 0; i < total_code_sizes_to_pack; i++)
   1007    {
   1008        mz_uint8 code_size = code_sizes_to_pack[i];
   1009        if (!code_size)
   1010        {
   1011            TDEFL_RLE_PREV_CODE_SIZE();
   1012            if (++rle_z_count == 138)
   1013            {
   1014                TDEFL_RLE_ZERO_CODE_SIZE();
   1015            }
   1016        }
   1017        else
   1018        {
   1019            TDEFL_RLE_ZERO_CODE_SIZE();
   1020            if (code_size != prev_code_size)
   1021            {
   1022                TDEFL_RLE_PREV_CODE_SIZE();
   1023                d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
   1024                packed_code_sizes[num_packed_code_sizes++] = code_size;
   1025            }
   1026            else if (++rle_repeat_count == 6)
   1027            {
   1028                TDEFL_RLE_PREV_CODE_SIZE();
   1029            }
   1030        }
   1031        prev_code_size = code_size;
   1032    }
   1033    if (rle_repeat_count)
   1034    {
   1035        TDEFL_RLE_PREV_CODE_SIZE();
   1036    }
   1037    else
   1038    {
   1039        TDEFL_RLE_ZERO_CODE_SIZE();
   1040    }
   1041
   1042    tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
   1043
   1044    TDEFL_PUT_BITS(2, 2);
   1045
   1046    TDEFL_PUT_BITS(num_lit_codes - 257, 5);
   1047    TDEFL_PUT_BITS(num_dist_codes - 1, 5);
   1048
   1049    for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
   1050        if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
   1051            break;
   1052    num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
   1053    TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
   1054    for (i = 0; (int)i < num_bit_lengths; i++)
   1055        TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
   1056
   1057    for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
   1058    {
   1059        mz_uint code = packed_code_sizes[packed_code_sizes_index++];
   1060        MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
   1061        TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
   1062        if (code >= 16)
   1063            TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
   1064    }
   1065}
   1066
   1067static void tdefl_start_static_block(tdefl_compressor *d)
   1068{
   1069    mz_uint i;
   1070    mz_uint8 *p = &d->m_huff_code_sizes[0][0];
   1071
   1072    for (i = 0; i <= 143; ++i)
   1073        *p++ = 8;
   1074    for (; i <= 255; ++i)
   1075        *p++ = 9;
   1076    for (; i <= 279; ++i)
   1077        *p++ = 7;
   1078    for (; i <= 287; ++i)
   1079        *p++ = 8;
   1080
   1081    memset(d->m_huff_code_sizes[1], 5, 32);
   1082
   1083    tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
   1084    tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
   1085
   1086    TDEFL_PUT_BITS(1, 2);
   1087}
   1088
   1089static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
   1090
   1091#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
   1092static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
   1093{
   1094    mz_uint flags;
   1095    mz_uint8 *pLZ_codes;
   1096    mz_uint8 *pOutput_buf = d->m_pOutput_buf;
   1097    mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
   1098    mz_uint64 bit_buffer = d->m_bit_buffer;
   1099    mz_uint bits_in = d->m_bits_in;
   1100
   1101#define TDEFL_PUT_BITS_FAST(b, l)                    \
   1102    {                                                \
   1103        bit_buffer |= (((mz_uint64)(b)) << bits_in); \
   1104        bits_in += (l);                              \
   1105    }
   1106
   1107    flags = 1;
   1108    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
   1109    {
   1110        if (flags == 1)
   1111            flags = *pLZ_codes++ | 0x100;
   1112
   1113        if (flags & 1)
   1114        {
   1115            mz_uint s0, s1, n0, n1, sym, num_extra_bits;
   1116            mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
   1117            pLZ_codes += 3;
   1118
   1119            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
   1120            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]]);
   1121            TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
   1122
   1123            /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
   1124            s0 = s_tdefl_small_dist_sym[match_dist & 511];
   1125            n0 = s_tdefl_small_dist_extra[match_dist & 511];
   1126            s1 = s_tdefl_large_dist_sym[match_dist >> 8];
   1127            n1 = s_tdefl_large_dist_extra[match_dist >> 8];
   1128            sym = (match_dist < 512) ? s0 : s1;
   1129            num_extra_bits = (match_dist < 512) ? n0 : n1;
   1130
   1131            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
   1132            TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
   1133            TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
   1134        }
   1135        else
   1136        {
   1137            mz_uint lit = *pLZ_codes++;
   1138            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
   1139            TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
   1140
   1141            if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
   1142            {
   1143                flags >>= 1;
   1144                lit = *pLZ_codes++;
   1145                MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
   1146                TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
   1147
   1148                if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
   1149                {
   1150                    flags >>= 1;
   1151                    lit = *pLZ_codes++;
   1152                    MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
   1153                    TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
   1154                }
   1155            }
   1156        }
   1157
   1158        if (pOutput_buf >= d->m_pOutput_buf_end)
   1159            return MZ_FALSE;
   1160
   1161        *(mz_uint64 *)pOutput_buf = bit_buffer;
   1162        pOutput_buf += (bits_in >> 3);
   1163        bit_buffer >>= (bits_in & ~7);
   1164        bits_in &= 7;
   1165    }
   1166
   1167#undef TDEFL_PUT_BITS_FAST
   1168
   1169    d->m_pOutput_buf = pOutput_buf;
   1170    d->m_bits_in = 0;
   1171    d->m_bit_buffer = 0;
   1172
   1173    while (bits_in)
   1174    {
   1175        mz_uint32 n = MZ_MIN(bits_in, 16);
   1176        TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
   1177        bit_buffer >>= n;
   1178        bits_in -= n;
   1179    }
   1180
   1181    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
   1182
   1183    return (d->m_pOutput_buf < d->m_pOutput_buf_end);
   1184}
   1185#else
   1186static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
   1187{
   1188    mz_uint flags;
   1189    mz_uint8 *pLZ_codes;
   1190
   1191    flags = 1;
   1192    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
   1193    {
   1194        if (flags == 1)
   1195            flags = *pLZ_codes++ | 0x100;
   1196        if (flags & 1)
   1197        {
   1198            mz_uint sym, num_extra_bits;
   1199            mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
   1200            pLZ_codes += 3;
   1201
   1202            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
   1203            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]]);
   1204            TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
   1205
   1206            if (match_dist < 512)
   1207            {
   1208                sym = s_tdefl_small_dist_sym[match_dist];
   1209                num_extra_bits = s_tdefl_small_dist_extra[match_dist];
   1210            }
   1211            else
   1212            {
   1213                sym = s_tdefl_large_dist_sym[match_dist >> 8];
   1214                num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
   1215            }
   1216            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
   1217            TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
   1218            TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
   1219        }
   1220        else
   1221        {
   1222            mz_uint lit = *pLZ_codes++;
   1223            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
   1224            TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
   1225        }
   1226    }
   1227
   1228    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
   1229
   1230    return (d->m_pOutput_buf < d->m_pOutput_buf_end);
   1231}
   1232#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
   1233
   1234static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
   1235{
   1236    if (static_block)
   1237        tdefl_start_static_block(d);
   1238    else
   1239        tdefl_start_dynamic_block(d);
   1240    return tdefl_compress_lz_codes(d);
   1241}
   1242
   1243static int tdefl_flush_block(tdefl_compressor *d, int flush)
   1244{
   1245    mz_uint saved_bit_buf, saved_bits_in;
   1246    mz_uint8 *pSaved_output_buf;
   1247    mz_bool comp_block_succeeded = MZ_FALSE;
   1248    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;
   1249    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;
   1250
   1251    d->m_pOutput_buf = pOutput_buf_start;
   1252    d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
   1253
   1254    MZ_ASSERT(!d->m_output_flush_remaining);
   1255    d->m_output_flush_ofs = 0;
   1256    d->m_output_flush_remaining = 0;
   1257
   1258    *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
   1259    d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
   1260
   1261    if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
   1262    {
   1263        TDEFL_PUT_BITS(0x78, 8);
   1264        TDEFL_PUT_BITS(0x01, 8);
   1265    }
   1266
   1267    TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
   1268
   1269    pSaved_output_buf = d->m_pOutput_buf;
   1270    saved_bit_buf = d->m_bit_buffer;
   1271    saved_bits_in = d->m_bits_in;
   1272
   1273    if (!use_raw_block)
   1274        comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
   1275
   1276    /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
   1277    if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
   1278        ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
   1279    {
   1280        mz_uint i;
   1281        d->m_pOutput_buf = pSaved_output_buf;
   1282        d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
   1283        TDEFL_PUT_BITS(0, 2);
   1284        if (d->m_bits_in)
   1285        {
   1286            TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
   1287        }
   1288        for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
   1289        {
   1290            TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
   1291        }
   1292        for (i = 0; i < d->m_total_lz_bytes; ++i)
   1293        {
   1294            TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
   1295        }
   1296    }
   1297    /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
   1298    else if (!comp_block_succeeded)
   1299    {
   1300        d->m_pOutput_buf = pSaved_output_buf;
   1301        d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
   1302        tdefl_compress_block(d, MZ_TRUE);
   1303    }
   1304
   1305    if (flush)
   1306    {
   1307        if (flush == TDEFL_FINISH)
   1308        {
   1309            if (d->m_bits_in)
   1310            {
   1311                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
   1312            }
   1313            if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
   1314            {
   1315                mz_uint i, a = d->m_adler32;
   1316                for (i = 0; i < 4; i++)
   1317                {
   1318                    TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
   1319                    a <<= 8;
   1320                }
   1321            }
   1322        }
   1323        else
   1324        {
   1325            mz_uint i, z = 0;
   1326            TDEFL_PUT_BITS(0, 3);
   1327            if (d->m_bits_in)
   1328            {
   1329                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
   1330            }
   1331            for (i = 2; i; --i, z ^= 0xFFFF)
   1332            {
   1333                TDEFL_PUT_BITS(z & 0xFFFF, 16);
   1334            }
   1335        }
   1336    }
   1337
   1338    MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
   1339
   1340    memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
   1341    memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
   1342
   1343    d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
   1344    d->m_pLZ_flags = d->m_lz_code_buf;
   1345    d->m_num_flags_left = 8;
   1346    d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
   1347    d->m_total_lz_bytes = 0;
   1348    d->m_block_index++;
   1349
   1350    if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
   1351    {
   1352        if (d->m_pPut_buf_func)
   1353        {
   1354            *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
   1355            if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
   1356                return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
   1357        }
   1358        else if (pOutput_buf_start == d->m_output_buf)
   1359        {
   1360            int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
   1361            memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
   1362            d->m_out_buf_ofs += bytes_to_copy;
   1363            if ((n -= bytes_to_copy) != 0)
   1364            {
   1365                d->m_output_flush_ofs = bytes_to_copy;
   1366                d->m_output_flush_remaining = n;
   1367            }
   1368        }
   1369        else
   1370        {
   1371            d->m_out_buf_ofs += n;
   1372        }
   1373    }
   1374
   1375    return d->m_output_flush_remaining;
   1376}
   1377
   1378#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
   1379#ifdef MINIZ_UNALIGNED_USE_MEMCPY
   1380static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)
   1381{
   1382	mz_uint16 ret;
   1383	memcpy(&ret, p, sizeof(mz_uint16));
   1384	return ret;
   1385}
   1386static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)
   1387{
   1388	mz_uint16 ret;
   1389	memcpy(&ret, p, sizeof(mz_uint16));
   1390	return ret;
   1391}
   1392#else
   1393#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
   1394#define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
   1395#endif
   1396static 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)
   1397{
   1398    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
   1399    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
   1400    const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
   1401    mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
   1402    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
   1403    if (max_match_len <= match_len)
   1404        return;
   1405    for (;;)
   1406    {
   1407        for (;;)
   1408        {
   1409            if (--num_probes_left == 0)
   1410                return;
   1411#define TDEFL_PROBE                                                                             \
   1412    next_probe_pos = d->m_next[probe_pos];                                                      \
   1413    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
   1414        return;                                                                                 \
   1415    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                       \
   1416    if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01)                \
   1417        break;
   1418            TDEFL_PROBE;
   1419            TDEFL_PROBE;
   1420            TDEFL_PROBE;
   1421        }
   1422        if (!dist)
   1423            break;
   1424        q = (const mz_uint16 *)(d->m_dict + probe_pos);
   1425        if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
   1426            continue;
   1427        p = s;
   1428        probe_len = 32;
   1429        do
   1430        {
   1431        } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
   1432                 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
   1433        if (!probe_len)
   1434        {
   1435            *pMatch_dist = dist;
   1436            *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
   1437            break;
   1438        }
   1439        else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
   1440        {
   1441            *pMatch_dist = dist;
   1442            if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
   1443                break;
   1444            c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
   1445        }
   1446    }
   1447}
   1448#else
   1449static 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)
   1450{
   1451    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
   1452    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
   1453    const mz_uint8 *s = d->m_dict + pos, *p, *q;
   1454    mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
   1455    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
   1456    if (max_match_len <= match_len)
   1457        return;
   1458    for (;;)
   1459    {
   1460        for (;;)
   1461        {
   1462            if (--num_probes_left == 0)
   1463                return;
   1464#define TDEFL_PROBE                                                                               \
   1465    next_probe_pos = d->m_next[probe_pos];                                                        \
   1466    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))   \
   1467        return;                                                                                   \
   1468    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                         \
   1469    if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
   1470        break;
   1471            TDEFL_PROBE;
   1472            TDEFL_PROBE;
   1473            TDEFL_PROBE;
   1474        }
   1475        if (!dist)
   1476            break;
   1477        p = s;
   1478        q = d->m_dict + probe_pos;
   1479        for (probe_len = 0; probe_len < max_match_len; probe_len++)
   1480            if (*p++ != *q++)
   1481                break;
   1482        if (probe_len > match_len)
   1483        {
   1484            *pMatch_dist = dist;
   1485            if ((*pMatch_len = match_len = probe_len) == max_match_len)
   1486                return;
   1487            c0 = d->m_dict[pos + match_len];
   1488            c1 = d->m_dict[pos + match_len - 1];
   1489        }
   1490    }
   1491}
   1492#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
   1493
   1494#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
   1495#ifdef MINIZ_UNALIGNED_USE_MEMCPY
   1496static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p)
   1497{
   1498	mz_uint32 ret;
   1499	memcpy(&ret, p, sizeof(mz_uint32));
   1500	return ret;
   1501}
   1502#else
   1503#define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
   1504#endif
   1505static mz_bool tdefl_compress_fast(tdefl_compressor *d)
   1506{
   1507    /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
   1508    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;
   1509    mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
   1510    mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
   1511
   1512    while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
   1513    {
   1514        const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
   1515        mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
   1516        mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
   1517        d->m_src_buf_left -= num_bytes_to_process;
   1518        lookahead_size += num_bytes_to_process;
   1519
   1520        while (num_bytes_to_process)
   1521        {
   1522            mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
   1523            memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
   1524            if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
   1525                memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
   1526            d->m_pSrc += n;
   1527            dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
   1528            num_bytes_to_process -= n;
   1529        }
   1530
   1531        dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
   1532        if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
   1533            break;
   1534
   1535        while (lookahead_size >= 4)
   1536        {
   1537            mz_uint cur_match_dist, cur_match_len = 1;
   1538            mz_uint8 *pCur_dict = d->m_dict + cur_pos;
   1539            mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
   1540            mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
   1541            mz_uint probe_pos = d->m_hash[hash];
   1542            d->m_hash[hash] = (mz_uint16)lookahead_pos;
   1543
   1544            if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
   1545            {
   1546                const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
   1547                const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
   1548                mz_uint32 probe_len = 32;
   1549                do
   1550                {
   1551                } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
   1552                         (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
   1553                cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
   1554                if (!probe_len)
   1555                    cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
   1556
   1557                if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
   1558                {
   1559                    cur_match_len = 1;
   1560                    *pLZ_code_buf++ = (mz_uint8)first_trigram;
   1561                    *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
   1562                    d->m_huff_count[0][(mz_uint8)first_trigram]++;
   1563                }
   1564                else
   1565                {
   1566                    mz_uint32 s0, s1;
   1567                    cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
   1568
   1569                    MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
   1570
   1571                    cur_match_dist--;
   1572
   1573                    pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
   1574#ifdef MINIZ_UNALIGNED_USE_MEMCPY
   1575					memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
   1576#else
   1577                    *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
   1578#endif
   1579                    pLZ_code_buf += 3;
   1580                    *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
   1581
   1582                    s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
   1583                    s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
   1584                    d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
   1585
   1586                    d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
   1587                }
   1588            }
   1589            else
   1590            {
   1591                *pLZ_code_buf++ = (mz_uint8)first_trigram;
   1592                *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
   1593                d->m_huff_count[0][(mz_uint8)first_trigram]++;
   1594            }
   1595
   1596            if (--num_flags_left == 0)
   1597            {
   1598                num_flags_left = 8;
   1599                pLZ_flags = pLZ_code_buf++;
   1600            }
   1601
   1602            total_lz_bytes += cur_match_len;
   1603            lookahead_pos += cur_match_len;
   1604            dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
   1605            cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
   1606            MZ_ASSERT(lookahead_size >= cur_match_len);
   1607            lookahead_size -= cur_match_len;
   1608
   1609            if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
   1610            {
   1611                int n;
   1612                d->m_lookahead_pos = lookahead_pos;
   1613                d->m_lookahead_size = lookahead_size;
   1614                d->m_dict_size = dict_size;
   1615                d->m_total_lz_bytes = total_lz_bytes;
   1616                d->m_pLZ_code_buf = pLZ_code_buf;
   1617                d->m_pLZ_flags = pLZ_flags;
   1618                d->m_num_flags_left = num_flags_left;
   1619                if ((n = tdefl_flush_block(d, 0)) != 0)
   1620                    return (n < 0) ? MZ_FALSE : MZ_TRUE;
   1621                total_lz_bytes = d->m_total_lz_bytes;
   1622                pLZ_code_buf = d->m_pLZ_code_buf;
   1623                pLZ_flags = d->m_pLZ_flags;
   1624                num_flags_left = d->m_num_flags_left;
   1625            }
   1626        }
   1627
   1628        while (lookahead_size)
   1629        {
   1630            mz_uint8 lit = d->m_dict[cur_pos];
   1631
   1632            total_lz_bytes++;
   1633            *pLZ_code_buf++ = lit;
   1634            *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
   1635            if (--num_flags_left == 0)
   1636            {
   1637                num_flags_left = 8;
   1638                pLZ_flags = pLZ_code_buf++;
   1639            }
   1640
   1641            d->m_huff_count[0][lit]++;
   1642
   1643            lookahead_pos++;
   1644            dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
   1645            cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
   1646            lookahead_size--;
   1647
   1648            if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
   1649            {
   1650                int n;
   1651                d->m_lookahead_pos = lookahead_pos;
   1652                d->m_lookahead_size = lookahead_size;
   1653                d->m_dict_size = dict_size;
   1654                d->m_total_lz_bytes = total_lz_bytes;
   1655                d->m_pLZ_code_buf = pLZ_code_buf;
   1656                d->m_pLZ_flags = pLZ_flags;
   1657                d->m_num_flags_left = num_flags_left;
   1658                if ((n = tdefl_flush_block(d, 0)) != 0)
   1659                    return (n < 0) ? MZ_FALSE : MZ_TRUE;
   1660                total_lz_bytes = d->m_total_lz_bytes;
   1661                pLZ_code_buf = d->m_pLZ_code_buf;
   1662                pLZ_flags = d->m_pLZ_flags;
   1663                num_flags_left = d->m_num_flags_left;
   1664            }
   1665        }
   1666    }
   1667
   1668    d->m_lookahead_pos = lookahead_pos;
   1669    d->m_lookahead_size = lookahead_size;
   1670    d->m_dict_size = dict_size;
   1671    d->m_total_lz_bytes = total_lz_bytes;
   1672    d->m_pLZ_code_buf = pLZ_code_buf;
   1673    d->m_pLZ_flags = pLZ_flags;
   1674    d->m_num_flags_left = num_flags_left;
   1675    return MZ_TRUE;
   1676}
   1677#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
   1678
   1679static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
   1680{
   1681    d->m_total_lz_bytes++;
   1682    *d->m_pLZ_code_buf++ = lit;
   1683    *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
   1684    if (--d->m_num_flags_left == 0)
   1685    {
   1686        d->m_num_flags_left = 8;
   1687        d->m_pLZ_flags = d->m_pLZ_code_buf++;
   1688    }
   1689    d->m_huff_count[0][lit]++;
   1690}
   1691
   1692static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
   1693{
   1694    mz_uint32 s0, s1;
   1695
   1696    MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
   1697
   1698    d->m_total_lz_bytes += match_len;
   1699
   1700    d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
   1701
   1702    match_dist -= 1;
   1703    d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
   1704    d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
   1705    d->m_pLZ_code_buf += 3;
   1706
   1707    *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
   1708    if (--d->m_num_flags_left == 0)
   1709    {
   1710        d->m_num_flags_left = 8;
   1711        d->m_pLZ_flags = d->m_pLZ_code_buf++;
   1712    }
   1713
   1714    s0 = s_tdefl_small_dist_sym[match_dist & 511];
   1715    s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
   1716    d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
   1717    d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
   1718}
   1719
   1720static mz_bool tdefl_compress_normal(tdefl_compressor *d)
   1721{
   1722    const mz_uint8 *pSrc = d->m_pSrc;
   1723    size_t src_buf_left = d->m_src_buf_left;
   1724    tdefl_flush flush = d->m_flush;
   1725
   1726    while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
   1727    {
   1728        mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
   1729        /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
   1730        if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
   1731        {
   1732            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;
   1733            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];
   1734            mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
   1735            const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
   1736            src_buf_left -= num_bytes_to_process;
   1737            d->m_lookahead_size += num_bytes_to_process;
   1738            while (pSrc != pSrc_end)
   1739            {
   1740                mz_uint8 c = *pSrc++;
   1741                d->m_dict[dst_pos] = c;
   1742                if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
   1743                    d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
   1744                hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
   1745                d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
   1746                d->m_hash[hash] = (mz_uint16)(ins_pos);
   1747                dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
   1748                ins_pos++;
   1749            }
   1750        }
   1751        else
   1752        {
   1753            while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
   1754            {
   1755                mz_uint8 c = *pSrc++;
   1756                mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
   1757                src_buf_left--;
   1758                d->m_dict[dst_pos] = c;
   1759                if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
   1760                    d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
   1761                if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
   1762                {
   1763                    mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
   1764                    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);
   1765                    d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
   1766                    d->m_hash[hash] = (mz_uint16)(ins_pos);
   1767                }
   1768            }
   1769        }
   1770        d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
   1771        if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
   1772            break;
   1773
   1774        /* Simple lazy/greedy parsing state machine. */
   1775        len_to_move = 1;
   1776        cur_match_dist = 0;
   1777        cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
   1778        cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
   1779        if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
   1780        {
   1781            if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
   1782            {
   1783                mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
   1784                cur_match_len = 0;
   1785                while (cur_match_len < d->m_lookahead_size)
   1786                {
   1787                    if (d->m_dict[cur_pos + cur_match_len] != c)
   1788                        break;
   1789                    cur_match_len++;
   1790                }
   1791                if (cur_match_len < TDEFL_MIN_MATCH_LEN)
   1792                    cur_match_len = 0;
   1793                else
   1794                    cur_match_dist = 1;
   1795            }
   1796        }
   1797        else
   1798        {
   1799            tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
   1800        }
   1801        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)))
   1802        {
   1803            cur_match_dist = cur_match_len = 0;
   1804        }
   1805        if (d->m_saved_match_len)
   1806        {
   1807            if (cur_match_len > d->m_saved_match_len)
   1808            {
   1809                tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
   1810                if (cur_match_len >= 128)
   1811                {
   1812                    tdefl_record_match(d, cur_match_len, cur_match_dist);
   1813                    d->m_saved_match_len = 0;
   1814                    len_to_move = cur_match_len;
   1815                }
   1816                else
   1817                {
   1818                    d->m_saved_lit = d->m_dict[cur_pos];
   1819                    d->m_saved_match_dist = cur_match_dist;
   1820                    d->m_saved_match_len = cur_match_len;
   1821                }
   1822            }
   1823            else
   1824            {
   1825                tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
   1826                len_to_move = d->m_saved_match_len - 1;
   1827                d->m_saved_match_len = 0;
   1828            }
   1829        }
   1830        else if (!cur_match_dist)
   1831            tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
   1832        else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
   1833        {
   1834            tdefl_record_match(d, cur_match_len, cur_match_dist);
   1835            len_to_move = cur_match_len;
   1836        }
   1837        else
   1838        {
   1839            d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
   1840            d->m_saved_match_dist = cur_match_dist;
   1841            d->m_saved_match_len = cur_match_len;
   1842        }
   1843        /* Move the lookahead forward by len_to_move bytes. */
   1844        d->m_lookahead_pos += len_to_move;
   1845        MZ_ASSERT(d->m_lookahead_size >= len_to_move);
   1846        d->m_lookahead_size -= len_to_move;
   1847        d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
   1848        /* Check if it's time to flush the current LZ codes to the internal output buffer. */
   1849        if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
   1850            ((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))))
   1851        {
   1852            int n;
   1853            d->m_pSrc = pSrc;
   1854            d->m_src_buf_left = src_buf_left;
   1855            if ((n = tdefl_flush_block(d, 0)) != 0)
   1856                return (n < 0) ? MZ_FALSE : MZ_TRUE;
   1857        }
   1858    }
   1859
   1860    d->m_pSrc = pSrc;
   1861    d->m_src_buf_left = src_buf_left;
   1862    return MZ_TRUE;
   1863}
   1864
   1865static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
   1866{
   1867    if (d->m_pIn_buf_size)
   1868    {
   1869        *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
   1870    }
   1871
   1872    if (d->m_pOut_buf_size)
   1873    {
   1874        size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
   1875        memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
   1876        d->m_output_flush_ofs += (mz_uint)n;
   1877        d->m_output_flush_remaining -= (mz_uint)n;
   1878        d->m_out_buf_ofs += n;
   1879
   1880        *d->m_pOut_buf_size = d->m_out_buf_ofs;
   1881    }
   1882
   1883    return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
   1884}
   1885
   1886tdefl_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)
   1887{
   1888    if (!d)
   1889    {
   1890        if (pIn_buf_size)
   1891            *pIn_buf_size = 0;
   1892        if (pOut_buf_size)
   1893            *pOut_buf_size = 0;
   1894        return TDEFL_STATUS_BAD_PARAM;
   1895    }
   1896
   1897    d->m_pIn_buf = pIn_buf;
   1898    d->m_pIn_buf_size = pIn_buf_size;
   1899    d->m_pOut_buf = pOut_buf;
   1900    d->m_pOut_buf_size = pOut_buf_size;
   1901    d->m_pSrc = (const mz_uint8 *)(pIn_buf);
   1902    d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
   1903    d->m_out_buf_ofs = 0;
   1904    d->m_flush = flush;
   1905
   1906    if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
   1907        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
   1908    {
   1909        if (pIn_buf_size)
   1910            *pIn_buf_size = 0;
   1911        if (pOut_buf_size)
   1912            *pOut_buf_size = 0;
   1913        return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
   1914    }
   1915    d->m_wants_to_finish |= (flush == TDEFL_FINISH);
   1916
   1917    if ((d->m_output_flush_remaining) || (d->m_finished))
   1918        return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
   1919
   1920#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
   1921    if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
   1922        ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
   1923        ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
   1924    {
   1925        if (!tdefl_compress_fast(d))
   1926            return d->m_prev_return_status;
   1927    }
   1928    else
   1929#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
   1930    {
   1931        if (!tdefl_compress_normal(d))
   1932            return d->m_prev_return_status;
   1933    }
   1934
   1935    if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
   1936        d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
   1937
   1938    if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
   1939    {
   1940        if (tdefl_flush_block(d, flush) < 0)
   1941            return d->m_prev_return_status;
   1942        d->m_finished = (flush == TDEFL_FINISH);
   1943        if (flush == TDEFL_FULL_FLUSH)
   1944        {
   1945            MZ_CLEAR_OBJ(d->m_hash);
   1946            MZ_CLEAR_OBJ(d->m_next);
   1947            d->m_dict_size = 0;
   1948        }
   1949    }
   1950
   1951    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
   1952}
   1953
   1954tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
   1955{
   1956    MZ_ASSERT(d->m_pPut_buf_func);
   1957    return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
   1958}
   1959
   1960tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
   1961{
   1962    d->m_pPut_buf_func = pPut_buf_func;
   1963    d->m_pPut_buf_user = pPut_buf_user;
   1964    d->m_flags = (mz_uint)(flags);
   1965    d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
   1966    d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
   1967    d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
   1968    if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
   1969        MZ_CLEAR_OBJ(d->m_hash);
   1970    d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
   1971    d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
   1972    d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
   1973    d->m_pLZ_flags = d->m_lz_code_buf;
   1974    *d->m_pLZ_flags = 0;
   1975    d->m_num_flags_left = 8;
   1976    d->m_pOutput_buf = d->m_output_buf;
   1977    d->m_pOutput_buf_end = d->m_output_buf;
   1978    d->m_prev_return_status = TDEFL_STATUS_OKAY;
   1979    d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
   1980    d->m_adler32 = 1;
   1981    d->m_pIn_buf = NULL;
   1982    d->m_pOut_buf = NULL;
   1983    d->m_pIn_buf_size = NULL;
   1984    d->m_pOut_buf_size = NULL;
   1985    d->m_flush = TDEFL_NO_FLUSH;
   1986    d->m_pSrc = NULL;
   1987    d->m_src_buf_left = 0;
   1988    d->m_out_buf_ofs = 0;
   1989    if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
   1990        MZ_CLEAR_OBJ(d->m_dict);
   1991    memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
   1992    memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
   1993    return TDEFL_STATUS_OKAY;
   1994}
   1995
   1996tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
   1997{
   1998    return d->m_prev_return_status;
   1999}
   2000
   2001mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
   2002{
   2003    return d->m_adler32;
   2004}
   2005
   2006mz_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)
   2007{
   2008    tdefl_compressor *pComp;
   2009    mz_bool succeeded;
   2010    if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
   2011        return MZ_FALSE;
   2012    pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
   2013    if (!pComp)
   2014        return MZ_FALSE;
   2015    succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
   2016    succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
   2017    MZ_FREE(pComp);
   2018    return succeeded;
   2019}
   2020
   2021typedef struct
   2022{
   2023    size_t m_size, m_capacity;
   2024    mz_uint8 *m_pBuf;
   2025    mz_bool m_expandable;
   2026} tdefl_output_buffer;
   2027
   2028static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
   2029{
   2030    tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
   2031    size_t new_size = p->m_size + len;
   2032    if (new_size > p->m_capacity)
   2033    {
   2034        size_t new_capacity = p->m_capacity;
   2035        mz_uint8 *pNew_buf;
   2036        if (!p->m_expandable)
   2037            return MZ_FALSE;
   2038        do
   2039        {
   2040            new_capacity = MZ_MAX(128U, new_capacity << 1U);
   2041        } while (new_size > new_capacity);
   2042        pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
   2043        if (!pNew_buf)
   2044            return MZ_FALSE;
   2045        p->m_pBuf = pNew_buf;
   2046        p->m_capacity = new_capacity;
   2047    }
   2048    memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
   2049    p->m_size = new_size;
   2050    return MZ_TRUE;
   2051}
   2052
   2053void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
   2054{
   2055    tdefl_output_buffer out_buf;
   2056    MZ_CLEAR_OBJ(out_buf);
   2057    if (!pOut_len)
   2058        return MZ_FALSE;
   2059    else
   2060        *pOut_len = 0;
   2061    out_buf.m_expandable = MZ_TRUE;
   2062    if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
   2063        return NULL;
   2064    *pOut_len = out_buf.m_size;
   2065    return out_buf.m_pBuf;
   2066}
   2067
   2068size_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)
   2069{
   2070    tdefl_output_buffer out_buf;
   2071    MZ_CLEAR_OBJ(out_buf);
   2072    if (!pOut_buf)
   2073        return 0;
   2074    out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
   2075    out_buf.m_capacity = out_buf_len;
   2076    if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
   2077        return 0;
   2078    return out_buf.m_size;
   2079}
   2080
   2081static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
   2082
   2083/* 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). */
   2084mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
   2085{
   2086    mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
   2087    if (window_bits > 0)
   2088        comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
   2089
   2090    if (!level)
   2091        comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
   2092    else if (strategy == MZ_FILTERED)
   2093        comp_flags |= TDEFL_FILTER_MATCHES;
   2094    else if (strategy == MZ_HUFFMAN_ONLY)
   2095        comp_flags &= ~TDEFL_MAX_PROBES_MASK;
   2096    else if (strategy == MZ_FIXED)
   2097        comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
   2098    else if (strategy == MZ_RLE)
   2099        comp_flags |= TDEFL_RLE_MATCHES;
   2100
   2101    return comp_flags;
   2102}
   2103
   2104#ifdef _MSC_VER
   2105#pragma warning(push)
   2106#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
   2107#endif
   2108
   2109/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
   2110 http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
   2111 This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
   2112void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
   2113{
   2114    /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
   2115    static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
   2116    tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
   2117    tdefl_output_buffer out_buf;
   2118    int i, bpl = w * num_chans, y, z;
   2119    mz_uint32 c;
   2120    *pLen_out = 0;
   2121    if (!pComp)
   2122        return NULL;
   2123    MZ_CLEAR_OBJ(out_buf);
   2124    out_buf.m_expandable = MZ_TRUE;
   2125    out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
   2126    if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
   2127    {
   2128        MZ_FREE(pComp);
   2129        return NULL;
   2130    }
   2131    /* write dummy header */
   2132    for (z = 41; z; --z)
   2133        tdefl_output_buffer_putter(&z, 1, &out_buf);
   2134    /* compress image data */
   2135    tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
   2136    for (y = 0; y < h; ++y)
   2137    {
   2138        tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
   2139        tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
   2140    }
   2141    if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
   2142    {
   2143        MZ_FREE(pComp);
   2144        MZ_FREE(out_buf.m_pBuf);
   2145        return NULL;
   2146    }
   2147    /* write real header */
   2148    *pLen_out = out_buf.m_size - 41;
   2149    {
   2150        static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
   2151        mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
   2152                                0x0a, 0x1a, 0x0a, 0x00, 0x00,
   2153                                0x00, 0x0d, 0x49, 0x48, 0x44,
   2154                                0x52, 0x00, 0x00, 0x00, 0x00,
   2155                                0x00, 0x00, 0x00, 0x00, 0x08,
   2156                                0x00, 0x00, 0x00, 0x00, 0x00,
   2157                                0x00, 0x00, 0x00, 0x00, 0x00,
   2158                                0x00, 0x00, 0x49, 0x44, 0x41,
   2159                                0x54 };
   2160        pnghdr[18] = (mz_uint8)(w >> 8);
   2161        pnghdr[19] = (mz_uint8)w;
   2162        pnghdr[22] = (mz_uint8)(h >> 8);
   2163        pnghdr[23] = (mz_uint8)h;
   2164        pnghdr[25] = chans[num_chans];
   2165        pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
   2166        pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
   2167        pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
   2168        pnghdr[36] = (mz_uint8)*pLen_out;
   2169        c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
   2170        for (i = 0; i < 4; ++i, c <<= 8)
   2171            ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
   2172        memcpy(out_buf.m_pBuf, pnghdr, 41);
   2173    }
   2174    /* write footer (IDAT CRC-32, followed by IEND chunk) */
   2175    if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
   2176    {
   2177        *pLen_out = 0;
   2178        MZ_FREE(pComp);
   2179        MZ_FREE(out_buf.m_pBuf);
   2180        return NULL;
   2181    }
   2182    c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
   2183    for (i = 0; i < 4; ++i, c <<= 8)
   2184        (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
   2185    /* compute final size of file, grab compressed data buffer and return */
   2186    *pLen_out += 57;
   2187    MZ_FREE(pComp);
   2188    return out_buf.m_pBuf;
   2189}
   2190void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
   2191{
   2192    /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */
   2193    return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
   2194}
   2195
   2196#ifndef MINIZ_NO_MALLOC
   2197/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
   2198/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
   2199/* structure size and allocation mechanism. */
   2200tdefl_compressor *tdefl_compressor_alloc()
   2201{
   2202    return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
   2203}
   2204
   2205void tdefl_compressor_free(tdefl_compressor *pComp)
   2206{
   2207    MZ_FREE(pComp);
   2208}
   2209#endif
   2210
   2211#ifdef _MSC_VER
   2212#pragma warning(pop)
   2213#endif
   2214
   2215#ifdef __cplusplus
   2216}
   2217#endif
   2218 /**************************************************************************
   2219 *
   2220 * Copyright 2013-2014 RAD Game Tools and Valve Software
   2221 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
   2222 * All Rights Reserved.
   2223 *
   2224 * Permission is hereby granted, free of charge, to any person obtaining a copy
   2225 * of this software and associated documentation files (the "Software"), to deal
   2226 * in the Software without restriction, including without limitation the rights
   2227 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   2228 * copies of the Software, and to permit persons to whom the Software is
   2229 * furnished to do so, subject to the following conditions:
   2230 *
   2231 * The above copyright notice and this permission notice shall be included in
   2232 * all copies or substantial portions of the Software.
   2233 *
   2234 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   2235 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   2236 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   2237 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   2238 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   2239 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   2240 * THE SOFTWARE.
   2241 *
   2242 **************************************************************************/
   2243
   2244
   2245
   2246#ifdef __cplusplus
   2247extern "C" {
   2248#endif
   2249
   2250/* ------------------- Low-level Decompression (completely independent from all compression API's) */
   2251
   2252#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
   2253#define TINFL_MEMSET(p, c, l) memset(p, c, l)
   2254
   2255#define TINFL_CR_BEGIN  \
   2256    switch (r->m_state) \
   2257    {                   \
   2258        case 0:
   2259#define TINFL_CR_RETURN(state_index, result) \
   2260    do                                       \
   2261    {                                        \
   2262        status = result;                     \
   2263        r->m_state = state_index;            \
   2264        goto common_exit;                    \
   2265        case state_index:;                   \
   2266    }                                        \
   2267    MZ_MACRO_END
   2268#define TINFL_CR_RETURN_FOREVER(state_index, result) \
   2269    do                                               \
   2270    {                                                \
   2271        for (;;)                                     \
   2272        {                                            \
   2273            TINFL_CR_RETURN(state_index, result);    \
   2274        }                                            \
   2275    }                                                \
   2276    MZ_MACRO_END
   2277#define TINFL_CR_FINISH }
   2278
   2279#define TINFL_GET_BYTE(state_index, c)                                                                                                                           \
   2280    do                                                                                                                                                           \
   2281    {                                                                                                                                                            \
   2282        while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \
   2283        {                                                                                                                                                        \
   2284            TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
   2285        }                                                                                                                                                        \
   2286        c = *pIn_buf_cur++;                                                                                                                                      \
   2287    }                                                                                                                                                            \
   2288    MZ_MACRO_END
   2289
   2290#define TINFL_NEED_BITS(state_index, n)                \
   2291    do                                                 \
   2292    {                                                  \
   2293        mz_uint c;                                     \
   2294        TINFL_GET_BYTE(state_index, c);                \
   2295        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
   2296        num_bits += 8;                                 \
   2297    } while (num_bits < (mz_uint)(n))
   2298#define TINFL_SKIP_BITS(state_index, n)      \
   2299    do                                       \
   2300    {                                        \
   2301        if (num_bits < (mz_uint)(n))         \
   2302        {                                    \
   2303            TINFL_NEED_BITS(state_index, n); \
   2304        }                                    \
   2305        bit_buf >>= (n);                     \
   2306        num_bits -= (n);                     \
   2307    }                                        \
   2308    MZ_MACRO_END
   2309#define TINFL_GET_BITS(state_index, b, n)    \
   2310    do                                       \
   2311    {                                        \
   2312        if (num_bits < (mz_uint)(n))         \
   2313        {                                    \
   2314            TINFL_NEED_BITS(state_index, n); \
   2315        }                                    \
   2316        b = bit_buf & ((1 << (n)) - 1);      \
   2317        bit_buf >>= (n);                     \
   2318        num_bits -= (n);                     \
   2319    }                                        \
   2320    MZ_MACRO_END
   2321
   2322/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
   2323/* 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 */
   2324/* 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 */
   2325/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
   2326#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
   2327    do                                                                         \
   2328    {                                                                          \
   2329        temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];     \
   2330        if (temp >= 0)                                                         \
   2331        {                                                                      \
   2332            code_len = temp >> 9;                                              \
   2333            if ((code_len) && (num_bits >= code_len))                          \
   2334                break;                                                         \
   2335        }                                                                      \
   2336        else if (num_bits > TINFL_FAST_LOOKUP_BITS)                            \
   2337        {                                                                      \
   2338            code_len = TINFL_FAST_LOOKUP_BITS;                                 \
   2339            do                                                                 \
   2340            {                                                                  \
   2341                temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
   2342            } while ((temp < 0) && (num_bits >= (code_len + 1)));              \
   2343            if (temp >= 0)                                                     \
   2344                break;                                                         \
   2345        }                                                                      \
   2346        TINFL_GET_BYTE(state_index, c);                                        \
   2347        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                         \
   2348        num_bits += 8;                                                         \
   2349    } while (num_bits < 15);
   2350
   2351/* 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 */
   2352/* 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 */
   2353/* 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. */
   2354/* The slow path is only executed at the very end of the input buffer. */
   2355/* 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 */
   2356/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
   2357#define TINFL_HUFF_DECODE(state_index, sym, pHuff)                                                                                  \
   2358    do                                                                                                                              \
   2359    {                                                                                                                               \
   2360        int temp;                                                                                                                   \
   2361        mz_uint code_len, c;                                                                                                        \
   2362        if (num_bits < 15)                                                                                                          \
   2363        {                                                                                                                           \
   2364            if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
   2365            {                                                                                                                       \
   2366                TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \
   2367            }                                                                                                                       \
   2368            else                                                                                                                    \
   2369            {                                                                                                                       \
   2370                bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
   2371                pIn_buf_cur += 2;                                                                                                   \
   2372                num_bits += 16;                                                                                                     \
   2373            }                                                                                                                       \
   2374        }                                                                                                                           \
   2375        if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \
   2376            code_len = temp >> 9, temp &= 511;                                                                                      \
   2377        else                                                                                                                        \
   2378        {                                                                                                                           \
   2379            code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
   2380            do                                                                                                                      \
   2381            {                                                                                                                       \
   2382                temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \
   2383            } while (temp < 0);                                                                                                     \
   2384        }                                                                                                                           \
   2385        sym = temp;                                                                                                                 \
   2386        bit_buf >>= code_len;                                                                                                       \
   2387        num_bits -= code_len;                                                                                                       \
   2388    }                                                                                                                               \
   2389    MZ_MACRO_END
   2390
   2391tinfl_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)
   2392{
   2393    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 };
   2394    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 };
   2395    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 };
   2396    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 };
   2397    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 };
   2398    static const int s_min_table_sizes[3] = { 257, 1, 4 };
   2399
   2400    tinfl_status status = TINFL_STATUS_FAILED;
   2401    mz_uint32 num_bits, dist, counter, num_extra;
   2402    tinfl_bit_buf_t bit_buf;
   2403    const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
   2404    mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
   2405    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;
   2406
   2407    /* 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). */
   2408    if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
   2409    {
   2410        *pIn_buf_size = *pOut_buf_size = 0;
   2411        return TINFL_STATUS_BAD_PARAM;
   2412    }
   2413
   2414    num_bits = r->m_num_bits;
   2415    bit_buf = r->m_bit_buf;
   2416    dist = r->m_dist;
   2417    counter = r->m_counter;
   2418    num_extra = r->m_num_extra;
   2419    dist_from_out_buf_start = r->m_dist_from_out_buf_start;
   2420    TINFL_CR_BEGIN
   2421
   2422    bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
   2423    r->m_z_adler32 = r->m_check_adler32 = 1;
   2424    if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
   2425    {
   2426        TINFL_GET_BYTE(1, r->m_zhdr0);
   2427        TINFL_GET_BYTE(2, r->m_zhdr1);
   2428        counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
   2429        if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
   2430            counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
   2431        if (counter)
   2432        {
   2433            TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
   2434        }
   2435    }
   2436
   2437    do
   2438    {
   2439        TINFL_GET_BITS(3, r->m_final, 3);
   2440        r->m_type = r->m_final >> 1;
   2441        if (r->m_type == 0)
   2442        {
   2443            TINFL_SKIP_BITS(5, num_bits & 7);
   2444            for (counter = 0; counter < 4; ++counter)
   2445            {
   2446                if (num_bits)
   2447                    TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
   2448                else
   2449                    TINFL_GET_BYTE(7, r->m_raw_header[counter]);
   2450            }
   2451            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))))
   2452            {
   2453                TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
   2454            }
   2455            while ((counter) && (num_bits))
   2456            {
   2457                TINFL_GET_BITS(51, dist, 8);
   2458                while (pOut_buf_cur >= pOut_buf_end)
   2459                {
   2460                    TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
   2461                }
   2462                *pOut_buf_cur++ = (mz_uint8)dist;
   2463                counter--;
   2464            }
   2465            while (counter)
   2466            {
   2467                size_t n;
   2468                while (pOut_buf_cur >= pOut_buf_end)
   2469                {
   2470                    TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
   2471                }
   2472                while (pIn_buf_cur >= pIn_buf_end)
   2473                {
   2474                    TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
   2475                }
   2476                n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
   2477                TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
   2478                pIn_buf_cur += n;
   2479                pOut_buf_cur += n;
   2480                counter -= (mz_uint)n;
   2481            }
   2482        }
   2483        else if (r->m_type == 3)
   2484        {
   2485            TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
   2486        }
   2487        else
   2488        {
   2489            if (r->m_type == 1)
   2490            {
   2491                mz_uint8 *p = r->m_tables[0].m_code_size;
   2492                mz_uint i;
   2493                r->m_table_sizes[0] = 288;
   2494                r->m_table_sizes[1] = 32;
   2495                TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
   2496                for (i = 0; i <= 143; ++i)
   2497                    *p++ = 8;
   2498                for (; i <= 255; ++i)
   2499                    *p++ = 9;
   2500                for (; i <= 279; ++i)
   2501                    *p++ = 7;
   2502                for (; i <= 287; ++i)
   2503                    *p++ = 8;
   2504            }
   2505            else
   2506            {
   2507                for (counter = 0; counter < 3; counter++)
   2508                {
   2509                    TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
   2510                    r->m_table_sizes[counter] += s_min_table_sizes[counter];
   2511                }
   2512                MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
   2513                for (counter = 0; counter < r->m_table_sizes[2]; counter++)
   2514                {
   2515                    mz_uint s;
   2516                    TINFL_GET_BITS(14, s, 3);
   2517                    r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
   2518                }
   2519                r->m_table_sizes[2] = 19;
   2520            }
   2521            for (; (int)r->m_type >= 0; r->m_type--)
   2522            {
   2523                int tree_next, tree_cur;
   2524                tinfl_huff_table *pTable;
   2525                mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
   2526                pTable = &r->m_tables[r->m_type];
   2527                MZ_CLEAR_OBJ(total_syms);
   2528                MZ_CLEAR_OBJ(pTable->m_look_up);
   2529                MZ_CLEAR_OBJ(pTable->m_tree);
   2530                for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
   2531                    total_syms[pTable->m_code_size[i]]++;
   2532                used_syms = 0, total = 0;
   2533                next_code[0] = next_code[1] = 0;
   2534                for (i = 1; i <= 15; ++i)
   2535                {
   2536                    used_syms += total_syms[i];
   2537                    next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
   2538                }
   2539                if ((65536 != total) && (used_syms > 1))
   2540                {
   2541                    TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
   2542                }
   2543                for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
   2544                {
   2545                    mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
   2546                    if (!code_size)
   2547                        continue;
   2548                    cur_code = next_code[code_size]++;
   2549                    for (l = code_size; l > 0; l--, cur_code >>= 1)
   2550                        rev_code = (rev_code << 1) | (cur_code & 1);
   2551                    if (code_size <= TINFL_FAST_LOOKUP_BITS)
   2552                    {
   2553                        mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
   2554                        while (rev_code < TINFL_FAST_LOOKUP_SIZE)
   2555                        {
   2556                            pTable->m_look_up[rev_code] = k;
   2557                            rev_code += (1 << code_size);
   2558                        }
   2559                        continue;
   2560                    }
   2561                    if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
   2562                    {
   2563                        pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
   2564                        tree_cur = tree_next;
   2565                        tree_next -= 2;
   2566                    }
   2567                    rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
   2568                    for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
   2569                    {
   2570                        tree_cur -= ((rev_code >>= 1) & 1);
   2571                        if (!pTable->m_tree[-tree_cur - 1])
   2572                        {
   2573                            pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
   2574                            tree_cur = tree_next;
   2575                            tree_next -= 2;
   2576                        }
   2577                        else
   2578                            tree_cur = pTable->m_tree[-tree_cur - 1];
   2579                    }
   2580                    tree_cur -= ((rev_code >>= 1) & 1);
   2581                    pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
   2582                }
   2583                if (r->m_type == 2)
   2584                {
   2585                    for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
   2586                    {
   2587                        mz_uint s;
   2588                        TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
   2589                        if (dist < 16)
   2590                        {
   2591                            r->m_len_codes[counter++] = (mz_uint8)dist;
   2592                            continue;
   2593                        }
   2594                        if ((dist == 16) && (!counter))
   2595                        {
   2596                            TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
   2597                        }
   2598                        num_extra = "\02\03\07"[dist - 16];
   2599                        TINFL_GET_BITS(18, s, num_extra);
   2600                        s += "\03\03\013"[dist - 16];
   2601                        TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
   2602                        counter += s;
   2603                    }
   2604                    if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
   2605                    {
   2606                        TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
   2607                    }
   2608                    TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
   2609                    TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
   2610                }
   2611            }
   2612            for (;;)
   2613            {
   2614                mz_uint8 *pSrc;
   2615                for (;;)
   2616                {
   2617                    if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
   2618                    {
   2619                        TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
   2620                        if (counter >= 256)
   2621                            break;
   2622                        while (pOut_buf_cur >= pOut_buf_end)
   2623                        {
   2624                            TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
   2625                        }
   2626                        *pOut_buf_cur++ = (mz_uint8)counter;
   2627                    }
   2628                    else
   2629                    {
   2630                        int sym2;
   2631                        mz_uint code_len;
   2632#if TINFL_USE_64BIT_BITBUF
   2633                        if (num_bits < 30)
   2634                        {
   2635                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
   2636                            pIn_buf_cur += 4;
   2637                            num_bits += 32;
   2638                        }
   2639#else
   2640                        if (num_bits < 15)
   2641                        {
   2642                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
   2643                            pIn_buf_cur += 2;
   2644                            num_bits += 16;
   2645                        }
   2646#endif
   2647                        if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
   2648                            code_len = sym2 >> 9;
   2649                        else
   2650                        {
   2651                            code_len = TINFL_FAST_LOOKUP_BITS;
   2652                            do
   2653                            {
   2654                                sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
   2655                            } while (sym2 < 0);
   2656                        }
   2657                        counter = sym2;
   2658                        bit_buf >>= code_len;
   2659                        num_bits -= code_len;
   2660                        if (counter & 256)
   2661                            break;
   2662
   2663#if !TINFL_USE_64BIT_BITBUF
   2664                        if (num_bits < 15)
   2665                        {
   2666                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
   2667                            pIn_buf_cur += 2;
   2668                            num_bits += 16;
   2669                        }
   2670#endif
   2671                        if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
   2672                            code_len = sym2 >> 9;
   2673                        else
   2674                        {
   2675                            code_len = TINFL_FAST_LOOKUP_BITS;
   2676                            do
   2677                            {
   2678                                sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
   2679                            } while (sym2 < 0);
   2680                        }
   2681                        bit_buf >>= code_len;
   2682                        num_bits -= code_len;
   2683
   2684                        pOut_buf_cur[0] = (mz_uint8)counter;
   2685                        if (sym2 & 256)
   2686                        {
   2687                            pOut_buf_cur++;
   2688                            counter = sym2;
   2689                            break;
   2690                        }
   2691                        pOut_buf_cur[1] = (mz_uint8)sym2;
   2692                        pOut_buf_cur += 2;
   2693                    }
   2694                }
   2695                if ((counter &= 511) == 256)
   2696                    break;
   2697
   2698                num_extra = s_length_extra[counter - 257];
   2699                counter = s_length_base[counter - 257];
   2700                if (num_extra)
   2701                {
   2702                    mz_uint extra_bits;
   2703                    TINFL_GET_BITS(25, extra_bits, num_extra);
   2704                    counter += extra_bits;
   2705                }
   2706
   2707                TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
   2708                num_extra = s_dist_extra[dist];
   2709                dist = s_dist_base[dist];
   2710                if (num_extra)
   2711                {
   2712                    mz_uint extra_bits;
   2713                    TINFL_GET_BITS(27, extra_bits, num_extra);
   2714                    dist += extra_bits;
   2715                }
   2716
   2717                dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
   2718                if ((dist == 0 || dist > dist_from_out_buf_start || dist_from_out_buf_start == 0) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
   2719                {
   2720                    TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
   2721                }
   2722
   2723                pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
   2724
   2725                if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
   2726                {
   2727                    while (counter--)
   2728                    {
   2729                        while (pOut_buf_cur >= pOut_buf_end)
   2730                        {
   2731                            TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
   2732                        }
   2733                        *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
   2734                    }
   2735                    continue;
   2736                }
   2737#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
   2738                else if ((counter >= 9) && (counter <= dist))
   2739                {
   2740                    const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
   2741                    do
   2742                    {
   2743#ifdef MINIZ_UNALIGNED_USE_MEMCPY
   2744						memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
   2745#else
   2746                        ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
   2747                        ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
   2748#endif
   2749                        pOut_buf_cur += 8;
   2750                    } while ((pSrc += 8) < pSrc_end);
   2751                    if ((counter &= 7) < 3)
   2752                    {
   2753                        if (counter)
   2754                        {
   2755                            pOut_buf_cur[0] = pSrc[0];
   2756                            if (counter > 1)
   2757                                pOut_buf_cur[1] = pSrc[1];
   2758                            pOut_buf_cur += counter;
   2759                        }
   2760                        continue;
   2761                    }
   2762                }
   2763#endif
   2764                while(counter>2)
   2765                {
   2766                    pOut_buf_cur[0] = pSrc[0];
   2767                    pOut_buf_cur[1] = pSrc[1];
   2768                    pOut_buf_cur[2] = pSrc[2];
   2769                    pOut_buf_cur += 3;
   2770                    pSrc += 3;
   2771					counter -= 3;
   2772                }
   2773                if (counter > 0)
   2774                {
   2775                    pOut_buf_cur[0] = pSrc[0];
   2776                    if (counter > 1)
   2777                        pOut_buf_cur[1] = pSrc[1];
   2778                    pOut_buf_cur += counter;
   2779                }
   2780            }
   2781        }
   2782    } while (!(r->m_final & 1));
   2783
   2784    /* 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. */
   2785    /* 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. */
   2786    TINFL_SKIP_BITS(32, num_bits & 7);
   2787    while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
   2788    {
   2789        --pIn_buf_cur;
   2790        num_bits -= 8;
   2791    }
   2792    bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
   2793    MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */
   2794
   2795    if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
   2796    {
   2797        for (counter = 0; counter < 4; ++counter)
   2798        {
   2799            mz_uint s;
   2800            if (num_bits)
   2801                TINFL_GET_BITS(41, s, 8);
   2802            else
   2803                TINFL_GET_BYTE(42, s);
   2804            r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
   2805        }
   2806    }
   2807    TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
   2808
   2809    TINFL_CR_FINISH
   2810
   2811common_exit:
   2812    /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
   2813    /* 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. */
   2814    /* 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. */
   2815    if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
   2816    {
   2817        while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
   2818        {
   2819            --pIn_buf_cur;
   2820            num_bits -= 8;
   2821        }
   2822    }
   2823    r->m_num_bits = num_bits;
   2824    r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
   2825    r->m_dist = dist;
   2826    r->m_counter = counter;
   2827    r->m_num_extra = num_extra;
   2828    r->m_dist_from_out_buf_start = dist_from_out_buf_start;
   2829    *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
   2830    *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
   2831    if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
   2832    {
   2833        const mz_uint8 *ptr = pOut_buf_next;
   2834        size_t buf_len = *pOut_buf_size;
   2835        mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
   2836        size_t block_len = buf_len % 5552;
   2837        while (buf_len)
   2838        {
   2839            for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
   2840            {
   2841                s1 += ptr[0], s2 += s1;
   2842                s1 += ptr[1], s2 += s1;
   2843                s1 += ptr[2], s2 += s1;
   2844                s1 += ptr[3], s2 += s1;
   2845                s1 += ptr[4], s2 += s1;
   2846                s1 += ptr[5], s2 += s1;
   2847                s1 += ptr[6], s2 += s1;
   2848                s1 += ptr[7], s2 += s1;
   2849            }
   2850            for (; i < block_len; ++i)
   2851                s1 += *ptr++, s2 += s1;
   2852            s1 %= 65521U, s2 %= 65521U;
   2853            buf_len -= block_len;
   2854            block_len = 5552;
   2855        }
   2856        r->m_check_adler32 = (s2 << 16) + s1;
   2857        if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
   2858            status = TINFL_STATUS_ADLER32_MISMATCH;
   2859    }
   2860    return status;
   2861}
   2862
   2863/* Higher level helper functions. */
   2864void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
   2865{
   2866    tinfl_decompressor decomp;
   2867    void *pBuf = NULL, *pNew_buf;
   2868    size_t src_buf_ofs = 0, out_buf_capacity = 0;
   2869    *pOut_len = 0;
   2870    tinfl_init(&decomp);
   2871    for (;;)
   2872    {
   2873        size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
   2874        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,
   2875                                               (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
   2876        if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
   2877        {
   2878            MZ_FREE(pBuf);
   2879            *pOut_len = 0;
   2880            return NULL;
   2881        }
   2882        src_buf_ofs += src_buf_size;
   2883        *pOut_len += dst_buf_size;
   2884        if (status == TINFL_STATUS_DONE)
   2885            break;
   2886        new_out_buf_capacity = out_buf_capacity * 2;
   2887        if (new_out_buf_capacity < 128)
   2888            new_out_buf_capacity = 128;
   2889        pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
   2890        if (!pNew_buf)
   2891        {
   2892            MZ_FREE(pBuf);
   2893            *pOut_len = 0;
   2894            return NULL;
   2895        }
   2896        pBuf = pNew_buf;
   2897        out_buf_capacity = new_out_buf_capacity;
   2898    }
   2899    return pBuf;
   2900}
   2901
   2902size_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)
   2903{
   2904    tinfl_decompressor decomp;
   2905    tinfl_status status;
   2906    tinfl_init(&decomp);
   2907    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);
   2908    return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
   2909}
   2910
   2911int 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)
   2912{
   2913    int result = 0;
   2914    tinfl_decompressor decomp;
   2915    mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
   2916    size_t in_buf_ofs = 0, dict_ofs = 0;
   2917    if (!pDict)
   2918        return TINFL_STATUS_FAILED;
   2919    tinfl_init(&decomp);
   2920    for (;;)
   2921    {
   2922        size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
   2923        tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
   2924                                               (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
   2925        in_buf_ofs += in_buf_size;
   2926        if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
   2927            break;
   2928        if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
   2929        {
   2930            result = (status == TINFL_STATUS_DONE);
   2931            break;
   2932        }
   2933        dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
   2934    }
   2935    MZ_FREE(pDict);
   2936    *pIn_buf_size = in_buf_ofs;
   2937    return result;
   2938}
   2939
   2940#ifndef MINIZ_NO_MALLOC
   2941tinfl_decompressor *tinfl_decompressor_alloc()
   2942{
   2943    tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
   2944    if (pDecomp)
   2945        tinfl_init(pDecomp);
   2946    return pDecomp;
   2947}
   2948
   2949void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
   2950{
   2951    MZ_FREE(pDecomp);
   2952}
   2953#endif
   2954
   2955#ifdef __cplusplus
   2956}
   2957#endif
   2958 /**************************************************************************
   2959 *
   2960 * Copyright 2013-2014 RAD Game Tools and Valve Software
   2961 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
   2962 * Copyright 2016 Martin Raiber
   2963 * All Rights Reserved.
   2964 *
   2965 * Permission is hereby granted, free of charge, to any person obtaining a copy
   2966 * of this software and associated documentation files (the "Software"), to deal
   2967 * in the Software without restriction, including without limitation the rights
   2968 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   2969 * copies of the Software, and to permit persons to whom the Software is
   2970 * furnished to do so, subject to the following conditions:
   2971 *
   2972 * The above copyright notice and this permission notice shall be included in
   2973 * all copies or substantial portions of the Software.
   2974 *
   2975 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   2976 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   2977 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   2978 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   2979 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   2980 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   2981 * THE SOFTWARE.
   2982 *
   2983 **************************************************************************/
   2984
   2985
   2986#ifndef MINIZ_NO_ARCHIVE_APIS
   2987
   2988#ifdef __cplusplus
   2989extern "C" {
   2990#endif
   2991
   2992/* ------------------- .ZIP archive reading */
   2993
   2994#ifdef MINIZ_NO_STDIO
   2995#define MZ_FILE void *
   2996#else
   2997#include <sys/stat.h>
   2998
   2999#if defined(_MSC_VER) || defined(__MINGW64__)
   3000static FILE *mz_fopen(const char *pFilename, const char *pMode)
   3001{
   3002    FILE *pFile = NULL;
   3003    fopen_s(&pFile, pFilename, pMode);
   3004    return pFile;
   3005}
   3006static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
   3007{
   3008    FILE *pFile = NULL;
   3009    if (freopen_s(&pFile, pPath, pMode, pStream))
   3010        return NULL;
   3011    return pFile;
   3012}
   3013#ifndef MINIZ_NO_TIME
   3014#include <sys/utime.h>
   3015#endif
   3016#define MZ_FOPEN mz_fopen
   3017#define MZ_FCLOSE fclose
   3018#define MZ_FREAD fread
   3019#define MZ_FWRITE fwrite
   3020#define MZ_FTELL64 _ftelli64
   3021#define MZ_FSEEK64 _fseeki64
   3022#define MZ_FILE_STAT_STRUCT _stat64
   3023#define MZ_FILE_STAT _stat64
   3024#define MZ_FFLUSH fflush
   3025#define MZ_FREOPEN mz_freopen
   3026#define MZ_DELETE_FILE remove
   3027#elif defined(__MINGW32__)
   3028#ifndef MINIZ_NO_TIME
   3029#include <sys/utime.h>
   3030#endif
   3031#define MZ_FOPEN(f, m) fopen(f, m)
   3032#define MZ_FCLOSE fclose
   3033#define MZ_FREAD fread
   3034#define MZ_FWRITE fwrite
   3035#define MZ_FTELL64 ftello64
   3036#define MZ_FSEEK64 fseeko64
   3037#define MZ_FILE_STAT_STRUCT _stat
   3038#define MZ_FILE_STAT _stat
   3039#define MZ_FFLUSH fflush
   3040#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
   3041#define MZ_DELETE_FILE remove
   3042#elif defined(__TINYC__)
   3043#ifndef MINIZ_NO_TIME
   3044#include <sys/utime.h>
   3045#endif
   3046#define MZ_FOPEN(f, m) fopen(f, m)
   3047#define MZ_FCLOSE fclose
   3048#define MZ_FREAD fread
   3049#define MZ_FWRITE fwrite
   3050#define MZ_FTELL64 ftell
   3051#define MZ_FSEEK64 fseek
   3052#define MZ_FILE_STAT_STRUCT stat
   3053#define MZ_FILE_STAT stat
   3054#define MZ_FFLUSH fflush
   3055#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
   3056#define MZ_DELETE_FILE remove
   3057#elif defined(__USE_LARGEFILE64) /* gcc, clang */
   3058#ifndef MINIZ_NO_TIME
   3059#include <utime.h>
   3060#endif
   3061#define MZ_FOPEN(f, m) fopen64(f, m)
   3062#define MZ_FCLOSE fclose
   3063#define MZ_FREAD fread
   3064#define MZ_FWRITE fwrite
   3065#define MZ_FTELL64 ftello64
   3066#define MZ_FSEEK64 fseeko64
   3067#define MZ_FILE_STAT_STRUCT stat64
   3068#define MZ_FILE_STAT stat64
   3069#define MZ_FFLUSH fflush
   3070#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
   3071#define MZ_DELETE_FILE remove
   3072#elif defined(__APPLE__)
   3073#ifndef MINIZ_NO_TIME
   3074#include <utime.h>
   3075#endif
   3076#define MZ_FOPEN(f, m) fopen(f, m)
   3077#define MZ_FCLOSE fclose
   3078#define MZ_FREAD fread
   3079#define MZ_FWRITE fwrite
   3080#define MZ_FTELL64 ftello
   3081#define MZ_FSEEK64 fseeko
   3082#define MZ_FILE_STAT_STRUCT stat
   3083#define MZ_FILE_STAT stat
   3084#define MZ_FFLUSH fflush
   3085#define MZ_FREOPEN(p, m, s) freopen(p, m, s)
   3086#define MZ_DELETE_FILE remove
   3087
   3088#else
   3089#pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
   3090#ifndef MINIZ_NO_TIME
   3091#include <utime.h>
   3092#endif
   3093#define MZ_FOPEN(f, m) fopen(f, m)
   3094#define MZ_FCLOSE fclose
   3095#define MZ_FREAD fread
   3096#define MZ_FWRITE fwrite
   3097#ifdef __STRICT_ANSI__
   3098#define MZ_FTELL64 ftell
   3099#define MZ_FSEEK64 fseek
   3100#else
   3101#define MZ_FTELL64 ftello
   3102#define MZ_FSEEK64 fseeko
   3103#endif
   3104#define MZ_FILE_STAT_STRUCT stat
   3105#define MZ_FILE_STAT stat
   3106#define MZ_FFLUSH fflush
   3107#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
   3108#define MZ_DELETE_FILE remove
   3109#endif /* #ifdef _MSC_VER */
   3110#endif /* #ifdef MINIZ_NO_STDIO */
   3111
   3112#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
   3113
   3114/* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */
   3115enum
   3116{
   3117    /* ZIP archive identifiers and record sizes */
   3118    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
   3119    MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
   3120    MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
   3121    MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
   3122    MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
   3123    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
   3124
   3125    /* ZIP64 archive identifier and record sizes */
   3126    MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
   3127    MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
   3128    MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
   3129    MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
   3130    MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
   3131    MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
   3132    MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
   3133    MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
   3134
   3135    /* Central directory header record offsets */
   3136    MZ_ZIP_CDH_SIG_OFS = 0,
   3137    MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
   3138    MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
   3139    MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
   3140    MZ_ZIP_CDH_METHOD_OFS = 10,
   3141    MZ_ZIP_CDH_FILE_TIME_OFS = 12,
   3142    MZ_ZIP_CDH_FILE_DATE_OFS = 14,
   3143    MZ_ZIP_CDH_CRC32_OFS = 16,
   3144    MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
   3145    MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
   3146    MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
   3147    MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
   3148    MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
   3149    MZ_ZIP_CDH_DISK_START_OFS = 34,
   3150    MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
   3151    MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
   3152    MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
   3153
   3154    /* Local directory header offsets */
   3155    MZ_ZIP_LDH_SIG_OFS = 0,
   3156    MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
   3157    MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
   3158    MZ_ZIP_LDH_METHOD_OFS = 8,
   3159    MZ_ZIP_LDH_FILE_TIME_OFS = 10,
   3160    MZ_ZIP_LDH_FILE_DATE_OFS = 12,
   3161    MZ_ZIP_LDH_CRC32_OFS = 14,
   3162    MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
   3163    MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
   3164    MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
   3165    MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
   3166    MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
   3167
   3168    /* End of central directory offsets */
   3169    MZ_ZIP_ECDH_SIG_OFS = 0,
   3170    MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
   3171    MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
   3172    MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
   3173    MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
   3174    MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
   3175    MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
   3176    MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
   3177
   3178    /* ZIP64 End of central directory locator offsets */
   3179    MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
   3180    MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
   3181    MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
   3182    MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
   3183
   3184    /* ZIP64 End of central directory header offsets */
   3185    MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
   3186    MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
   3187    MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
   3188    MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
   3189    MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
   3190    MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
   3191    MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
   3192    MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
   3193    MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
   3194    MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
   3195    MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
   3196    MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
   3197    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
   3198    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
   3199    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
   3200    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
   3201    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
   3202};
   3203
   3204typedef struct
   3205{
   3206    void *m_p;
   3207    size_t m_size, m_capacity;
   3208    mz_uint m_element_size;
   3209} mz_zip_array;
   3210
   3211struct mz_zip_internal_state_tag
   3212{
   3213    mz_zip_array m_central_dir;
   3214    mz_zip_array m_central_dir_offsets;
   3215    mz_zip_array m_sorted_central_dir_offsets;
   3216
   3217    /* The flags passed in when the archive is initially opened. */
   3218    uint32_t m_init_flags;
   3219
   3220    /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
   3221    mz_bool m_zip64;
   3222
   3223    /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */
   3224    mz_bool m_zip64_has_extended_info_fields;
   3225
   3226    /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
   3227    MZ_FILE *m_pFile;
   3228    mz_uint64 m_file_archive_start_ofs;
   3229
   3230    void *m_pMem;
   3231    size_t m_mem_size;
   3232    size_t m_mem_capacity;
   3233};
   3234
   3235#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
   3236
   3237#if defined(DEBUG) || defined(_DEBUG)
   3238static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
   3239{
   3240    MZ_ASSERT(index < pArray->m_size);
   3241    return index;
   3242}
   3243#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
   3244#else
   3245#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
   3246#endif
   3247
   3248static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
   3249{
   3250    memset(pArray, 0, sizeof(mz_zip_array));
   3251    pArray->m_element_size = element_size;
   3252}
   3253
   3254static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
   3255{
   3256    pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
   3257    memset(pArray, 0, sizeof(mz_zip_array));
   3258}
   3259
   3260static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
   3261{
   3262    void *pNew_p;
   3263    size_t new_capacity = min_new_capacity;
   3264    MZ_ASSERT(pArray->m_element_size);
   3265    if (pArray->m_capacity >= min_new_capacity)
   3266        return MZ_TRUE;
   3267    if (growing)
   3268    {
   3269        new_capacity = MZ_MAX(1, pArray->m_capacity);
   3270        while (new_capacity < min_new_capacity)
   3271            new_capacity *= 2;
   3272    }
   3273    if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
   3274        return MZ_FALSE;
   3275    pArray->m_p = pNew_p;
   3276    pArray->m_capacity = new_capacity;
   3277    return MZ_TRUE;
   3278}
   3279
   3280static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
   3281{
   3282    if (new_capacity > pArray->m_capacity)
   3283    {
   3284        if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
   3285            return MZ_FALSE;
   3286    }
   3287    return MZ_TRUE;
   3288}
   3289
   3290static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
   3291{
   3292    if (new_size > pArray->m_capacity)
   3293    {
   3294        if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
   3295            return MZ_FALSE;
   3296    }
   3297    pArray->m_size = new_size;
   3298    return MZ_TRUE;
   3299}
   3300
   3301static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
   3302{
   3303    return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
   3304}
   3305
   3306static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
   3307{
   3308    size_t orig_size = pArray->m_size;
   3309    if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
   3310        return MZ_FALSE;
   3311    if (n > 0)
   3312        memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
   3313    return MZ_TRUE;
   3314}
   3315
   3316#ifndef MINIZ_NO_TIME
   3317static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
   3318{
   3319    struct tm tm;
   3320    memset(&tm, 0, sizeof(tm));
   3321    tm.tm_isdst = -1;
   3322    tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
   3323    tm.tm_mon = ((dos_date >> 5) & 15) - 1;
   3324    tm.tm_mday = dos_date & 31;
   3325    tm.tm_hour = (dos_time >> 11) & 31;
   3326    tm.tm_min = (dos_time >> 5) & 63;
   3327    tm.tm_sec = (dos_time << 1) & 62;
   3328    return mktime(&tm);
   3329}
   3330
   3331#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
   3332static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
   3333{
   3334#ifdef _MSC_VER
   3335    struct tm tm_struct;
   3336    struct tm *tm = &tm_struct;
   3337    errno_t err = localtime_s(tm, &time);
   3338    if (err)
   3339    {
   3340        *pDOS_date = 0;
   3341        *pDOS_time = 0;
   3342        return;
   3343    }
   3344#else
   3345    struct tm *tm = localtime(&time);
   3346#endif /* #ifdef _MSC_VER */
   3347
   3348    *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
   3349    *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
   3350}
   3351#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
   3352
   3353#ifndef MINIZ_NO_STDIO
   3354#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
   3355static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
   3356{
   3357    struct MZ_FILE_STAT_STRUCT file_stat;
   3358
   3359    /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
   3360    if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
   3361        return MZ_FALSE;
   3362
   3363    *pTime = file_stat.st_mtime;
   3364
   3365    return MZ_TRUE;
   3366}
   3367#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
   3368
   3369static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
   3370{
   3371    struct utimbuf t;
   3372
   3373    memset(&t, 0, sizeof(t));
   3374    t.actime = access_time;
   3375    t.modtime = modified_time;
   3376
   3377    return !utime(pFilename, &t);
   3378}
   3379#endif /* #ifndef MINIZ_NO_STDIO */
   3380#endif /* #ifndef MINIZ_NO_TIME */
   3381
   3382static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
   3383{
   3384    if (pZip)
   3385        pZip->m_last_error = err_num;
   3386    return MZ_FALSE;
   3387}
   3388
   3389static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
   3390{
   3391    (void)flags;
   3392    if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
   3393        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   3394
   3395    if (!pZip->m_pAlloc)
   3396        pZip->m_pAlloc = miniz_def_alloc_func;
   3397    if (!pZip->m_pFree)
   3398        pZip->m_pFree = miniz_def_free_func;
   3399    if (!pZip->m_pRealloc)
   3400        pZip->m_pRealloc = miniz_def_realloc_func;
   3401
   3402    pZip->m_archive_size = 0;
   3403    pZip->m_central_directory_file_ofs = 0;
   3404    pZip->m_total_files = 0;
   3405    pZip->m_last_error = MZ_ZIP_NO_ERROR;
   3406
   3407    if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
   3408        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   3409
   3410    memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
   3411    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
   3412    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
   3413    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
   3414    pZip->m_pState->m_init_flags = flags;
   3415    pZip->m_pState->m_zip64 = MZ_FALSE;
   3416    pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
   3417
   3418    pZip->m_zip_mode = MZ_ZIP_MODE_READING;
   3419
   3420    return MZ_TRUE;
   3421}
   3422
   3423static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
   3424{
   3425    const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
   3426    const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
   3427    mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   3428    mz_uint8 l = 0, r = 0;
   3429    pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
   3430    pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
   3431    pE = pL + MZ_MIN(l_len, r_len);
   3432    while (pL < pE)
   3433    {
   3434        if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
   3435            break;
   3436        pL++;
   3437        pR++;
   3438    }
   3439    return (pL == pE) ? (l_len < r_len) : (l < r);
   3440}
   3441
   3442#define MZ_SWAP_UINT32(a, b) \
   3443    do                       \
   3444    {                        \
   3445        mz_uint32 t = a;     \
   3446        a = b;               \
   3447        b = t;               \
   3448    }                        \
   3449    MZ_MACRO_END
   3450
   3451/* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */
   3452static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
   3453{
   3454    mz_zip_internal_state *pState = pZip->m_pState;
   3455    const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
   3456    const mz_zip_array *pCentral_dir = &pState->m_central_dir;
   3457    mz_uint32 *pIndices;
   3458    mz_uint32 start, end;
   3459    const mz_uint32 size = pZip->m_total_files;
   3460
   3461    if (size <= 1U)
   3462        return;
   3463
   3464    pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
   3465
   3466    start = (size - 2U) >> 1U;
   3467    for (;;)
   3468    {
   3469        mz_uint64 child, root = start;
   3470        for (;;)
   3471        {
   3472            if ((child = (root << 1U) + 1U) >= size)
   3473                break;
   3474            child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
   3475            if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
   3476                break;
   3477            MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
   3478            root = child;
   3479        }
   3480        if (!start)
   3481            break;
   3482        start--;
   3483    }
   3484
   3485    end = size - 1;
   3486    while (end > 0)
   3487    {
   3488        mz_uint64 child, root = 0;
   3489        MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
   3490        for (;;)
   3491        {
   3492            if ((child = (root << 1U) + 1U) >= end)
   3493                break;
   3494            child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
   3495            if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
   3496                break;
   3497            MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
   3498            root = child;
   3499        }
   3500        end--;
   3501    }
   3502}
   3503
   3504static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
   3505{
   3506    mz_int64 cur_file_ofs;
   3507    mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
   3508    mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
   3509
   3510    /* Basic sanity checks - reject files which are too small */
   3511    if (pZip->m_archive_size < record_size)
   3512        return MZ_FALSE;
   3513
   3514    /* Find the record by scanning the file from the end towards the beginning. */
   3515    cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
   3516    for (;;)
   3517    {
   3518        int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
   3519
   3520        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
   3521            return MZ_FALSE;
   3522
   3523        for (i = n - 4; i >= 0; --i)
   3524        {
   3525            mz_uint s = MZ_READ_LE32(pBuf + i);
   3526            if (s == record_sig)
   3527            {
   3528                if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
   3529                    break;
   3530            }
   3531        }
   3532
   3533        if (i >= 0)
   3534        {
   3535            cur_file_ofs += i;
   3536            break;
   3537        }
   3538
   3539        /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
   3540        if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
   3541            return MZ_FALSE;
   3542
   3543        cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
   3544    }
   3545
   3546    *pOfs = cur_file_ofs;
   3547    return MZ_TRUE;
   3548}
   3549
   3550static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
   3551{
   3552    mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
   3553    mz_uint64 cdir_ofs = 0;
   3554    mz_int64 cur_file_ofs = 0;
   3555    const mz_uint8 *p;
   3556
   3557    mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
   3558    mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
   3559    mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
   3560    mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   3561    mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
   3562
   3563    mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   3564    mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
   3565
   3566    mz_uint64 zip64_end_of_central_dir_ofs = 0;
   3567
   3568    /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */
   3569    if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
   3570        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
   3571
   3572    if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
   3573        return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
   3574
   3575    /* Read and verify the end of central directory record. */
   3576    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
   3577        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   3578
   3579    if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
   3580        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
   3581
   3582    if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
   3583    {
   3584        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
   3585        {
   3586            if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
   3587            {
   3588                zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
   3589                if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
   3590                    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
   3591
   3592                if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
   3593                {
   3594                    if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
   3595                    {
   3596                        pZip->m_pState->m_zip64 = MZ_TRUE;
   3597                    }
   3598                }
   3599            }
   3600        }
   3601    }
   3602
   3603    pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
   3604    cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
   3605    num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
   3606    cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
   3607    cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
   3608    cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
   3609
   3610    if (pZip->m_pState->m_zip64)
   3611    {
   3612        mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
   3613        mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
   3614        mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
   3615        mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
   3616        mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
   3617
   3618        if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
   3619            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3620
   3621        if (zip64_total_num_of_disks != 1U)
   3622            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
   3623
   3624        /* Check for miniz's practical limits */
   3625        if (zip64_cdir_total_entries > MZ_UINT32_MAX)
   3626            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   3627
   3628        pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
   3629
   3630        if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
   3631            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   3632
   3633        cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
   3634
   3635        /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
   3636        if (zip64_size_of_central_directory > MZ_UINT32_MAX)
   3637            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
   3638
   3639        cdir_size = (mz_uint32)zip64_size_of_central_directory;
   3640
   3641        num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
   3642
   3643        cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
   3644
   3645        cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
   3646    }
   3647
   3648    if (pZip->m_total_files != cdir_entries_on_this_disk)
   3649        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
   3650
   3651    if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
   3652        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
   3653
   3654    if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
   3655        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3656
   3657    if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
   3658        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3659
   3660    pZip->m_central_directory_file_ofs = cdir_ofs;
   3661
   3662    if (pZip->m_total_files)
   3663    {
   3664        mz_uint i, n;
   3665        /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */
   3666        if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
   3667            (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
   3668            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   3669
   3670        if (sort_central_dir)
   3671        {
   3672            if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
   3673                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   3674        }
   3675
   3676        if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
   3677            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   3678
   3679        /* Now create an index into the central directory file records, do some basic sanity checking on each record */
   3680        p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
   3681        for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
   3682        {
   3683            mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
   3684            mz_uint64 comp_size, decomp_size, local_header_ofs;
   3685
   3686            if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
   3687                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3688
   3689            MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
   3690
   3691            if (sort_central_dir)
   3692                MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
   3693
   3694            comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
   3695            decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
   3696            local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
   3697            filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   3698            ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
   3699
   3700            if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
   3701                (ext_data_size) &&
   3702                (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
   3703            {
   3704                /* Attempt to find zip64 extended information field in the entry's extra data */
   3705                mz_uint32 extra_size_remaining = ext_data_size;
   3706
   3707                if (extra_size_remaining)
   3708                {
   3709					const mz_uint8 *pExtra_data;
   3710					void* buf = NULL;
   3711
   3712					if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
   3713					{
   3714						buf = MZ_MALLOC(ext_data_size);
   3715						if(buf==NULL)
   3716							return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   3717
   3718						if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size)
   3719						{
   3720							MZ_FREE(buf);
   3721							return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   3722						}
   3723
   3724						pExtra_data = (mz_uint8*)buf;
   3725					}
   3726					else
   3727					{
   3728						pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
   3729					}
   3730
   3731                    do
   3732                    {
   3733                        mz_uint32 field_id;
   3734                        mz_uint32 field_data_size;
   3735
   3736						if (extra_size_remaining < (sizeof(mz_uint16) * 2))
   3737						{
   3738							MZ_FREE(buf);
   3739							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3740						}
   3741
   3742                        field_id = MZ_READ_LE16(pExtra_data);
   3743                        field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
   3744
   3745						if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
   3746						{
   3747							MZ_FREE(buf);
   3748							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3749						}
   3750
   3751                        if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
   3752                        {
   3753                            /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */
   3754                            pZip->m_pState->m_zip64 = MZ_TRUE;
   3755                            pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
   3756                            break;
   3757                        }
   3758
   3759                        pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
   3760                        extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
   3761                    } while (extra_size_remaining);
   3762
   3763					MZ_FREE(buf);
   3764                }
   3765            }
   3766
   3767            /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
   3768            if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
   3769            {
   3770                if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
   3771                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3772            }
   3773
   3774            disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
   3775            if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
   3776                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
   3777
   3778            if (comp_size != MZ_UINT32_MAX)
   3779            {
   3780                if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
   3781                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3782            }
   3783
   3784            bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
   3785            if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
   3786                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
   3787
   3788            if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
   3789                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   3790
   3791            n -= total_header_size;
   3792            p += total_header_size;
   3793        }
   3794    }
   3795
   3796    if (sort_central_dir)
   3797        mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
   3798
   3799    return MZ_TRUE;
   3800}
   3801
   3802void mz_zip_zero_struct(mz_zip_archive *pZip)
   3803{
   3804    if (pZip)
   3805        MZ_CLEAR_OBJ(*pZip);
   3806}
   3807
   3808static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
   3809{
   3810    mz_bool status = MZ_TRUE;
   3811
   3812    if (!pZip)
   3813        return MZ_FALSE;
   3814
   3815    if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
   3816    {
   3817        if (set_last_error)
   3818            pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
   3819
   3820        return MZ_FALSE;
   3821    }
   3822
   3823    if (pZip->m_pState)
   3824    {
   3825        mz_zip_internal_state *pState = pZip->m_pState;
   3826        pZip->m_pState = NULL;
   3827
   3828        mz_zip_array_clear(pZip, &pState->m_central_dir);
   3829        mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
   3830        mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
   3831
   3832#ifndef MINIZ_NO_STDIO
   3833        if (pState->m_pFile)
   3834        {
   3835            if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
   3836            {
   3837                if (MZ_FCLOSE(pState->m_pFile) == EOF)
   3838                {
   3839                    if (set_last_error)
   3840                        pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
   3841                    status = MZ_FALSE;
   3842                }
   3843            }
   3844            pState->m_pFile = NULL;
   3845        }
   3846#endif /* #ifndef MINIZ_NO_STDIO */
   3847
   3848        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   3849    }
   3850    pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
   3851
   3852    return status;
   3853}
   3854
   3855mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
   3856{
   3857    return mz_zip_reader_end_internal(pZip, MZ_TRUE);
   3858}
   3859mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
   3860{
   3861    if ((!pZip) || (!pZip->m_pRead))
   3862        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   3863
   3864    if (!mz_zip_reader_init_internal(pZip, flags))
   3865        return MZ_FALSE;
   3866
   3867    pZip->m_zip_type = MZ_ZIP_TYPE_USER;
   3868    pZip->m_archive_size = size;
   3869
   3870    if (!mz_zip_reader_read_central_dir(pZip, flags))
   3871    {
   3872        mz_zip_reader_end_internal(pZip, MZ_FALSE);
   3873        return MZ_FALSE;
   3874    }
   3875
   3876    return MZ_TRUE;
   3877}
   3878
   3879static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
   3880{
   3881    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
   3882    size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
   3883    memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
   3884    return s;
   3885}
   3886
   3887mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
   3888{
   3889    if (!pMem)
   3890        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   3891
   3892    if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
   3893        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
   3894
   3895    if (!mz_zip_reader_init_internal(pZip, flags))
   3896        return MZ_FALSE;
   3897
   3898    pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
   3899    pZip->m_archive_size = size;
   3900    pZip->m_pRead = mz_zip_mem_read_func;
   3901    pZip->m_pIO_opaque = pZip;
   3902    pZip->m_pNeeds_keepalive = NULL;
   3903
   3904#ifdef __cplusplus
   3905    pZip->m_pState->m_pMem = const_cast<void *>(pMem);
   3906#else
   3907    pZip->m_pState->m_pMem = (void *)pMem;
   3908#endif
   3909
   3910    pZip->m_pState->m_mem_size = size;
   3911
   3912    if (!mz_zip_reader_read_central_dir(pZip, flags))
   3913    {
   3914        mz_zip_reader_end_internal(pZip, MZ_FALSE);
   3915        return MZ_FALSE;
   3916    }
   3917
   3918    return MZ_TRUE;
   3919}
   3920
   3921#ifndef MINIZ_NO_STDIO
   3922static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
   3923{
   3924    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
   3925    mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
   3926
   3927    file_ofs += pZip->m_pState->m_file_archive_start_ofs;
   3928
   3929    if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
   3930        return 0;
   3931
   3932    return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
   3933}
   3934
   3935mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
   3936{
   3937    return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
   3938}
   3939
   3940mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
   3941{
   3942    mz_uint64 file_size;
   3943    MZ_FILE *pFile;
   3944
   3945    if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
   3946        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   3947
   3948    pFile = MZ_FOPEN(pFilename, "rb");
   3949    if (!pFile)
   3950        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
   3951
   3952    file_size = archive_size;
   3953    if (!file_size)
   3954    {
   3955        if (MZ_FSEEK64(pFile, 0, SEEK_END))
   3956        {
   3957            MZ_FCLOSE(pFile);
   3958            return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
   3959        }
   3960
   3961        file_size = MZ_FTELL64(pFile);
   3962    }
   3963
   3964    /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
   3965
   3966    if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
   3967    {
   3968	MZ_FCLOSE(pFile);
   3969        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
   3970    }
   3971
   3972    if (!mz_zip_reader_init_internal(pZip, flags))
   3973    {
   3974        MZ_FCLOSE(pFile);
   3975        return MZ_FALSE;
   3976    }
   3977
   3978    pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
   3979    pZip->m_pRead = mz_zip_file_read_func;
   3980    pZip->m_pIO_opaque = pZip;
   3981    pZip->m_pState->m_pFile = pFile;
   3982    pZip->m_archive_size = file_size;
   3983    pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
   3984
   3985    if (!mz_zip_reader_read_central_dir(pZip, flags))
   3986    {
   3987        mz_zip_reader_end_internal(pZip, MZ_FALSE);
   3988        return MZ_FALSE;
   3989    }
   3990
   3991    return MZ_TRUE;
   3992}
   3993
   3994mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
   3995{
   3996    mz_uint64 cur_file_ofs;
   3997
   3998    if ((!pZip) || (!pFile))
   3999        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
   4000
   4001    cur_file_ofs = MZ_FTELL64(pFile);
   4002
   4003    if (!archive_size)
   4004    {
   4005        if (MZ_FSEEK64(pFile, 0, SEEK_END))
   4006            return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
   4007
   4008        archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
   4009
   4010        if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
   4011            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
   4012    }
   4013
   4014    if (!mz_zip_reader_init_internal(pZip, flags))
   4015        return MZ_FALSE;
   4016
   4017    pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
   4018    pZip->m_pRead = mz_zip_file_read_func;
   4019
   4020    pZip->m_pIO_opaque = pZip;
   4021    pZip->m_pState->m_pFile = pFile;
   4022    pZip->m_archive_size = archive_size;
   4023    pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
   4024
   4025    if (!mz_zip_reader_read_central_dir(pZip, flags))
   4026    {
   4027        mz_zip_reader_end_internal(pZip, MZ_FALSE);
   4028        return MZ_FALSE;
   4029    }
   4030
   4031    return MZ_TRUE;
   4032}
   4033
   4034#endif /* #ifndef MINIZ_NO_STDIO */
   4035
   4036static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
   4037{
   4038    if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
   4039        return NULL;
   4040    return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
   4041}
   4042
   4043mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
   4044{
   4045    mz_uint m_bit_flag;
   4046    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
   4047    if (!p)
   4048    {
   4049        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4050        return MZ_FALSE;
   4051    }
   4052
   4053    m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
   4054    return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
   4055}
   4056
   4057mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
   4058{
   4059    mz_uint bit_flag;
   4060    mz_uint method;
   4061
   4062    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
   4063    if (!p)
   4064    {
   4065        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4066        return MZ_FALSE;
   4067    }
   4068
   4069    method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
   4070    bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
   4071
   4072    if ((method != 0) && (method != MZ_DEFLATED))
   4073    {
   4074        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
   4075        return MZ_FALSE;
   4076    }
   4077
   4078    if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
   4079    {
   4080        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
   4081        return MZ_FALSE;
   4082    }
   4083
   4084    if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
   4085    {
   4086        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
   4087        return MZ_FALSE;
   4088    }
   4089
   4090    return MZ_TRUE;
   4091}
   4092
   4093mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
   4094{
   4095    mz_uint filename_len, attribute_mapping_id, external_attr;
   4096    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
   4097    if (!p)
   4098    {
   4099        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4100        return MZ_FALSE;
   4101    }
   4102
   4103    filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   4104    if (filename_len)
   4105    {
   4106        if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
   4107            return MZ_TRUE;
   4108    }
   4109
   4110    /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
   4111    /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */
   4112    /* FIXME: Remove this check? Is it necessary - we already check the filename. */
   4113    attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
   4114    (void)attribute_mapping_id;
   4115
   4116    external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
   4117    if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
   4118    {
   4119        return MZ_TRUE;
   4120    }
   4121
   4122    return MZ_FALSE;
   4123}
   4124
   4125static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
   4126{
   4127    mz_uint n;
   4128    const mz_uint8 *p = pCentral_dir_header;
   4129
   4130    if (pFound_zip64_extra_data)
   4131        *pFound_zip64_extra_data = MZ_FALSE;
   4132
   4133    if ((!p) || (!pStat))
   4134        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4135
   4136    /* Extract fields from the central directory record. */
   4137    pStat->m_file_index = file_index;
   4138    pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
   4139    pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
   4140    pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
   4141    pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
   4142    pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
   4143#ifndef MINIZ_NO_TIME
   4144    pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
   4145#endif
   4146    pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
   4147    pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
   4148    pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
   4149    pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
   4150    pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
   4151    pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
   4152
   4153    /* Copy as much of the filename and comment as possible. */
   4154    n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   4155    n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
   4156    memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
   4157    pStat->m_filename[n] = '\0';
   4158
   4159    n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
   4160    n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
   4161    pStat->m_comment_size = n;
   4162    memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n);
   4163    pStat->m_comment[n] = '\0';
   4164
   4165    /* Set some flags for convienance */
   4166    pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
   4167    pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
   4168    pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
   4169
   4170    /* See if we need to read any zip64 extended information fields. */
   4171    /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */
   4172    if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
   4173    {
   4174        /* Attempt to find zip64 extended information field in the entry's extra data */
   4175        mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
   4176
   4177        if (extra_size_remaining)
   4178        {
   4179            const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   4180
   4181            do
   4182            {
   4183                mz_uint32 field_id;
   4184                mz_uint32 field_data_size;
   4185
   4186                if (extra_size_remaining < (sizeof(mz_uint16) * 2))
   4187                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4188
   4189                field_id = MZ_READ_LE16(pExtra_data);
   4190                field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
   4191
   4192                if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
   4193                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4194
   4195                if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
   4196                {
   4197                    const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
   4198                    mz_uint32 field_data_remaining = field_data_size;
   4199
   4200                    if (pFound_zip64_extra_data)
   4201                        *pFound_zip64_extra_data = MZ_TRUE;
   4202
   4203                    if (pStat->m_uncomp_size == MZ_UINT32_MAX)
   4204                    {
   4205                        if (field_data_remaining < sizeof(mz_uint64))
   4206                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4207
   4208                        pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
   4209                        pField_data += sizeof(mz_uint64);
   4210                        field_data_remaining -= sizeof(mz_uint64);
   4211                    }
   4212
   4213                    if (pStat->m_comp_size == MZ_UINT32_MAX)
   4214                    {
   4215                        if (field_data_remaining < sizeof(mz_uint64))
   4216                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4217
   4218                        pStat->m_comp_size = MZ_READ_LE64(pField_data);
   4219                        pField_data += sizeof(mz_uint64);
   4220                        field_data_remaining -= sizeof(mz_uint64);
   4221                    }
   4222
   4223                    if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
   4224                    {
   4225                        if (field_data_remaining < sizeof(mz_uint64))
   4226                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4227
   4228                        pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
   4229                        pField_data += sizeof(mz_uint64);
   4230                        field_data_remaining -= sizeof(mz_uint64);
   4231                    }
   4232
   4233                    break;
   4234                }
   4235
   4236                pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
   4237                extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
   4238            } while (extra_size_remaining);
   4239        }
   4240    }
   4241
   4242    return MZ_TRUE;
   4243}
   4244
   4245static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
   4246{
   4247    mz_uint i;
   4248    if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
   4249        return 0 == memcmp(pA, pB, len);
   4250    for (i = 0; i < len; ++i)
   4251        if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
   4252            return MZ_FALSE;
   4253    return MZ_TRUE;
   4254}
   4255
   4256static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
   4257{
   4258    const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
   4259    mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   4260    mz_uint8 l = 0, r = 0;
   4261    pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
   4262    pE = pL + MZ_MIN(l_len, r_len);
   4263    while (pL < pE)
   4264    {
   4265        if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
   4266            break;
   4267        pL++;
   4268        pR++;
   4269    }
   4270    return (pL == pE) ? (int)(l_len - r_len) : (l - r);
   4271}
   4272
   4273static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
   4274{
   4275    mz_zip_internal_state *pState = pZip->m_pState;
   4276    const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
   4277    const mz_zip_array *pCentral_dir = &pState->m_central_dir;
   4278    mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
   4279    const uint32_t size = pZip->m_total_files;
   4280    const mz_uint filename_len = (mz_uint)strlen(pFilename);
   4281
   4282    if (pIndex)
   4283        *pIndex = 0;
   4284
   4285    if (size)
   4286    {
   4287        /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
   4288        /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
   4289        mz_int64 l = 0, h = (mz_int64)size - 1;
   4290
   4291        while (l <= h)
   4292        {
   4293            mz_int64 m = l + ((h - l) >> 1);
   4294            uint32_t file_index = pIndices[(uint32_t)m];
   4295
   4296            int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
   4297            if (!comp)
   4298            {
   4299                if (pIndex)
   4300                    *pIndex = file_index;
   4301                return MZ_TRUE;
   4302            }
   4303            else if (comp < 0)
   4304                l = m + 1;
   4305            else
   4306                h = m - 1;
   4307        }
   4308    }
   4309
   4310    return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
   4311}
   4312
   4313int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
   4314{
   4315    mz_uint32 index;
   4316    if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
   4317        return -1;
   4318    else
   4319        return (int)index;
   4320}
   4321
   4322mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
   4323{
   4324    mz_uint file_index;
   4325    size_t name_len, comment_len;
   4326
   4327    if (pIndex)
   4328        *pIndex = 0;
   4329
   4330    if ((!pZip) || (!pZip->m_pState) || (!pName))
   4331        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4332
   4333    /* See if we can use a binary search */
   4334    if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
   4335        (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
   4336        ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
   4337    {
   4338        return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
   4339    }
   4340
   4341    /* Locate the entry by scanning the entire central directory */
   4342    name_len = strlen(pName);
   4343    if (name_len > MZ_UINT16_MAX)
   4344        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4345
   4346    comment_len = pComment ? strlen(pComment) : 0;
   4347    if (comment_len > MZ_UINT16_MAX)
   4348        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4349
   4350    for (file_index = 0; file_index < pZip->m_total_files; file_index++)
   4351    {
   4352        const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
   4353        mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   4354        const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
   4355        if (filename_len < name_len)
   4356            continue;
   4357        if (comment_len)
   4358        {
   4359            mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
   4360            const char *pFile_comment = pFilename + filename_len + file_extra_len;
   4361            if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
   4362                continue;
   4363        }
   4364        if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
   4365        {
   4366            int ofs = filename_len - 1;
   4367            do
   4368            {
   4369                if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
   4370                    break;
   4371            } while (--ofs >= 0);
   4372            ofs++;
   4373            pFilename += ofs;
   4374            filename_len -= ofs;
   4375        }
   4376        if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
   4377        {
   4378            if (pIndex)
   4379                *pIndex = file_index;
   4380            return MZ_TRUE;
   4381        }
   4382    }
   4383
   4384    return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
   4385}
   4386
   4387mz_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)
   4388{
   4389    int status = TINFL_STATUS_DONE;
   4390    mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
   4391    mz_zip_archive_file_stat file_stat;
   4392    void *pRead_buf;
   4393    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   4394    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
   4395    tinfl_decompressor inflator;
   4396
   4397    if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
   4398        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4399
   4400    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
   4401        return MZ_FALSE;
   4402
   4403    /* A directory or zero length file */
   4404    if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
   4405        return MZ_TRUE;
   4406
   4407    /* Encryption and patch files are not supported. */
   4408    if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
   4409        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
   4410
   4411    /* This function only supports decompressing stored and deflate. */
   4412    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
   4413        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
   4414
   4415    /* Ensure supplied output buffer is large enough. */
   4416    needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
   4417    if (buf_size < needed_size)
   4418        return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
   4419
   4420    /* Read and parse the local directory entry. */
   4421    cur_file_ofs = file_stat.m_local_header_ofs;
   4422    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
   4423        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   4424
   4425    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
   4426        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4427
   4428    cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
   4429    if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
   4430        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4431
   4432    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
   4433    {
   4434        /* The file is stored or the caller has requested the compressed data. */
   4435        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
   4436            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   4437
   4438#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4439        if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
   4440        {
   4441            if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
   4442                return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
   4443        }
   4444#endif
   4445
   4446        return MZ_TRUE;
   4447    }
   4448
   4449    /* Decompress the file either directly from memory or from a file input buffer. */
   4450    tinfl_init(&inflator);
   4451
   4452    if (pZip->m_pState->m_pMem)
   4453    {
   4454        /* Read directly from the archive in memory. */
   4455        pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
   4456        read_buf_size = read_buf_avail = file_stat.m_comp_size;
   4457        comp_remaining = 0;
   4458    }
   4459    else if (pUser_read_buf)
   4460    {
   4461        /* Use a user provided read buffer. */
   4462        if (!user_read_buf_size)
   4463            return MZ_FALSE;
   4464        pRead_buf = (mz_uint8 *)pUser_read_buf;
   4465        read_buf_size = user_read_buf_size;
   4466        read_buf_avail = 0;
   4467        comp_remaining = file_stat.m_comp_size;
   4468    }
   4469    else
   4470    {
   4471        /* Temporarily allocate a read buffer. */
   4472        read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
   4473        if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
   4474            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   4475
   4476        if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
   4477            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4478
   4479        read_buf_avail = 0;
   4480        comp_remaining = file_stat.m_comp_size;
   4481    }
   4482
   4483    do
   4484    {
   4485        /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
   4486        size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
   4487        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
   4488        {
   4489            read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
   4490            if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
   4491            {
   4492                status = TINFL_STATUS_FAILED;
   4493                mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
   4494                break;
   4495            }
   4496            cur_file_ofs += read_buf_avail;
   4497            comp_remaining -= read_buf_avail;
   4498            read_buf_ofs = 0;
   4499        }
   4500        in_buf_size = (size_t)read_buf_avail;
   4501        status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
   4502        read_buf_avail -= in_buf_size;
   4503        read_buf_ofs += in_buf_size;
   4504        out_buf_ofs += out_buf_size;
   4505    } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
   4506
   4507    if (status == TINFL_STATUS_DONE)
   4508    {
   4509        /* Make sure the entire file was decompressed, and check its CRC. */
   4510        if (out_buf_ofs != file_stat.m_uncomp_size)
   4511        {
   4512            mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
   4513            status = TINFL_STATUS_FAILED;
   4514        }
   4515#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4516        else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
   4517        {
   4518            mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
   4519            status = TINFL_STATUS_FAILED;
   4520        }
   4521#endif
   4522    }
   4523
   4524    if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
   4525        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   4526
   4527    return status == TINFL_STATUS_DONE;
   4528}
   4529
   4530mz_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)
   4531{
   4532    mz_uint32 file_index;
   4533    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
   4534        return MZ_FALSE;
   4535    return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
   4536}
   4537
   4538mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
   4539{
   4540    return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
   4541}
   4542
   4543mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
   4544{
   4545    return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
   4546}
   4547
   4548void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
   4549{
   4550    mz_uint64 comp_size, uncomp_size, alloc_size;
   4551    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
   4552    void *pBuf;
   4553
   4554    if (pSize)
   4555        *pSize = 0;
   4556
   4557    if (!p)
   4558    {
   4559        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4560        return NULL;
   4561    }
   4562
   4563    comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
   4564    uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
   4565
   4566    alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
   4567    if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
   4568    {
   4569        mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   4570        return NULL;
   4571    }
   4572
   4573    if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
   4574    {
   4575        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4576        return NULL;
   4577    }
   4578
   4579    if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
   4580    {
   4581        pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   4582        return NULL;
   4583    }
   4584
   4585    if (pSize)
   4586        *pSize = (size_t)alloc_size;
   4587    return pBuf;
   4588}
   4589
   4590void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
   4591{
   4592    mz_uint32 file_index;
   4593    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
   4594    {
   4595        if (pSize)
   4596            *pSize = 0;
   4597        return MZ_FALSE;
   4598    }
   4599    return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
   4600}
   4601
   4602mz_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)
   4603{
   4604    int status = TINFL_STATUS_DONE;
   4605#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4606    mz_uint file_crc32 = MZ_CRC32_INIT;
   4607#endif
   4608    mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
   4609    mz_zip_archive_file_stat file_stat;
   4610    void *pRead_buf = NULL;
   4611    void *pWrite_buf = NULL;
   4612    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   4613    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
   4614
   4615    if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
   4616        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   4617
   4618    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
   4619        return MZ_FALSE;
   4620
   4621    /* A directory or zero length file */
   4622    if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
   4623        return MZ_TRUE;
   4624
   4625    /* Encryption and patch files are not supported. */
   4626    if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
   4627        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
   4628
   4629    /* This function only supports decompressing stored and deflate. */
   4630    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
   4631        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
   4632
   4633    /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */
   4634    cur_file_ofs = file_stat.m_local_header_ofs;
   4635    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
   4636        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   4637
   4638    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
   4639        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4640
   4641    cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
   4642    if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
   4643        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4644
   4645    /* Decompress the file either directly from memory or from a file input buffer. */
   4646    if (pZip->m_pState->m_pMem)
   4647    {
   4648        pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
   4649        read_buf_size = read_buf_avail = file_stat.m_comp_size;
   4650        comp_remaining = 0;
   4651    }
   4652    else
   4653    {
   4654        read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
   4655        if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
   4656            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4657
   4658        read_buf_avail = 0;
   4659        comp_remaining = file_stat.m_comp_size;
   4660    }
   4661
   4662    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
   4663    {
   4664        /* The file is stored or the caller has requested the compressed data. */
   4665        if (pZip->m_pState->m_pMem)
   4666        {
   4667            if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
   4668                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   4669
   4670            if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
   4671            {
   4672                mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
   4673                status = TINFL_STATUS_FAILED;
   4674            }
   4675            else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
   4676            {
   4677#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4678                file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
   4679#endif
   4680            }
   4681
   4682            cur_file_ofs += file_stat.m_comp_size;
   4683            out_buf_ofs += file_stat.m_comp_size;
   4684            comp_remaining = 0;
   4685        }
   4686        else
   4687        {
   4688            while (comp_remaining)
   4689            {
   4690                read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
   4691                if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
   4692                {
   4693                    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   4694                    status = TINFL_STATUS_FAILED;
   4695                    break;
   4696                }
   4697
   4698#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4699                if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
   4700                {
   4701                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
   4702                }
   4703#endif
   4704
   4705                if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
   4706                {
   4707                    mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
   4708                    status = TINFL_STATUS_FAILED;
   4709                    break;
   4710                }
   4711
   4712                cur_file_ofs += read_buf_avail;
   4713                out_buf_ofs += read_buf_avail;
   4714                comp_remaining -= read_buf_avail;
   4715            }
   4716        }
   4717    }
   4718    else
   4719    {
   4720        tinfl_decompressor inflator;
   4721        tinfl_init(&inflator);
   4722
   4723        if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
   4724        {
   4725            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4726            status = TINFL_STATUS_FAILED;
   4727        }
   4728        else
   4729        {
   4730            do
   4731            {
   4732                mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
   4733                size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
   4734                if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
   4735                {
   4736                    read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
   4737                    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
   4738                    {
   4739                        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   4740                        status = TINFL_STATUS_FAILED;
   4741                        break;
   4742                    }
   4743                    cur_file_ofs += read_buf_avail;
   4744                    comp_remaining -= read_buf_avail;
   4745                    read_buf_ofs = 0;
   4746                }
   4747
   4748                in_buf_size = (size_t)read_buf_avail;
   4749                status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
   4750                read_buf_avail -= in_buf_size;
   4751                read_buf_ofs += in_buf_size;
   4752
   4753                if (out_buf_size)
   4754                {
   4755                    if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
   4756                    {
   4757                        mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
   4758                        status = TINFL_STATUS_FAILED;
   4759                        break;
   4760                    }
   4761
   4762#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4763                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
   4764#endif
   4765                    if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
   4766                    {
   4767                        mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
   4768                        status = TINFL_STATUS_FAILED;
   4769                        break;
   4770                    }
   4771                }
   4772            } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
   4773        }
   4774    }
   4775
   4776    if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
   4777    {
   4778        /* Make sure the entire file was decompressed, and check its CRC. */
   4779        if (out_buf_ofs != file_stat.m_uncomp_size)
   4780        {
   4781            mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
   4782            status = TINFL_STATUS_FAILED;
   4783        }
   4784#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4785        else if (file_crc32 != file_stat.m_crc32)
   4786        {
   4787            mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
   4788            status = TINFL_STATUS_FAILED;
   4789        }
   4790#endif
   4791    }
   4792
   4793    if (!pZip->m_pState->m_pMem)
   4794        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   4795
   4796    if (pWrite_buf)
   4797        pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
   4798
   4799    return status == TINFL_STATUS_DONE;
   4800}
   4801
   4802mz_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)
   4803{
   4804    mz_uint32 file_index;
   4805    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
   4806        return MZ_FALSE;
   4807
   4808    return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
   4809}
   4810
   4811mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
   4812{
   4813    mz_zip_reader_extract_iter_state *pState;
   4814    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   4815    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
   4816
   4817    /* Argument sanity check */
   4818    if ((!pZip) || (!pZip->m_pState))
   4819        return NULL;
   4820
   4821    /* Allocate an iterator status structure */
   4822    pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
   4823    if (!pState)
   4824    {
   4825        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4826        return NULL;
   4827    }
   4828
   4829    /* Fetch file details */
   4830    if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
   4831    {
   4832        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4833        return NULL;
   4834    }
   4835
   4836    /* Encryption and patch files are not supported. */
   4837    if (pState->file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
   4838    {
   4839        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
   4840        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4841        return NULL;
   4842    }
   4843
   4844    /* This function only supports decompressing stored and deflate. */
   4845    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
   4846    {
   4847        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
   4848        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4849        return NULL;
   4850    }
   4851
   4852    /* Init state - save args */
   4853    pState->pZip = pZip;
   4854    pState->flags = flags;
   4855
   4856    /* Init state - reset variables to defaults */
   4857    pState->status = TINFL_STATUS_DONE;
   4858#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4859    pState->file_crc32 = MZ_CRC32_INIT;
   4860#endif
   4861    pState->read_buf_ofs = 0;
   4862    pState->out_buf_ofs = 0;
   4863    pState->pRead_buf = NULL;
   4864    pState->pWrite_buf = NULL;
   4865    pState->out_blk_remain = 0;
   4866
   4867    /* Read and parse the local directory entry. */
   4868    pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
   4869    if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
   4870    {
   4871        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   4872        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4873        return NULL;
   4874    }
   4875
   4876    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
   4877    {
   4878        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4879        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4880        return NULL;
   4881    }
   4882
   4883    pState->cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
   4884    if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
   4885    {
   4886        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   4887        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4888        return NULL;
   4889    }
   4890
   4891    /* Decompress the file either directly from memory or from a file input buffer. */
   4892    if (pZip->m_pState->m_pMem)
   4893    {
   4894        pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
   4895        pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
   4896        pState->comp_remaining = pState->file_stat.m_comp_size;
   4897    }
   4898    else
   4899    {
   4900        if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
   4901        {
   4902            /* Decompression required, therefore intermediate read buffer required */
   4903            pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
   4904            if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
   4905            {
   4906                mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4907                pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4908                return NULL;
   4909            }
   4910        }
   4911        else
   4912        {
   4913            /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
   4914            pState->read_buf_size = 0;
   4915        }
   4916        pState->read_buf_avail = 0;
   4917        pState->comp_remaining = pState->file_stat.m_comp_size;
   4918    }
   4919
   4920    if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
   4921    {
   4922        /* Decompression required, init decompressor */
   4923        tinfl_init( &pState->inflator );
   4924
   4925        /* Allocate write buffer */
   4926        if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
   4927        {
   4928            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   4929            if (pState->pRead_buf)
   4930                pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
   4931            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   4932            return NULL;
   4933        }
   4934    }
   4935
   4936    return pState;
   4937}
   4938
   4939mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
   4940{
   4941    mz_uint32 file_index;
   4942
   4943    /* Locate file index by name */
   4944    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
   4945        return NULL;
   4946
   4947    /* Construct iterator */
   4948    return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
   4949}
   4950
   4951size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
   4952{
   4953    size_t copied_to_caller = 0;
   4954
   4955    /* Argument sanity check */
   4956    if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
   4957        return 0;
   4958
   4959    if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
   4960    {
   4961        /* The file is stored or the caller has requested the compressed data, calc amount to return. */
   4962        copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
   4963
   4964        /* Zip is in memory....or requires reading from a file? */
   4965        if (pState->pZip->m_pState->m_pMem)
   4966        {
   4967            /* Copy data to caller's buffer */
   4968            memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
   4969            pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
   4970        }
   4971        else
   4972        {
   4973            /* Read directly into caller's buffer */
   4974            if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
   4975            {
   4976                /* Failed to read all that was asked for, flag failure and alert user */
   4977                mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
   4978                pState->status = TINFL_STATUS_FAILED;
   4979                copied_to_caller = 0;
   4980            }
   4981        }
   4982
   4983#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   4984        /* Compute CRC if not returning compressed data only */
   4985        if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
   4986            pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
   4987#endif
   4988
   4989        /* Advance offsets, dec counters */
   4990        pState->cur_file_ofs += copied_to_caller;
   4991        pState->out_buf_ofs += copied_to_caller;
   4992        pState->comp_remaining -= copied_to_caller;
   4993    }
   4994    else
   4995    {
   4996        do
   4997        {
   4998            /* Calc ptr to write buffer - given current output pos and block size */
   4999            mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
   5000
   5001            /* Calc max output size - given current output pos and block size */
   5002            size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
   5003
   5004            if (!pState->out_blk_remain)
   5005            {
   5006                /* Read more data from file if none available (and reading from file) */
   5007                if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
   5008                {
   5009                    /* Calc read size */
   5010                    pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
   5011                    if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail)
   5012                    {
   5013                        mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
   5014                        pState->status = TINFL_STATUS_FAILED;
   5015                        break;
   5016                    }
   5017
   5018                    /* Advance offsets, dec counters */
   5019                    pState->cur_file_ofs += pState->read_buf_avail;
   5020                    pState->comp_remaining -= pState->read_buf_avail;
   5021                    pState->read_buf_ofs = 0;
   5022                }
   5023
   5024                /* Perform decompression */
   5025                in_buf_size = (size_t)pState->read_buf_avail;
   5026                pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
   5027                pState->read_buf_avail -= in_buf_size;
   5028                pState->read_buf_ofs += in_buf_size;
   5029
   5030                /* Update current output block size remaining */
   5031                pState->out_blk_remain = out_buf_size;
   5032            }
   5033
   5034            if (pState->out_blk_remain)
   5035            {
   5036                /* Calc amount to return. */
   5037                size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
   5038
   5039                /* Copy data to caller's buffer */
   5040                memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
   5041
   5042#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   5043                /* Perform CRC */
   5044                pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
   5045#endif
   5046
   5047                /* Decrement data consumed from block */
   5048                pState->out_blk_remain -= to_copy;
   5049
   5050                /* Inc output offset, while performing sanity check */
   5051                if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
   5052                {
   5053                    mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
   5054                    pState->status = TINFL_STATUS_FAILED;
   5055                    break;
   5056                }
   5057
   5058                /* Increment counter of data copied to caller */
   5059                copied_to_caller += to_copy;
   5060            }
   5061        } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
   5062    }
   5063
   5064    /* Return how many bytes were copied into user buffer */
   5065    return copied_to_caller;
   5066}
   5067
   5068mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)
   5069{
   5070    int status;
   5071
   5072    /* Argument sanity check */
   5073    if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
   5074        return MZ_FALSE;
   5075
   5076    /* Was decompression completed and requested? */
   5077    if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
   5078    {
   5079        /* Make sure the entire file was decompressed, and check its CRC. */
   5080        if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
   5081        {
   5082            mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
   5083            pState->status = TINFL_STATUS_FAILED;
   5084        }
   5085#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
   5086        else if (pState->file_crc32 != pState->file_stat.m_crc32)
   5087        {
   5088            mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
   5089            pState->status = TINFL_STATUS_FAILED;
   5090        }
   5091#endif
   5092    }
   5093
   5094    /* Free buffers */
   5095    if (!pState->pZip->m_pState->m_pMem)
   5096        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
   5097    if (pState->pWrite_buf)
   5098        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
   5099
   5100    /* Save status */
   5101    status = pState->status;
   5102
   5103    /* Free context */
   5104    pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
   5105
   5106    return status == TINFL_STATUS_DONE;
   5107}
   5108
   5109#ifndef MINIZ_NO_STDIO
   5110static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
   5111{
   5112    (void)ofs;
   5113
   5114    return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
   5115}
   5116
   5117mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
   5118{
   5119    mz_bool status;
   5120    mz_zip_archive_file_stat file_stat;
   5121    MZ_FILE *pFile;
   5122
   5123    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
   5124        return MZ_FALSE;
   5125
   5126    if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
   5127        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
   5128
   5129    pFile = MZ_FOPEN(pDst_filename, "wb");
   5130    if (!pFile)
   5131        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
   5132
   5133    status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
   5134
   5135    if (MZ_FCLOSE(pFile) == EOF)
   5136    {
   5137        if (status)
   5138            mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
   5139
   5140        status = MZ_FALSE;
   5141    }
   5142
   5143#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
   5144    if (status)
   5145        mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
   5146#endif
   5147
   5148    return status;
   5149}
   5150
   5151mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
   5152{
   5153    mz_uint32 file_index;
   5154    if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
   5155        return MZ_FALSE;
   5156
   5157    return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
   5158}
   5159
   5160mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
   5161{
   5162    mz_zip_archive_file_stat file_stat;
   5163
   5164    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
   5165        return MZ_FALSE;
   5166
   5167    if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
   5168        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
   5169
   5170    return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
   5171}
   5172
   5173mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
   5174{
   5175    mz_uint32 file_index;
   5176    if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
   5177        return MZ_FALSE;
   5178
   5179    return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
   5180}
   5181#endif /* #ifndef MINIZ_NO_STDIO */
   5182
   5183static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
   5184{
   5185    mz_uint32 *p = (mz_uint32 *)pOpaque;
   5186    (void)file_ofs;
   5187    *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
   5188    return n;
   5189}
   5190
   5191mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
   5192{
   5193    mz_zip_archive_file_stat file_stat;
   5194    mz_zip_internal_state *pState;
   5195    const mz_uint8 *pCentral_dir_header;
   5196    mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
   5197    mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
   5198    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   5199    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
   5200    mz_uint64 local_header_ofs = 0;
   5201    mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
   5202    mz_uint64 local_header_comp_size, local_header_uncomp_size;
   5203    mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
   5204    mz_bool has_data_descriptor;
   5205    mz_uint32 local_header_bit_flags;
   5206
   5207    mz_zip_array file_data_array;
   5208    mz_zip_array_init(&file_data_array, 1);
   5209
   5210    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
   5211        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5212
   5213    if (file_index > pZip->m_total_files)
   5214        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5215
   5216    pState = pZip->m_pState;
   5217
   5218    pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
   5219
   5220    if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
   5221        return MZ_FALSE;
   5222
   5223    /* A directory or zero length file */
   5224    if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
   5225        return MZ_TRUE;
   5226
   5227    /* Encryption and patch files are not supported. */
   5228    if (file_stat.m_is_encrypted)
   5229        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
   5230
   5231    /* This function only supports stored and deflate. */
   5232    if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
   5233        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
   5234
   5235    if (!file_stat.m_is_supported)
   5236        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
   5237
   5238    /* Read and parse the local directory entry. */
   5239    local_header_ofs = file_stat.m_local_header_ofs;
   5240    if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
   5241        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   5242
   5243    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
   5244        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   5245
   5246    local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
   5247    local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
   5248    local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
   5249    local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
   5250    local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
   5251    local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
   5252    has_data_descriptor = (local_header_bit_flags & 8) != 0;
   5253
   5254    if (local_header_filename_len != strlen(file_stat.m_filename))
   5255        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   5256
   5257    if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)
   5258        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   5259
   5260    if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
   5261    {
   5262        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   5263        goto handle_failure;
   5264    }
   5265
   5266    if (local_header_filename_len)
   5267    {
   5268        if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)
   5269        {
   5270            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   5271            goto handle_failure;
   5272        }
   5273
   5274        /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */
   5275        if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
   5276        {
   5277            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
   5278            goto handle_failure;
   5279        }
   5280    }
   5281
   5282    if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
   5283    {
   5284        mz_uint32 extra_size_remaining = local_header_extra_len;
   5285        const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
   5286
   5287        if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
   5288        {
   5289            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   5290            goto handle_failure;
   5291        }
   5292
   5293        do
   5294        {
   5295            mz_uint32 field_id, field_data_size, field_total_size;
   5296
   5297            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
   5298            {
   5299                mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   5300                goto handle_failure;
   5301            }
   5302
   5303            field_id = MZ_READ_LE16(pExtra_data);
   5304            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
   5305            field_total_size = field_data_size + sizeof(mz_uint16) * 2;
   5306
   5307            if (field_total_size > extra_size_remaining)
   5308            {
   5309                mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   5310                goto handle_failure;
   5311            }
   5312
   5313            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
   5314            {
   5315                const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
   5316
   5317                if (field_data_size < sizeof(mz_uint64) * 2)
   5318                {
   5319                    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   5320                    goto handle_failure;
   5321                }
   5322
   5323                local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
   5324                local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
   5325
   5326                found_zip64_ext_data_in_ldir = MZ_TRUE;
   5327                break;
   5328            }
   5329
   5330            pExtra_data += field_total_size;
   5331            extra_size_remaining -= field_total_size;
   5332        } while (extra_size_remaining);
   5333    }
   5334
   5335    /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
   5336    /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
   5337    if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
   5338    {
   5339        mz_uint8 descriptor_buf[32];
   5340        mz_bool has_id;
   5341        const mz_uint8 *pSrc;
   5342        mz_uint32 file_crc32;
   5343        mz_uint64 comp_size = 0, uncomp_size = 0;
   5344
   5345        mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
   5346
   5347        if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))
   5348        {
   5349            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   5350            goto handle_failure;
   5351        }
   5352
   5353        has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
   5354        pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
   5355
   5356        file_crc32 = MZ_READ_LE32(pSrc);
   5357
   5358        if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
   5359        {
   5360            comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
   5361            uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
   5362        }
   5363        else
   5364        {
   5365            comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
   5366            uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
   5367        }
   5368
   5369        if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
   5370        {
   5371            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
   5372            goto handle_failure;
   5373        }
   5374    }
   5375    else
   5376    {
   5377        if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))
   5378        {
   5379            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
   5380            goto handle_failure;
   5381        }
   5382    }
   5383
   5384    mz_zip_array_clear(pZip, &file_data_array);
   5385
   5386    if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
   5387    {
   5388        if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
   5389            return MZ_FALSE;
   5390
   5391        /* 1 more check to be sure, although the extract checks too. */
   5392        if (uncomp_crc32 != file_stat.m_crc32)
   5393        {
   5394            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
   5395            return MZ_FALSE;
   5396        }
   5397    }
   5398
   5399    return MZ_TRUE;
   5400
   5401handle_failure:
   5402    mz_zip_array_clear(pZip, &file_data_array);
   5403    return MZ_FALSE;
   5404}
   5405
   5406mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
   5407{
   5408    mz_zip_internal_state *pState;
   5409    uint32_t i;
   5410
   5411    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
   5412        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5413
   5414    pState = pZip->m_pState;
   5415
   5416    /* Basic sanity checks */
   5417    if (!pState->m_zip64)
   5418    {
   5419        if (pZip->m_total_files > MZ_UINT16_MAX)
   5420            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   5421
   5422        if (pZip->m_archive_size > MZ_UINT32_MAX)
   5423            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   5424    }
   5425    else
   5426    {
   5427        if (pZip->m_total_files >= MZ_UINT32_MAX)
   5428            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   5429
   5430        if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
   5431            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   5432    }
   5433
   5434    for (i = 0; i < pZip->m_total_files; i++)
   5435    {
   5436        if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
   5437        {
   5438            mz_uint32 found_index;
   5439            mz_zip_archive_file_stat stat;
   5440
   5441            if (!mz_zip_reader_file_stat(pZip, i, &stat))
   5442                return MZ_FALSE;
   5443
   5444            if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
   5445                return MZ_FALSE;
   5446
   5447            /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
   5448            if (found_index != i)
   5449                return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
   5450        }
   5451
   5452        if (!mz_zip_validate_file(pZip, i, flags))
   5453            return MZ_FALSE;
   5454    }
   5455
   5456    return MZ_TRUE;
   5457}
   5458
   5459mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
   5460{
   5461    mz_bool success = MZ_TRUE;
   5462    mz_zip_archive zip;
   5463    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
   5464
   5465    if ((!pMem) || (!size))
   5466    {
   5467        if (pErr)
   5468            *pErr = MZ_ZIP_INVALID_PARAMETER;
   5469        return MZ_FALSE;
   5470    }
   5471
   5472    mz_zip_zero_struct(&zip);
   5473
   5474    if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
   5475    {
   5476        if (pErr)
   5477            *pErr = zip.m_last_error;
   5478        return MZ_FALSE;
   5479    }
   5480
   5481    if (!mz_zip_validate_archive(&zip, flags))
   5482    {
   5483        actual_err = zip.m_last_error;
   5484        success = MZ_FALSE;
   5485    }
   5486
   5487    if (!mz_zip_reader_end_internal(&zip, success))
   5488    {
   5489        if (!actual_err)
   5490            actual_err = zip.m_last_error;
   5491        success = MZ_FALSE;
   5492    }
   5493
   5494    if (pErr)
   5495        *pErr = actual_err;
   5496
   5497    return success;
   5498}
   5499
   5500#ifndef MINIZ_NO_STDIO
   5501mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
   5502{
   5503    mz_bool success = MZ_TRUE;
   5504    mz_zip_archive zip;
   5505    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
   5506
   5507    if (!pFilename)
   5508    {
   5509        if (pErr)
   5510            *pErr = MZ_ZIP_INVALID_PARAMETER;
   5511        return MZ_FALSE;
   5512    }
   5513
   5514    mz_zip_zero_struct(&zip);
   5515
   5516    if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
   5517    {
   5518        if (pErr)
   5519            *pErr = zip.m_last_error;
   5520        return MZ_FALSE;
   5521    }
   5522
   5523    if (!mz_zip_validate_archive(&zip, flags))
   5524    {
   5525        actual_err = zip.m_last_error;
   5526        success = MZ_FALSE;
   5527    }
   5528
   5529    if (!mz_zip_reader_end_internal(&zip, success))
   5530    {
   5531        if (!actual_err)
   5532            actual_err = zip.m_last_error;
   5533        success = MZ_FALSE;
   5534    }
   5535
   5536    if (pErr)
   5537        *pErr = actual_err;
   5538
   5539    return success;
   5540}
   5541#endif /* #ifndef MINIZ_NO_STDIO */
   5542
   5543/* ------------------- .ZIP archive writing */
   5544
   5545#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
   5546
   5547static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
   5548{
   5549    p[0] = (mz_uint8)v;
   5550    p[1] = (mz_uint8)(v >> 8);
   5551}
   5552static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
   5553{
   5554    p[0] = (mz_uint8)v;
   5555    p[1] = (mz_uint8)(v >> 8);
   5556    p[2] = (mz_uint8)(v >> 16);
   5557    p[3] = (mz_uint8)(v >> 24);
   5558}
   5559static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
   5560{
   5561    mz_write_le32(p, (mz_uint32)v);
   5562    mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
   5563}
   5564
   5565#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
   5566#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
   5567#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
   5568
   5569static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
   5570{
   5571    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
   5572    mz_zip_internal_state *pState = pZip->m_pState;
   5573    mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
   5574
   5575    if (!n)
   5576        return 0;
   5577
   5578    /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
   5579    if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
   5580    {
   5581        mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
   5582        return 0;
   5583    }
   5584
   5585    if (new_size > pState->m_mem_capacity)
   5586    {
   5587        void *pNew_block;
   5588        size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
   5589
   5590        while (new_capacity < new_size)
   5591            new_capacity *= 2;
   5592
   5593        if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
   5594        {
   5595            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   5596            return 0;
   5597        }
   5598
   5599        pState->m_pMem = pNew_block;
   5600        pState->m_mem_capacity = new_capacity;
   5601    }
   5602    memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
   5603    pState->m_mem_size = (size_t)new_size;
   5604    return n;
   5605}
   5606
   5607static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
   5608{
   5609    mz_zip_internal_state *pState;
   5610    mz_bool status = MZ_TRUE;
   5611
   5612    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
   5613    {
   5614        if (set_last_error)
   5615            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5616        return MZ_FALSE;
   5617    }
   5618
   5619    pState = pZip->m_pState;
   5620    pZip->m_pState = NULL;
   5621    mz_zip_array_clear(pZip, &pState->m_central_dir);
   5622    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
   5623    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
   5624
   5625#ifndef MINIZ_NO_STDIO
   5626    if (pState->m_pFile)
   5627    {
   5628        if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
   5629        {
   5630            if (MZ_FCLOSE(pState->m_pFile) == EOF)
   5631            {
   5632                if (set_last_error)
   5633                    mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
   5634                status = MZ_FALSE;
   5635            }
   5636        }
   5637
   5638        pState->m_pFile = NULL;
   5639    }
   5640#endif /* #ifndef MINIZ_NO_STDIO */
   5641
   5642    if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
   5643    {
   5644        pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
   5645        pState->m_pMem = NULL;
   5646    }
   5647
   5648    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
   5649    pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
   5650    return status;
   5651}
   5652
   5653mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
   5654{
   5655    mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
   5656
   5657    if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
   5658        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5659
   5660    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
   5661    {
   5662        if (!pZip->m_pRead)
   5663            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5664    }
   5665
   5666    if (pZip->m_file_offset_alignment)
   5667    {
   5668        /* Ensure user specified file offset alignment is a power of 2. */
   5669        if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
   5670            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5671    }
   5672
   5673    if (!pZip->m_pAlloc)
   5674        pZip->m_pAlloc = miniz_def_alloc_func;
   5675    if (!pZip->m_pFree)
   5676        pZip->m_pFree = miniz_def_free_func;
   5677    if (!pZip->m_pRealloc)
   5678        pZip->m_pRealloc = miniz_def_realloc_func;
   5679
   5680    pZip->m_archive_size = existing_size;
   5681    pZip->m_central_directory_file_ofs = 0;
   5682    pZip->m_total_files = 0;
   5683
   5684    if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
   5685        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   5686
   5687    memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
   5688
   5689    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
   5690    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
   5691    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
   5692
   5693    pZip->m_pState->m_zip64 = zip64;
   5694    pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
   5695
   5696    pZip->m_zip_type = MZ_ZIP_TYPE_USER;
   5697    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
   5698
   5699    return MZ_TRUE;
   5700}
   5701
   5702mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
   5703{
   5704    return mz_zip_writer_init_v2(pZip, existing_size, 0);
   5705}
   5706
   5707mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
   5708{
   5709    pZip->m_pWrite = mz_zip_heap_write_func;
   5710    pZip->m_pNeeds_keepalive = NULL;
   5711
   5712    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
   5713        pZip->m_pRead = mz_zip_mem_read_func;
   5714
   5715    pZip->m_pIO_opaque = pZip;
   5716
   5717    if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
   5718        return MZ_FALSE;
   5719
   5720    pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
   5721
   5722    if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
   5723    {
   5724        if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
   5725        {
   5726            mz_zip_writer_end_internal(pZip, MZ_FALSE);
   5727            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   5728        }
   5729        pZip->m_pState->m_mem_capacity = initial_allocation_size;
   5730    }
   5731
   5732    return MZ_TRUE;
   5733}
   5734
   5735mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
   5736{
   5737    return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
   5738}
   5739
   5740#ifndef MINIZ_NO_STDIO
   5741static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
   5742{
   5743    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
   5744    mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
   5745
   5746    file_ofs += pZip->m_pState->m_file_archive_start_ofs;
   5747
   5748    if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
   5749    {
   5750        mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
   5751        return 0;
   5752    }
   5753
   5754    return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
   5755}
   5756
   5757mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
   5758{
   5759    return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
   5760}
   5761
   5762mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
   5763{
   5764    MZ_FILE *pFile;
   5765
   5766    pZip->m_pWrite = mz_zip_file_write_func;
   5767    pZip->m_pNeeds_keepalive = NULL;
   5768
   5769    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
   5770        pZip->m_pRead = mz_zip_file_read_func;
   5771
   5772    pZip->m_pIO_opaque = pZip;
   5773
   5774    if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
   5775        return MZ_FALSE;
   5776
   5777    if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
   5778    {
   5779        mz_zip_writer_end(pZip);
   5780        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
   5781    }
   5782
   5783    pZip->m_pState->m_pFile = pFile;
   5784    pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
   5785
   5786    if (size_to_reserve_at_beginning)
   5787    {
   5788        mz_uint64 cur_ofs = 0;
   5789        char buf[4096];
   5790
   5791        MZ_CLEAR_OBJ(buf);
   5792
   5793        do
   5794        {
   5795            size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
   5796            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
   5797            {
   5798                mz_zip_writer_end(pZip);
   5799                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   5800            }
   5801            cur_ofs += n;
   5802            size_to_reserve_at_beginning -= n;
   5803        } while (size_to_reserve_at_beginning);
   5804    }
   5805
   5806    return MZ_TRUE;
   5807}
   5808
   5809mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
   5810{
   5811    pZip->m_pWrite = mz_zip_file_write_func;
   5812    pZip->m_pNeeds_keepalive = NULL;
   5813
   5814    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
   5815        pZip->m_pRead = mz_zip_file_read_func;
   5816
   5817    pZip->m_pIO_opaque = pZip;
   5818
   5819    if (!mz_zip_writer_init_v2(pZip, 0, flags))
   5820        return MZ_FALSE;
   5821
   5822    pZip->m_pState->m_pFile = pFile;
   5823    pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
   5824    pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
   5825
   5826    return MZ_TRUE;
   5827}
   5828#endif /* #ifndef MINIZ_NO_STDIO */
   5829
   5830mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
   5831{
   5832    mz_zip_internal_state *pState;
   5833
   5834    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
   5835        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5836
   5837    if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
   5838    {
   5839        /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */
   5840        if (!pZip->m_pState->m_zip64)
   5841            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5842    }
   5843
   5844    /* No sense in trying to write to an archive that's already at the support max size */
   5845    if (pZip->m_pState->m_zip64)
   5846    {
   5847        if (pZip->m_total_files == MZ_UINT32_MAX)
   5848            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   5849    }
   5850    else
   5851    {
   5852        if (pZip->m_total_files == MZ_UINT16_MAX)
   5853            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   5854
   5855        if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
   5856            return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
   5857    }
   5858
   5859    pState = pZip->m_pState;
   5860
   5861    if (pState->m_pFile)
   5862    {
   5863#ifdef MINIZ_NO_STDIO
   5864        (void)pFilename;
   5865        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5866#else
   5867        if (pZip->m_pIO_opaque != pZip)
   5868            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5869
   5870        if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
   5871        {
   5872            if (!pFilename)
   5873                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5874
   5875            /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
   5876            if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
   5877            {
   5878                /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
   5879                mz_zip_reader_end_internal(pZip, MZ_FALSE);
   5880                return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
   5881            }
   5882        }
   5883
   5884        pZip->m_pWrite = mz_zip_file_write_func;
   5885        pZip->m_pNeeds_keepalive = NULL;
   5886#endif /* #ifdef MINIZ_NO_STDIO */
   5887    }
   5888    else if (pState->m_pMem)
   5889    {
   5890        /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
   5891        if (pZip->m_pIO_opaque != pZip)
   5892            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5893
   5894        pState->m_mem_capacity = pState->m_mem_size;
   5895        pZip->m_pWrite = mz_zip_heap_write_func;
   5896        pZip->m_pNeeds_keepalive = NULL;
   5897    }
   5898    /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
   5899    else if (!pZip->m_pWrite)
   5900        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   5901
   5902    /* Start writing new files at the archive's current central directory location. */
   5903    /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
   5904    pZip->m_archive_size = pZip->m_central_directory_file_ofs;
   5905    pZip->m_central_directory_file_ofs = 0;
   5906
   5907    /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
   5908    /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
   5909    /* TODO: We could easily maintain the sorted central directory offsets. */
   5910    mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
   5911
   5912    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
   5913
   5914    return MZ_TRUE;
   5915}
   5916
   5917mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
   5918{
   5919    return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
   5920}
   5921
   5922/* TODO: pArchive_name is a terrible name here! */
   5923mz_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)
   5924{
   5925    return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
   5926}
   5927
   5928typedef struct
   5929{
   5930    mz_zip_archive *m_pZip;
   5931    mz_uint64 m_cur_archive_file_ofs;
   5932    mz_uint64 m_comp_size;
   5933} mz_zip_writer_add_state;
   5934
   5935static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
   5936{
   5937    mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
   5938    if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
   5939        return MZ_FALSE;
   5940
   5941    pState->m_cur_archive_file_ofs += len;
   5942    pState->m_comp_size += len;
   5943    return MZ_TRUE;
   5944}
   5945
   5946#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
   5947#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
   5948static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
   5949{
   5950    mz_uint8 *pDst = pBuf;
   5951    mz_uint32 field_size = 0;
   5952
   5953    MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
   5954    MZ_WRITE_LE16(pDst + 2, 0);
   5955    pDst += sizeof(mz_uint16) * 2;
   5956
   5957    if (pUncomp_size)
   5958    {
   5959        MZ_WRITE_LE64(pDst, *pUncomp_size);
   5960        pDst += sizeof(mz_uint64);
   5961        field_size += sizeof(mz_uint64);
   5962    }
   5963
   5964    if (pComp_size)
   5965    {
   5966        MZ_WRITE_LE64(pDst, *pComp_size);
   5967        pDst += sizeof(mz_uint64);
   5968        field_size += sizeof(mz_uint64);
   5969    }
   5970
   5971    if (pLocal_header_ofs)
   5972    {
   5973        MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
   5974        pDst += sizeof(mz_uint64);
   5975        field_size += sizeof(mz_uint64);
   5976    }
   5977
   5978    MZ_WRITE_LE16(pBuf + 2, field_size);
   5979
   5980    return (mz_uint32)(pDst - pBuf);
   5981}
   5982
   5983static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
   5984{
   5985    (void)pZip;
   5986    memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
   5987    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
   5988    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
   5989    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
   5990    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
   5991    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
   5992    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
   5993    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
   5994    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
   5995    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
   5996    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
   5997    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
   5998    return MZ_TRUE;
   5999}
   6000
   6001static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,
   6002                                                       mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
   6003                                                       mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
   6004                                                       mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
   6005                                                       mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
   6006{
   6007    (void)pZip;
   6008    memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
   6009    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
   6010    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
   6011    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
   6012    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
   6013    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
   6014    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
   6015    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
   6016    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
   6017    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
   6018    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
   6019    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
   6020    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
   6021    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
   6022    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
   6023    return MZ_TRUE;
   6024}
   6025
   6026static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
   6027                                                const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
   6028                                                mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
   6029                                                mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
   6030                                                mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
   6031                                                const char *user_extra_data, mz_uint user_extra_data_len)
   6032{
   6033    mz_zip_internal_state *pState = pZip->m_pState;
   6034    mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
   6035    size_t orig_central_dir_size = pState->m_central_dir.m_size;
   6036    mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
   6037
   6038    if (!pZip->m_pState->m_zip64)
   6039    {
   6040        if (local_header_ofs > 0xFFFFFFFF)
   6041            return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
   6042    }
   6043
   6044    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
   6045    if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
   6046        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
   6047
   6048    if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(extra_size + user_extra_data_len), comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
   6049        return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6050
   6051    if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
   6052        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
   6053        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
   6054        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
   6055        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
   6056        (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
   6057    {
   6058        /* Try to resize the central directory array back into its original state. */
   6059        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   6060        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6061    }
   6062
   6063    return MZ_TRUE;
   6064}
   6065
   6066static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
   6067{
   6068    /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */
   6069    if (*pArchive_name == '/')
   6070        return MZ_FALSE;
   6071
   6072    /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
   6073
   6074    return MZ_TRUE;
   6075}
   6076
   6077static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
   6078{
   6079    mz_uint32 n;
   6080    if (!pZip->m_file_offset_alignment)
   6081        return 0;
   6082    n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
   6083    return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
   6084}
   6085
   6086static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
   6087{
   6088    char buf[4096];
   6089    memset(buf, 0, MZ_MIN(sizeof(buf), n));
   6090    while (n)
   6091    {
   6092        mz_uint32 s = MZ_MIN(sizeof(buf), n);
   6093        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
   6094            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6095
   6096        cur_file_ofs += s;
   6097        n -= s;
   6098    }
   6099    return MZ_TRUE;
   6100}
   6101
   6102mz_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,
   6103                                 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
   6104{
   6105    return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
   6106}
   6107
   6108mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
   6109                                    mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
   6110                                    const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
   6111{
   6112    mz_uint16 method = 0, dos_time = 0, dos_date = 0;
   6113    mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
   6114    mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
   6115    size_t archive_name_size;
   6116    mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
   6117    tdefl_compressor *pComp = NULL;
   6118    mz_bool store_data_uncompressed;
   6119    mz_zip_internal_state *pState;
   6120    mz_uint8 *pExtra_data = NULL;
   6121    mz_uint32 extra_size = 0;
   6122    mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
   6123    mz_uint16 bit_flags = 0;
   6124
   6125    if ((int)level_and_flags < 0)
   6126        level_and_flags = MZ_DEFAULT_LEVEL;
   6127
   6128    if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
   6129        bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
   6130
   6131    if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
   6132        bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
   6133
   6134    level = level_and_flags & 0xF;
   6135    store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
   6136
   6137    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
   6138        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6139
   6140    pState = pZip->m_pState;
   6141
   6142    if (pState->m_zip64)
   6143    {
   6144        if (pZip->m_total_files == MZ_UINT32_MAX)
   6145            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   6146    }
   6147    else
   6148    {
   6149        if (pZip->m_total_files == MZ_UINT16_MAX)
   6150        {
   6151            pState->m_zip64 = MZ_TRUE;
   6152            /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
   6153        }
   6154        if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
   6155        {
   6156            pState->m_zip64 = MZ_TRUE;
   6157            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
   6158        }
   6159    }
   6160
   6161    if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
   6162        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6163
   6164    if (!mz_zip_writer_validate_archive_name(pArchive_name))
   6165        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
   6166
   6167#ifndef MINIZ_NO_TIME
   6168    if (last_modified != NULL)
   6169    {
   6170        mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
   6171    }
   6172    else
   6173    {
   6174        MZ_TIME_T cur_time;
   6175        time(&cur_time);
   6176        mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
   6177    }
   6178#endif /* #ifndef MINIZ_NO_TIME */
   6179
   6180	if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
   6181	{
   6182		uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
   6183		uncomp_size = buf_size;
   6184		if (uncomp_size <= 3)
   6185		{
   6186			level = 0;
   6187			store_data_uncompressed = MZ_TRUE;
   6188		}
   6189	}
   6190
   6191    archive_name_size = strlen(pArchive_name);
   6192    if (archive_name_size > MZ_UINT16_MAX)
   6193        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
   6194
   6195    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
   6196
   6197    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
   6198    if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
   6199        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
   6200
   6201    if (!pState->m_zip64)
   6202    {
   6203        /* Bail early if the archive would obviously become too large */
   6204        if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
   6205			+ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
   6206			pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
   6207			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
   6208        {
   6209            pState->m_zip64 = MZ_TRUE;
   6210            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
   6211        }
   6212    }
   6213
   6214    if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
   6215    {
   6216        /* Set DOS Subdirectory attribute bit. */
   6217        ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
   6218
   6219        /* Subdirectories cannot contain data. */
   6220        if ((buf_size) || (uncomp_size))
   6221            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6222    }
   6223
   6224    /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */
   6225    if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
   6226        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6227
   6228    if ((!store_data_uncompressed) && (buf_size))
   6229    {
   6230        if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
   6231            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6232    }
   6233
   6234    if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
   6235    {
   6236        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6237        return MZ_FALSE;
   6238    }
   6239
   6240    local_dir_header_ofs += num_alignment_padding_bytes;
   6241    if (pZip->m_file_offset_alignment)
   6242    {
   6243        MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
   6244    }
   6245    cur_archive_file_ofs += num_alignment_padding_bytes;
   6246
   6247    MZ_CLEAR_OBJ(local_dir_header);
   6248
   6249    if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
   6250    {
   6251        method = MZ_DEFLATED;
   6252    }
   6253
   6254    if (pState->m_zip64)
   6255    {
   6256        if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
   6257        {
   6258            pExtra_data = extra_data;
   6259            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
   6260                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
   6261        }
   6262
   6263        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date))
   6264            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6265
   6266        if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
   6267            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6268
   6269        cur_archive_file_ofs += sizeof(local_dir_header);
   6270
   6271        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
   6272        {
   6273            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6274            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6275        }
   6276        cur_archive_file_ofs += archive_name_size;
   6277
   6278        if (pExtra_data != NULL)
   6279        {
   6280            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
   6281                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6282
   6283            cur_archive_file_ofs += extra_size;
   6284        }
   6285    }
   6286    else
   6287    {
   6288        if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
   6289            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   6290        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
   6291            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6292
   6293        if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
   6294            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6295
   6296        cur_archive_file_ofs += sizeof(local_dir_header);
   6297
   6298        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
   6299        {
   6300            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6301            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6302        }
   6303        cur_archive_file_ofs += archive_name_size;
   6304    }
   6305
   6306	if (user_extra_data_len > 0)
   6307	{
   6308		if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
   6309			return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6310
   6311		cur_archive_file_ofs += user_extra_data_len;
   6312	}
   6313
   6314    if (store_data_uncompressed)
   6315    {
   6316        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
   6317        {
   6318            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6319            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6320        }
   6321
   6322        cur_archive_file_ofs += buf_size;
   6323        comp_size = buf_size;
   6324    }
   6325    else if (buf_size)
   6326    {
   6327        mz_zip_writer_add_state state;
   6328
   6329        state.m_pZip = pZip;
   6330        state.m_cur_archive_file_ofs = cur_archive_file_ofs;
   6331        state.m_comp_size = 0;
   6332
   6333        if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
   6334            (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
   6335        {
   6336            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6337            return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
   6338        }
   6339
   6340        comp_size = state.m_comp_size;
   6341        cur_archive_file_ofs = state.m_cur_archive_file_ofs;
   6342    }
   6343
   6344    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6345    pComp = NULL;
   6346
   6347    if (uncomp_size)
   6348    {
   6349        mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
   6350        mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
   6351
   6352        MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
   6353
   6354        MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
   6355        MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
   6356        if (pExtra_data == NULL)
   6357        {
   6358            if (comp_size > MZ_UINT32_MAX)
   6359                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   6360
   6361            MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
   6362            MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
   6363        }
   6364        else
   6365        {
   6366            MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
   6367            MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
   6368            local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
   6369        }
   6370
   6371        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
   6372            return MZ_FALSE;
   6373
   6374        cur_archive_file_ofs += local_dir_footer_size;
   6375    }
   6376
   6377    if (pExtra_data != NULL)
   6378    {
   6379        extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
   6380                                                           (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
   6381    }
   6382
   6383    if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
   6384                                          comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
   6385                                          user_extra_data_central, user_extra_data_central_len))
   6386        return MZ_FALSE;
   6387
   6388    pZip->m_total_files++;
   6389    pZip->m_archive_size = cur_archive_file_ofs;
   6390
   6391    return MZ_TRUE;
   6392}
   6393
   6394mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
   6395                                const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
   6396{
   6397    mz_uint16 gen_flags = (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) ? 0 : MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
   6398    mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
   6399    mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
   6400    mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
   6401    size_t archive_name_size;
   6402    mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
   6403    mz_uint8 *pExtra_data = NULL;
   6404    mz_uint32 extra_size = 0;
   6405    mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
   6406    mz_zip_internal_state *pState;
   6407    mz_uint64 file_ofs = 0, cur_archive_header_file_ofs;
   6408
   6409    if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
   6410        gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
   6411
   6412    if ((int)level_and_flags < 0)
   6413        level_and_flags = MZ_DEFAULT_LEVEL;
   6414    level = level_and_flags & 0xF;
   6415
   6416    /* Sanity checks */
   6417    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
   6418        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6419
   6420    pState = pZip->m_pState;
   6421
   6422    if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX))
   6423    {
   6424        /* Source file is too large for non-zip64 */
   6425        /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
   6426        pState->m_zip64 = MZ_TRUE;
   6427    }
   6428
   6429    /* We could support this, but why? */
   6430    if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
   6431        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6432
   6433    if (!mz_zip_writer_validate_archive_name(pArchive_name))
   6434        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
   6435
   6436    if (pState->m_zip64)
   6437    {
   6438        if (pZip->m_total_files == MZ_UINT32_MAX)
   6439            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   6440    }
   6441    else
   6442    {
   6443        if (pZip->m_total_files == MZ_UINT16_MAX)
   6444        {
   6445            pState->m_zip64 = MZ_TRUE;
   6446            /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
   6447        }
   6448    }
   6449
   6450    archive_name_size = strlen(pArchive_name);
   6451    if (archive_name_size > MZ_UINT16_MAX)
   6452        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
   6453
   6454    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
   6455
   6456    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
   6457    if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
   6458        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
   6459
   6460    if (!pState->m_zip64)
   6461    {
   6462        /* Bail early if the archive would obviously become too large */
   6463        if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
   6464			+ archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
   6465			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
   6466        {
   6467            pState->m_zip64 = MZ_TRUE;
   6468            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
   6469        }
   6470    }
   6471
   6472#ifndef MINIZ_NO_TIME
   6473    if (pFile_time)
   6474    {
   6475        mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
   6476    }
   6477#endif
   6478
   6479    if (max_size <= 3)
   6480        level = 0;
   6481
   6482    if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
   6483    {
   6484        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6485    }
   6486
   6487    cur_archive_file_ofs += num_alignment_padding_bytes;
   6488    local_dir_header_ofs = cur_archive_file_ofs;
   6489
   6490    if (pZip->m_file_offset_alignment)
   6491    {
   6492        MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
   6493    }
   6494
   6495    if (max_size && level)
   6496    {
   6497        method = MZ_DEFLATED;
   6498    }
   6499
   6500    MZ_CLEAR_OBJ(local_dir_header);
   6501    if (pState->m_zip64)
   6502    {
   6503        if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
   6504        {
   6505            pExtra_data = extra_data;
   6506            if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
   6507                extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
   6508                                                               (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
   6509                                                                (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
   6510            else
   6511                extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, NULL,
   6512                                                                   NULL,
   6513                                                                   (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
   6514        }
   6515
   6516        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date))
   6517            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6518
   6519        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
   6520            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6521
   6522        cur_archive_file_ofs += sizeof(local_dir_header);
   6523
   6524        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
   6525        {
   6526            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6527        }
   6528
   6529        cur_archive_file_ofs += archive_name_size;
   6530
   6531        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
   6532            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6533
   6534        cur_archive_file_ofs += extra_size;
   6535    }
   6536    else
   6537    {
   6538        if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
   6539            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   6540        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
   6541            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6542
   6543        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
   6544            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6545
   6546        cur_archive_file_ofs += sizeof(local_dir_header);
   6547
   6548        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
   6549        {
   6550            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6551        }
   6552
   6553        cur_archive_file_ofs += archive_name_size;
   6554    }
   6555
   6556    if (user_extra_data_len > 0)
   6557    {
   6558        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
   6559            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6560
   6561        cur_archive_file_ofs += user_extra_data_len;
   6562    }
   6563
   6564    if (max_size)
   6565    {
   6566        void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
   6567        if (!pRead_buf)
   6568        {
   6569            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6570        }
   6571
   6572        if (!level)
   6573        {
   6574            while (1)
   6575            {
   6576                size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
   6577                if (n == 0)
   6578                    break;
   6579
   6580                if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
   6581                {
   6582                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   6583                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   6584                }
   6585                if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)
   6586                {
   6587                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   6588                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6589                }
   6590                file_ofs += n;
   6591                uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
   6592                cur_archive_file_ofs += n;
   6593            }
   6594            uncomp_size = file_ofs;
   6595            comp_size = uncomp_size;
   6596        }
   6597        else
   6598        {
   6599            mz_bool result = MZ_FALSE;
   6600            mz_zip_writer_add_state state;
   6601            tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
   6602            if (!pComp)
   6603            {
   6604                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   6605                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6606            }
   6607
   6608            state.m_pZip = pZip;
   6609            state.m_cur_archive_file_ofs = cur_archive_file_ofs;
   6610            state.m_comp_size = 0;
   6611
   6612            if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
   6613            {
   6614                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6615                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   6616                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6617            }
   6618
   6619            for (;;)
   6620            {
   6621                tdefl_status status;
   6622                tdefl_flush flush = TDEFL_NO_FLUSH;
   6623
   6624                size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
   6625                if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
   6626                {
   6627                    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   6628                    break;
   6629                }
   6630
   6631                file_ofs += n;
   6632                uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
   6633
   6634                if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
   6635                    flush = TDEFL_FULL_FLUSH;
   6636
   6637                if (n == 0)
   6638                    flush = TDEFL_FINISH;
   6639
   6640                status = tdefl_compress_buffer(pComp, pRead_buf, n, flush);
   6641                if (status == TDEFL_STATUS_DONE)
   6642                {
   6643                    result = MZ_TRUE;
   6644                    break;
   6645                }
   6646                else if (status != TDEFL_STATUS_OKAY)
   6647                {
   6648                    mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
   6649                    break;
   6650                }
   6651            }
   6652
   6653            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
   6654
   6655            if (!result)
   6656            {
   6657                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   6658                return MZ_FALSE;
   6659            }
   6660
   6661            uncomp_size = file_ofs;
   6662            comp_size = state.m_comp_size;
   6663            cur_archive_file_ofs = state.m_cur_archive_file_ofs;
   6664        }
   6665
   6666        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
   6667    }
   6668
   6669    if (!(level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE))
   6670    {
   6671        mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
   6672        mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
   6673
   6674        MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
   6675        MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
   6676        if (pExtra_data == NULL)
   6677        {
   6678            if (comp_size > MZ_UINT32_MAX)
   6679                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   6680
   6681            MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
   6682            MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
   6683        }
   6684        else
   6685        {
   6686            MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
   6687            MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
   6688            local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
   6689        }
   6690
   6691        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
   6692            return MZ_FALSE;
   6693
   6694        cur_archive_file_ofs += local_dir_footer_size;
   6695    }
   6696
   6697    if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
   6698    {
   6699        if (pExtra_data != NULL)
   6700        {
   6701            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
   6702                                                               (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
   6703        }
   6704
   6705        if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header,
   6706                                                   (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len),
   6707                                                   (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size, 
   6708                                                    (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size,
   6709                                                   uncomp_crc32, method, gen_flags, dos_time, dos_date))
   6710            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
   6711
   6712        cur_archive_header_file_ofs = local_dir_header_ofs;
   6713
   6714        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
   6715            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6716
   6717        if (pExtra_data != NULL)
   6718        {
   6719            cur_archive_header_file_ofs += sizeof(local_dir_header);
   6720
   6721            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
   6722            {
   6723                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6724            }
   6725
   6726            cur_archive_header_file_ofs += archive_name_size;
   6727
   6728            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, extra_data, extra_size) != extra_size)
   6729                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   6730
   6731            cur_archive_header_file_ofs += extra_size;
   6732        }
   6733    }
   6734
   6735    if (pExtra_data != NULL)
   6736    {
   6737        extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
   6738                                                           (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
   6739    }
   6740
   6741    if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size,
   6742                                          uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
   6743                                          user_extra_data_central, user_extra_data_central_len))
   6744        return MZ_FALSE;
   6745
   6746    pZip->m_total_files++;
   6747    pZip->m_archive_size = cur_archive_file_ofs;
   6748
   6749    return MZ_TRUE;
   6750}
   6751
   6752#ifndef MINIZ_NO_STDIO
   6753
   6754static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
   6755{
   6756	MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
   6757	mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
   6758
   6759	if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
   6760		return 0;
   6761
   6762	return MZ_FREAD(pBuf, 1, n, pSrc_file);
   6763}
   6764
   6765mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
   6766	const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
   6767{
   6768	return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, max_size, pFile_time, pComment, comment_size, level_and_flags,
   6769		user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
   6770}
   6771
   6772mz_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)
   6773{
   6774    MZ_FILE *pSrc_file = NULL;
   6775    mz_uint64 uncomp_size = 0;
   6776    MZ_TIME_T file_modified_time;
   6777    MZ_TIME_T *pFile_time = NULL;
   6778    mz_bool status;
   6779
   6780    memset(&file_modified_time, 0, sizeof(file_modified_time));
   6781
   6782#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
   6783    pFile_time = &file_modified_time;
   6784    if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
   6785        return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
   6786#endif
   6787
   6788    pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
   6789    if (!pSrc_file)
   6790        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
   6791
   6792    MZ_FSEEK64(pSrc_file, 0, SEEK_END);
   6793    uncomp_size = MZ_FTELL64(pSrc_file);
   6794    MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
   6795
   6796    status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);
   6797
   6798    MZ_FCLOSE(pSrc_file);
   6799
   6800    return status;
   6801}
   6802#endif /* #ifndef MINIZ_NO_STDIO */
   6803
   6804static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
   6805{
   6806    /* + 64 should be enough for any new zip64 data */
   6807    if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
   6808        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6809
   6810    mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
   6811
   6812    if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
   6813    {
   6814        mz_uint8 new_ext_block[64];
   6815        mz_uint8 *pDst = new_ext_block;
   6816        mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
   6817        mz_write_le16(pDst + sizeof(mz_uint16), 0);
   6818        pDst += sizeof(mz_uint16) * 2;
   6819
   6820        if (pUncomp_size)
   6821        {
   6822            mz_write_le64(pDst, *pUncomp_size);
   6823            pDst += sizeof(mz_uint64);
   6824        }
   6825
   6826        if (pComp_size)
   6827        {
   6828            mz_write_le64(pDst, *pComp_size);
   6829            pDst += sizeof(mz_uint64);
   6830        }
   6831
   6832        if (pLocal_header_ofs)
   6833        {
   6834            mz_write_le64(pDst, *pLocal_header_ofs);
   6835            pDst += sizeof(mz_uint64);
   6836        }
   6837
   6838        if (pDisk_start)
   6839        {
   6840            mz_write_le32(pDst, *pDisk_start);
   6841            pDst += sizeof(mz_uint32);
   6842        }
   6843
   6844        mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
   6845
   6846        if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
   6847            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6848    }
   6849
   6850    if ((pExt) && (ext_len))
   6851    {
   6852        mz_uint32 extra_size_remaining = ext_len;
   6853        const mz_uint8 *pExtra_data = pExt;
   6854
   6855        do
   6856        {
   6857            mz_uint32 field_id, field_data_size, field_total_size;
   6858
   6859            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
   6860                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   6861
   6862            field_id = MZ_READ_LE16(pExtra_data);
   6863            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
   6864            field_total_size = field_data_size + sizeof(mz_uint16) * 2;
   6865
   6866            if (field_total_size > extra_size_remaining)
   6867                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   6868
   6869            if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
   6870            {
   6871                if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
   6872                    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6873            }
   6874
   6875            pExtra_data += field_total_size;
   6876            extra_size_remaining -= field_total_size;
   6877        } while (extra_size_remaining);
   6878    }
   6879
   6880    return MZ_TRUE;
   6881}
   6882
   6883/* TODO: This func is now pretty freakin complex due to zip64, split it up? */
   6884mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
   6885{
   6886    mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
   6887    mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
   6888    mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
   6889    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
   6890    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
   6891    mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
   6892    size_t orig_central_dir_size;
   6893    mz_zip_internal_state *pState;
   6894    void *pBuf;
   6895    const mz_uint8 *pSrc_central_header;
   6896    mz_zip_archive_file_stat src_file_stat;
   6897    mz_uint32 src_filename_len, src_comment_len, src_ext_len;
   6898    mz_uint32 local_header_filename_size, local_header_extra_len;
   6899    mz_uint64 local_header_comp_size, local_header_uncomp_size;
   6900    mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
   6901
   6902    /* Sanity checks */
   6903    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
   6904        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6905
   6906    pState = pZip->m_pState;
   6907
   6908    /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
   6909    if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
   6910        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6911
   6912    /* Get pointer to the source central dir header and crack it */
   6913    if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
   6914        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   6915
   6916    if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
   6917        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   6918
   6919    src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   6920    src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
   6921    src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
   6922    src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
   6923
   6924    /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */
   6925    if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
   6926        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
   6927
   6928    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
   6929
   6930    if (!pState->m_zip64)
   6931    {
   6932        if (pZip->m_total_files == MZ_UINT16_MAX)
   6933            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   6934    }
   6935    else
   6936    {
   6937        /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
   6938        if (pZip->m_total_files == MZ_UINT32_MAX)
   6939            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   6940    }
   6941
   6942    if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
   6943        return MZ_FALSE;
   6944
   6945    cur_src_file_ofs = src_file_stat.m_local_header_ofs;
   6946    cur_dst_file_ofs = pZip->m_archive_size;
   6947
   6948    /* Read the source archive's local dir header */
   6949    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
   6950        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   6951
   6952    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
   6953        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   6954
   6955    cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
   6956
   6957    /* Compute the total size we need to copy (filename+extra data+compressed data) */
   6958    local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
   6959    local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
   6960    local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
   6961    local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
   6962    src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
   6963
   6964    /* Try to find a zip64 extended information field */
   6965    if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
   6966    {
   6967        mz_zip_array file_data_array;
   6968        const mz_uint8 *pExtra_data;
   6969        mz_uint32 extra_size_remaining = local_header_extra_len;
   6970
   6971        mz_zip_array_init(&file_data_array, 1);
   6972        if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
   6973        {
   6974            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   6975        }
   6976
   6977        if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
   6978        {
   6979            mz_zip_array_clear(pZip, &file_data_array);
   6980            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   6981        }
   6982
   6983        pExtra_data = (const mz_uint8 *)file_data_array.m_p;
   6984
   6985        do
   6986        {
   6987            mz_uint32 field_id, field_data_size, field_total_size;
   6988
   6989            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
   6990            {
   6991                mz_zip_array_clear(pZip, &file_data_array);
   6992                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   6993            }
   6994
   6995            field_id = MZ_READ_LE16(pExtra_data);
   6996            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
   6997            field_total_size = field_data_size + sizeof(mz_uint16) * 2;
   6998
   6999            if (field_total_size > extra_size_remaining)
   7000            {
   7001                mz_zip_array_clear(pZip, &file_data_array);
   7002                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   7003            }
   7004
   7005            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
   7006            {
   7007                const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
   7008
   7009                if (field_data_size < sizeof(mz_uint64) * 2)
   7010                {
   7011                    mz_zip_array_clear(pZip, &file_data_array);
   7012                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
   7013                }
   7014
   7015                local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
   7016                local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
   7017
   7018                found_zip64_ext_data_in_ldir = MZ_TRUE;
   7019                break;
   7020            }
   7021
   7022            pExtra_data += field_total_size;
   7023            extra_size_remaining -= field_total_size;
   7024        } while (extra_size_remaining);
   7025
   7026        mz_zip_array_clear(pZip, &file_data_array);
   7027    }
   7028
   7029    if (!pState->m_zip64)
   7030    {
   7031        /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */
   7032        /* We also check when the archive is finalized so this doesn't need to be perfect. */
   7033        mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +
   7034                                            pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
   7035
   7036        if (approx_new_archive_size >= MZ_UINT32_MAX)
   7037            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   7038    }
   7039
   7040    /* Write dest archive padding */
   7041    if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
   7042        return MZ_FALSE;
   7043
   7044    cur_dst_file_ofs += num_alignment_padding_bytes;
   7045
   7046    local_dir_header_ofs = cur_dst_file_ofs;
   7047    if (pZip->m_file_offset_alignment)
   7048    {
   7049        MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
   7050    }
   7051
   7052    /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */
   7053    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
   7054        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7055
   7056    cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
   7057
   7058    /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
   7059    if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
   7060        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7061
   7062    while (src_archive_bytes_remaining)
   7063    {
   7064        n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
   7065        if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
   7066        {
   7067            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   7068            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   7069        }
   7070        cur_src_file_ofs += n;
   7071
   7072        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
   7073        {
   7074            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   7075            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7076        }
   7077        cur_dst_file_ofs += n;
   7078
   7079        src_archive_bytes_remaining -= n;
   7080    }
   7081
   7082    /* Now deal with the optional data descriptor */
   7083    bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
   7084    if (bit_flags & 8)
   7085    {
   7086        /* Copy data descriptor */
   7087        if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
   7088        {
   7089            /* src is zip64, dest must be zip64 */
   7090
   7091            /* name			uint32_t's */
   7092            /* id				1 (optional in zip64?) */
   7093            /* crc			1 */
   7094            /* comp_size	2 */
   7095            /* uncomp_size 2 */
   7096            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
   7097            {
   7098                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   7099                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   7100            }
   7101
   7102            n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
   7103        }
   7104        else
   7105        {
   7106            /* src is NOT zip64 */
   7107            mz_bool has_id;
   7108
   7109            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
   7110            {
   7111                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   7112                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
   7113            }
   7114
   7115            has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
   7116
   7117            if (pZip->m_pState->m_zip64)
   7118            {
   7119                /* dest is zip64, so upgrade the data descriptor */
   7120                const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
   7121                const mz_uint32 src_crc32 = pSrc_descriptor[0];
   7122                const mz_uint64 src_comp_size = pSrc_descriptor[1];
   7123                const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
   7124
   7125                mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
   7126                mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
   7127                mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
   7128                mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
   7129
   7130                n = sizeof(mz_uint32) * 6;
   7131            }
   7132            else
   7133            {
   7134                /* dest is NOT zip64, just copy it as-is */
   7135                n = sizeof(mz_uint32) * (has_id ? 4 : 3);
   7136            }
   7137        }
   7138
   7139        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
   7140        {
   7141            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   7142            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7143        }
   7144
   7145        cur_src_file_ofs += n;
   7146        cur_dst_file_ofs += n;
   7147    }
   7148    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
   7149
   7150    /* Finally, add the new central dir header */
   7151    orig_central_dir_size = pState->m_central_dir.m_size;
   7152
   7153    memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
   7154
   7155    if (pState->m_zip64)
   7156    {
   7157        /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */
   7158        const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
   7159        mz_zip_array new_ext_block;
   7160
   7161        mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
   7162
   7163        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
   7164        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
   7165        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
   7166
   7167        if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))
   7168        {
   7169            mz_zip_array_clear(pZip, &new_ext_block);
   7170            return MZ_FALSE;
   7171        }
   7172
   7173        MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
   7174
   7175        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
   7176        {
   7177            mz_zip_array_clear(pZip, &new_ext_block);
   7178            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7179        }
   7180
   7181        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
   7182        {
   7183            mz_zip_array_clear(pZip, &new_ext_block);
   7184            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   7185            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7186        }
   7187
   7188        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
   7189        {
   7190            mz_zip_array_clear(pZip, &new_ext_block);
   7191            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   7192            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7193        }
   7194
   7195        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))
   7196        {
   7197            mz_zip_array_clear(pZip, &new_ext_block);
   7198            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   7199            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7200        }
   7201
   7202        mz_zip_array_clear(pZip, &new_ext_block);
   7203    }
   7204    else
   7205    {
   7206        /* sanity checks */
   7207        if (cur_dst_file_ofs > MZ_UINT32_MAX)
   7208            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   7209
   7210        if (local_dir_header_ofs >= MZ_UINT32_MAX)
   7211            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
   7212
   7213        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
   7214
   7215        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
   7216            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7217
   7218        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))
   7219        {
   7220            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   7221            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7222        }
   7223    }
   7224
   7225    /* This shouldn't trigger unless we screwed up during the initial sanity checks */
   7226    if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
   7227    {
   7228        /* TODO: Support central dirs >= 32-bits in size */
   7229        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   7230        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
   7231    }
   7232
   7233    n = (mz_uint32)orig_central_dir_size;
   7234    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
   7235    {
   7236        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
   7237        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
   7238    }
   7239
   7240    pZip->m_total_files++;
   7241    pZip->m_archive_size = cur_dst_file_ofs;
   7242
   7243    return MZ_TRUE;
   7244}
   7245
   7246mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
   7247{
   7248    mz_zip_internal_state *pState;
   7249    mz_uint64 central_dir_ofs, central_dir_size;
   7250    mz_uint8 hdr[256];
   7251
   7252    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
   7253        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   7254
   7255    pState = pZip->m_pState;
   7256
   7257    if (pState->m_zip64)
   7258    {
   7259        if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
   7260            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   7261    }
   7262    else
   7263    {
   7264        if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))
   7265            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
   7266    }
   7267
   7268    central_dir_ofs = 0;
   7269    central_dir_size = 0;
   7270    if (pZip->m_total_files)
   7271    {
   7272        /* Write central directory */
   7273        central_dir_ofs = pZip->m_archive_size;
   7274        central_dir_size = pState->m_central_dir.m_size;
   7275        pZip->m_central_directory_file_ofs = central_dir_ofs;
   7276        if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
   7277            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7278
   7279        pZip->m_archive_size += central_dir_size;
   7280    }
   7281
   7282    if (pState->m_zip64)
   7283    {
   7284        /* Write zip64 end of central directory header */
   7285        mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
   7286
   7287        MZ_CLEAR_OBJ(hdr);
   7288        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
   7289        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64));
   7290        MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
   7291        MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
   7292        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
   7293        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
   7294        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
   7295        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
   7296        if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
   7297            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7298
   7299        pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
   7300
   7301        /* Write zip64 end of central directory locator */
   7302        MZ_CLEAR_OBJ(hdr);
   7303        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
   7304        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
   7305        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
   7306        if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
   7307            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7308
   7309        pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
   7310    }
   7311
   7312    /* Write end of central directory record */
   7313    MZ_CLEAR_OBJ(hdr);
   7314    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
   7315    MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
   7316    MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
   7317    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
   7318    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
   7319
   7320    if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
   7321        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
   7322
   7323#ifndef MINIZ_NO_STDIO
   7324    if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
   7325        return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
   7326#endif /* #ifndef MINIZ_NO_STDIO */
   7327
   7328    pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
   7329
   7330    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
   7331    return MZ_TRUE;
   7332}
   7333
   7334mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
   7335{
   7336    if ((!ppBuf) || (!pSize))
   7337        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   7338
   7339    *ppBuf = NULL;
   7340    *pSize = 0;
   7341
   7342    if ((!pZip) || (!pZip->m_pState))
   7343        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   7344
   7345    if (pZip->m_pWrite != mz_zip_heap_write_func)
   7346        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   7347
   7348    if (!mz_zip_writer_finalize_archive(pZip))
   7349        return MZ_FALSE;
   7350
   7351    *ppBuf = pZip->m_pState->m_pMem;
   7352    *pSize = pZip->m_pState->m_mem_size;
   7353    pZip->m_pState->m_pMem = NULL;
   7354    pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
   7355
   7356    return MZ_TRUE;
   7357}
   7358
   7359mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
   7360{
   7361    return mz_zip_writer_end_internal(pZip, MZ_TRUE);
   7362}
   7363
   7364#ifndef MINIZ_NO_STDIO
   7365mz_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)
   7366{
   7367    return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);
   7368}
   7369
   7370mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(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, mz_zip_error *pErr)
   7371{
   7372    mz_bool status, created_new_archive = MZ_FALSE;
   7373    mz_zip_archive zip_archive;
   7374    struct MZ_FILE_STAT_STRUCT file_stat;
   7375    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
   7376
   7377    mz_zip_zero_struct(&zip_archive);
   7378    if ((int)level_and_flags < 0)
   7379        level_and_flags = MZ_DEFAULT_LEVEL;
   7380
   7381    if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
   7382    {
   7383        if (pErr)
   7384            *pErr = MZ_ZIP_INVALID_PARAMETER;
   7385        return MZ_FALSE;
   7386    }
   7387
   7388    if (!mz_zip_writer_validate_archive_name(pArchive_name))
   7389    {
   7390        if (pErr)
   7391            *pErr = MZ_ZIP_INVALID_FILENAME;
   7392        return MZ_FALSE;
   7393    }
   7394
   7395    /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */
   7396    /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
   7397    if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
   7398    {
   7399        /* Create a new archive. */
   7400        if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
   7401        {
   7402            if (pErr)
   7403                *pErr = zip_archive.m_last_error;
   7404            return MZ_FALSE;
   7405        }
   7406
   7407        created_new_archive = MZ_TRUE;
   7408    }
   7409    else
   7410    {
   7411        /* Append to an existing archive. */
   7412        if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
   7413        {
   7414            if (pErr)
   7415                *pErr = zip_archive.m_last_error;
   7416            return MZ_FALSE;
   7417        }
   7418
   7419        if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
   7420        {
   7421            if (pErr)
   7422                *pErr = zip_archive.m_last_error;
   7423
   7424            mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
   7425
   7426            return MZ_FALSE;
   7427        }
   7428    }
   7429
   7430    status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
   7431    actual_err = zip_archive.m_last_error;
   7432
   7433    /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */
   7434    if (!mz_zip_writer_finalize_archive(&zip_archive))
   7435    {
   7436        if (!actual_err)
   7437            actual_err = zip_archive.m_last_error;
   7438
   7439        status = MZ_FALSE;
   7440    }
   7441
   7442    if (!mz_zip_writer_end_internal(&zip_archive, status))
   7443    {
   7444        if (!actual_err)
   7445            actual_err = zip_archive.m_last_error;
   7446
   7447        status = MZ_FALSE;
   7448    }
   7449
   7450    if ((!status) && (created_new_archive))
   7451    {
   7452        /* It's a new archive and something went wrong, so just delete it. */
   7453        int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
   7454        (void)ignoredStatus;
   7455    }
   7456
   7457    if (pErr)
   7458        *pErr = actual_err;
   7459
   7460    return status;
   7461}
   7462
   7463void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
   7464{
   7465    mz_uint32 file_index;
   7466    mz_zip_archive zip_archive;
   7467    void *p = NULL;
   7468
   7469    if (pSize)
   7470        *pSize = 0;
   7471
   7472    if ((!pZip_filename) || (!pArchive_name))
   7473    {
   7474        if (pErr)
   7475            *pErr = MZ_ZIP_INVALID_PARAMETER;
   7476
   7477        return NULL;
   7478    }
   7479
   7480    mz_zip_zero_struct(&zip_archive);
   7481    if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
   7482    {
   7483        if (pErr)
   7484            *pErr = zip_archive.m_last_error;
   7485
   7486        return NULL;
   7487    }
   7488
   7489    if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
   7490    {
   7491        p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
   7492    }
   7493
   7494    mz_zip_reader_end_internal(&zip_archive, p != NULL);
   7495
   7496    if (pErr)
   7497        *pErr = zip_archive.m_last_error;
   7498
   7499    return p;
   7500}
   7501
   7502void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
   7503{
   7504    return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
   7505}
   7506
   7507#endif /* #ifndef MINIZ_NO_STDIO */
   7508
   7509#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
   7510
   7511/* ------------------- Misc utils */
   7512
   7513mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
   7514{
   7515    return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
   7516}
   7517
   7518mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
   7519{
   7520    return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
   7521}
   7522
   7523mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
   7524{
   7525    mz_zip_error prev_err;
   7526
   7527    if (!pZip)
   7528        return MZ_ZIP_INVALID_PARAMETER;
   7529
   7530    prev_err = pZip->m_last_error;
   7531
   7532    pZip->m_last_error = err_num;
   7533    return prev_err;
   7534}
   7535
   7536mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
   7537{
   7538    if (!pZip)
   7539        return MZ_ZIP_INVALID_PARAMETER;
   7540
   7541    return pZip->m_last_error;
   7542}
   7543
   7544mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
   7545{
   7546    return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
   7547}
   7548
   7549mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
   7550{
   7551    mz_zip_error prev_err;
   7552
   7553    if (!pZip)
   7554        return MZ_ZIP_INVALID_PARAMETER;
   7555
   7556    prev_err = pZip->m_last_error;
   7557
   7558    pZip->m_last_error = MZ_ZIP_NO_ERROR;
   7559    return prev_err;
   7560}
   7561
   7562const char *mz_zip_get_error_string(mz_zip_error mz_err)
   7563{
   7564    switch (mz_err)
   7565    {
   7566        case MZ_ZIP_NO_ERROR:
   7567            return "no error";
   7568        case MZ_ZIP_UNDEFINED_ERROR:
   7569            return "undefined error";
   7570        case MZ_ZIP_TOO_MANY_FILES:
   7571            return "too many files";
   7572        case MZ_ZIP_FILE_TOO_LARGE:
   7573            return "file too large";
   7574        case MZ_ZIP_UNSUPPORTED_METHOD:
   7575            return "unsupported method";
   7576        case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
   7577            return "unsupported encryption";
   7578        case MZ_ZIP_UNSUPPORTED_FEATURE:
   7579            return "unsupported feature";
   7580        case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
   7581            return "failed finding central directory";
   7582        case MZ_ZIP_NOT_AN_ARCHIVE:
   7583            return "not a ZIP archive";
   7584        case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
   7585            return "invalid header or archive is corrupted";
   7586        case MZ_ZIP_UNSUPPORTED_MULTIDISK:
   7587            return "unsupported multidisk archive";
   7588        case MZ_ZIP_DECOMPRESSION_FAILED:
   7589            return "decompression failed or archive is corrupted";
   7590        case MZ_ZIP_COMPRESSION_FAILED:
   7591            return "compression failed";
   7592        case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
   7593            return "unexpected decompressed size";
   7594        case MZ_ZIP_CRC_CHECK_FAILED:
   7595            return "CRC-32 check failed";
   7596        case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
   7597            return "unsupported central directory size";
   7598        case MZ_ZIP_ALLOC_FAILED:
   7599            return "allocation failed";
   7600        case MZ_ZIP_FILE_OPEN_FAILED:
   7601            return "file open failed";
   7602        case MZ_ZIP_FILE_CREATE_FAILED:
   7603            return "file create failed";
   7604        case MZ_ZIP_FILE_WRITE_FAILED:
   7605            return "file write failed";
   7606        case MZ_ZIP_FILE_READ_FAILED:
   7607            return "file read failed";
   7608        case MZ_ZIP_FILE_CLOSE_FAILED:
   7609            return "file close failed";
   7610        case MZ_ZIP_FILE_SEEK_FAILED:
   7611            return "file seek failed";
   7612        case MZ_ZIP_FILE_STAT_FAILED:
   7613            return "file stat failed";
   7614        case MZ_ZIP_INVALID_PARAMETER:
   7615            return "invalid parameter";
   7616        case MZ_ZIP_INVALID_FILENAME:
   7617            return "invalid filename";
   7618        case MZ_ZIP_BUF_TOO_SMALL:
   7619            return "buffer too small";
   7620        case MZ_ZIP_INTERNAL_ERROR:
   7621            return "internal error";
   7622        case MZ_ZIP_FILE_NOT_FOUND:
   7623            return "file not found";
   7624        case MZ_ZIP_ARCHIVE_TOO_LARGE:
   7625            return "archive is too large";
   7626        case MZ_ZIP_VALIDATION_FAILED:
   7627            return "validation failed";
   7628        case MZ_ZIP_WRITE_CALLBACK_FAILED:
   7629            return "write calledback failed";
   7630        default:
   7631            break;
   7632    }
   7633
   7634    return "unknown error";
   7635}
   7636
   7637/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
   7638mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
   7639{
   7640    if ((!pZip) || (!pZip->m_pState))
   7641        return MZ_FALSE;
   7642
   7643    return pZip->m_pState->m_zip64;
   7644}
   7645
   7646size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
   7647{
   7648    if ((!pZip) || (!pZip->m_pState))
   7649        return 0;
   7650
   7651    return pZip->m_pState->m_central_dir.m_size;
   7652}
   7653
   7654mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
   7655{
   7656    return pZip ? pZip->m_total_files : 0;
   7657}
   7658
   7659mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
   7660{
   7661    if (!pZip)
   7662        return 0;
   7663    return pZip->m_archive_size;
   7664}
   7665
   7666mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
   7667{
   7668    if ((!pZip) || (!pZip->m_pState))
   7669        return 0;
   7670    return pZip->m_pState->m_file_archive_start_ofs;
   7671}
   7672
   7673MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
   7674{
   7675    if ((!pZip) || (!pZip->m_pState))
   7676        return 0;
   7677    return pZip->m_pState->m_pFile;
   7678}
   7679
   7680size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
   7681{
   7682    if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
   7683        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   7684
   7685    return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
   7686}
   7687
   7688mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
   7689{
   7690    mz_uint n;
   7691    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
   7692    if (!p)
   7693    {
   7694        if (filename_buf_size)
   7695            pFilename[0] = '\0';
   7696        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
   7697        return 0;
   7698    }
   7699    n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
   7700    if (filename_buf_size)
   7701    {
   7702        n = MZ_MIN(n, filename_buf_size - 1);
   7703        memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
   7704        pFilename[n] = '\0';
   7705    }
   7706    return n + 1;
   7707}
   7708
   7709mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
   7710{
   7711    return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
   7712}
   7713
   7714mz_bool mz_zip_end(mz_zip_archive *pZip)
   7715{
   7716    if (!pZip)
   7717        return MZ_FALSE;
   7718
   7719    if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
   7720        return mz_zip_reader_end(pZip);
   7721#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
   7722    else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
   7723        return mz_zip_writer_end(pZip);
   7724#endif
   7725
   7726    return MZ_FALSE;
   7727}
   7728
   7729#ifdef __cplusplus
   7730}
   7731#endif
   7732
   7733#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/