root/src/punutil/miniz.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mz_adler32
  2. mz_crc32
  3. mz_free
  4. miniz_def_alloc_func
  5. miniz_def_free_func
  6. miniz_def_realloc_func
  7. mz_version
  8. mz_deflateInit
  9. mz_deflateInit2
  10. mz_deflateReset
  11. mz_deflate
  12. mz_deflateEnd
  13. mz_deflateBound
  14. mz_compress2
  15. mz_compress
  16. mz_compressBound
  17. mz_inflateInit2
  18. mz_inflateInit
  19. mz_inflateReset
  20. mz_inflate
  21. mz_inflateEnd
  22. mz_uncompress2
  23. mz_uncompress
  24. mz_error
  25. tdefl_radix_sort_syms
  26. tdefl_calculate_minimum_redundancy
  27. tdefl_huffman_enforce_max_code_size
  28. tdefl_optimize_huffman_table
  29. tdefl_start_dynamic_block
  30. tdefl_start_static_block
  31. tdefl_compress_lz_codes
  32. tdefl_compress_lz_codes
  33. tdefl_compress_block
  34. tdefl_flush_block
  35. TDEFL_READ_UNALIGNED_WORD
  36. TDEFL_READ_UNALIGNED_WORD2
  37. tdefl_find_match
  38. tdefl_find_match
  39. TDEFL_READ_UNALIGNED_WORD32
  40. tdefl_compress_fast
  41. tdefl_record_literal
  42. tdefl_record_match
  43. tdefl_compress_normal
  44. tdefl_flush_output_buffer
  45. tdefl_compress
  46. tdefl_compress_buffer
  47. tdefl_init
  48. tdefl_get_prev_return_status
  49. tdefl_get_adler32
  50. tdefl_compress_mem_to_output
  51. tdefl_output_buffer_putter
  52. tdefl_compress_mem_to_heap
  53. tdefl_compress_mem_to_mem
  54. tdefl_create_comp_flags_from_zip_params
  55. tdefl_write_image_to_png_file_in_memory_ex
  56. tdefl_write_image_to_png_file_in_memory
  57. tdefl_compressor_alloc
  58. tdefl_compressor_free
  59. tinfl_clear_tree
  60. tinfl_decompress
  61. tinfl_decompress_mem_to_heap
  62. tinfl_decompress_mem_to_mem
  63. tinfl_decompress_mem_to_callback
  64. tinfl_decompressor_alloc
  65. tinfl_decompressor_free
  66. mz_utf8z_to_widechar
  67. mz_fopen
  68. mz_freopen
  69. mz_stat
  70. mz_stat64
  71. mz_zip_array_range_check
  72. mz_zip_array_init
  73. mz_zip_array_clear
  74. mz_zip_array_ensure_capacity
  75. mz_zip_array_reserve
  76. mz_zip_array_resize
  77. mz_zip_array_ensure_room
  78. mz_zip_array_push_back
  79. mz_zip_dos_to_time_t
  80. mz_zip_time_t_to_dos_time
  81. mz_zip_get_file_modified_time
  82. mz_zip_set_file_times
  83. mz_zip_set_error
  84. mz_zip_reader_init_internal
  85. mz_zip_reader_filename_less
  86. mz_zip_reader_sort_central_dir_offsets_by_filename
  87. mz_zip_reader_locate_header_sig
  88. mz_zip_reader_eocd64_valid
  89. mz_zip_reader_read_central_dir
  90. mz_zip_zero_struct
  91. mz_zip_reader_end_internal
  92. mz_zip_reader_end
  93. mz_zip_reader_init
  94. mz_zip_mem_read_func
  95. mz_zip_reader_init_mem
  96. mz_zip_file_read_func
  97. mz_zip_reader_init_file
  98. mz_zip_reader_init_file_v2
  99. mz_zip_reader_init_cfile
  100. mz_zip_get_cdh
  101. mz_zip_reader_is_file_encrypted
  102. mz_zip_reader_is_file_supported
  103. mz_zip_reader_is_file_a_directory
  104. mz_zip_file_stat_internal
  105. mz_zip_string_equal
  106. mz_zip_filename_compare
  107. mz_zip_locate_file_binary_search
  108. mz_zip_reader_locate_file
  109. mz_zip_reader_locate_file_v2
  110. mz_zip_reader_extract_to_mem_no_alloc1
  111. mz_zip_reader_extract_to_mem_no_alloc
  112. mz_zip_reader_extract_file_to_mem_no_alloc
  113. mz_zip_reader_extract_to_mem
  114. mz_zip_reader_extract_file_to_mem
  115. mz_zip_reader_extract_to_heap
  116. mz_zip_reader_extract_file_to_heap
  117. mz_zip_reader_extract_to_callback
  118. mz_zip_reader_extract_file_to_callback
  119. mz_zip_reader_extract_iter_new
  120. mz_zip_reader_extract_file_iter_new
  121. mz_zip_reader_extract_iter_read
  122. mz_zip_reader_extract_iter_free
  123. mz_zip_file_write_callback
  124. mz_zip_reader_extract_to_file
  125. mz_zip_reader_extract_file_to_file
  126. mz_zip_reader_extract_to_cfile
  127. mz_zip_reader_extract_file_to_cfile
  128. mz_zip_compute_crc32_callback
  129. mz_zip_validate_file
  130. mz_zip_validate_archive
  131. mz_zip_validate_mem_archive
  132. mz_zip_validate_file_archive
  133. mz_write_le16
  134. mz_write_le32
  135. mz_write_le64
  136. mz_zip_heap_write_func
  137. mz_zip_writer_end_internal
  138. mz_zip_writer_init_v2
  139. mz_zip_writer_init
  140. mz_zip_writer_init_heap_v2
  141. mz_zip_writer_init_heap
  142. mz_zip_file_write_func
  143. mz_zip_writer_init_file
  144. mz_zip_writer_init_file_v2
  145. mz_zip_writer_init_cfile
  146. mz_zip_writer_init_from_reader_v2
  147. mz_zip_writer_init_from_reader
  148. mz_zip_writer_add_mem
  149. mz_zip_writer_add_put_buf_callback
  150. mz_zip_writer_create_zip64_extra_data
  151. mz_zip_writer_create_local_dir_header
  152. mz_zip_writer_create_central_dir_header
  153. mz_zip_writer_add_to_central_dir
  154. mz_zip_writer_validate_archive_name
  155. mz_zip_writer_compute_padding_needed_for_file_alignment
  156. mz_zip_writer_write_zeros
  157. mz_zip_writer_add_mem_ex
  158. mz_zip_writer_add_mem_ex_v2
  159. mz_zip_writer_add_read_buf_callback
  160. mz_file_read_func_stdio
  161. mz_zip_writer_add_cfile
  162. mz_zip_writer_add_file
  163. mz_zip_writer_update_zip64_extension_block
  164. mz_zip_writer_add_from_zip_reader
  165. mz_zip_writer_finalize_archive
  166. mz_zip_writer_finalize_heap_archive
  167. mz_zip_writer_end
  168. mz_zip_add_mem_to_archive_file_in_place
  169. mz_zip_add_mem_to_archive_file_in_place_v2
  170. mz_zip_extract_archive_file_to_heap_v2
  171. mz_zip_extract_archive_file_to_heap
  172. mz_zip_get_mode
  173. mz_zip_get_type
  174. mz_zip_set_last_error
  175. mz_zip_peek_last_error
  176. mz_zip_clear_last_error
  177. mz_zip_get_last_error
  178. mz_zip_get_error_string
  179. mz_zip_is_zip64
  180. mz_zip_get_central_dir_size
  181. mz_zip_reader_get_num_files
  182. mz_zip_get_archive_size
  183. mz_zip_get_archive_file_start_offset
  184. mz_zip_get_cfile
  185. mz_zip_read_archive_data
  186. mz_zip_reader_get_filename
  187. mz_zip_reader_file_stat
  188. mz_zip_end

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

/* [previous][next][first][last][top][bottom][index][help] */