diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-02-11 18:17:33 +0100 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-02-11 18:17:33 +0100 |
commit | df00df5a7a5bcd9076d4423128ea014ab3535626 (patch) | |
tree | 337e62f8ca39b19b250b155a3fbeb495384e356b /source/kit/miniz/miniz_tinfl.c | |
parent | 80da54bb97c279aa60fb77a9bbad9baa0f2e4477 (diff) | |
download | saw-df00df5a7a5bcd9076d4423128ea014ab3535626.zip |
Update kit
Diffstat (limited to 'source/kit/miniz/miniz_tinfl.c')
-rw-r--r-- | source/kit/miniz/miniz_tinfl.c | 818 |
1 files changed, 818 insertions, 0 deletions
diff --git a/source/kit/miniz/miniz_tinfl.c b/source/kit/miniz/miniz_tinfl.c new file mode 100644 index 0000000..c8843ad --- /dev/null +++ b/source/kit/miniz/miniz_tinfl.c @@ -0,0 +1,818 @@ +/************************************************************************** + * + * Copyright 2013-2014 RAD Game Tools and Valve Software + * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + *obtaining a copy of this software and associated documentation files + *(the "Software"), to deal in the Software without restriction, + *including without limitation the rights to use, copy, modify, merge, + *publish, distribute, sublicense, and/or sell copies of the Software, + *and to permit persons to whom the Software is furnished to do so, + *subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + *BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + *ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + *CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + *SOFTWARE. + * + **************************************************************************/ + +#include "miniz.h" + +#ifndef MINIZ_NO_INFLATE_APIS + +# ifdef __cplusplus +extern "C" { +# endif + +/* ------------------- Low-level Decompression (completely independent + * from all compression API's) */ + +# define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +# define TINFL_MEMSET(p, c, l) memset(p, c, l) + +# define TINFL_CR_BEGIN \ + switch (r->m_state) { \ + case 0: +# define TINFL_CR_RETURN(state_index, result) \ + do { \ + status = result; \ + r->m_state = state_index; \ + goto common_exit; \ + case state_index:; \ + } \ + MZ_MACRO_END +# define TINFL_CR_RETURN_FOREVER(state_index, result) \ + do { \ + for (;;) { TINFL_CR_RETURN(state_index, result); } \ + } \ + MZ_MACRO_END +# define TINFL_CR_FINISH } + +# define TINFL_GET_BYTE(state_index, c) \ + do { \ + while (pIn_buf_cur >= pIn_buf_end) { \ + TINFL_CR_RETURN( \ + state_index, \ + (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) \ + ? TINFL_STATUS_NEEDS_MORE_INPUT \ + : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \ + } \ + c = *pIn_buf_cur++; \ + } \ + MZ_MACRO_END + +# define TINFL_NEED_BITS(state_index, n) \ + do { \ + mz_uint c; \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t) c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < (mz_uint) (n)) +# define TINFL_SKIP_BITS(state_index, n) \ + do { \ + if (num_bits < (mz_uint) (n)) { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END +# define TINFL_GET_BITS(state_index, b, n) \ + do { \ + if (num_bits < (mz_uint) (n)) { \ + TINFL_NEED_BITS(state_index, n); \ + } \ + b = bit_buf & ((1 << (n)) - 1); \ + bit_buf >>= (n); \ + num_bits -= (n); \ + } \ + MZ_MACRO_END + +/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of + * bytes remaining in the input buffer falls below 2. */ +/* It reads just enough bytes from the input stream that are needed to + * decode the next Huffman code (and absolutely no more). It works by + * trying to fully decode a */ +/* Huffman code by using whatever bits are currently present in the + * bit buffer. If this fails, it reads another byte, and tries again + * until it succeeds or until the */ +/* bit buffer contains >=15 bits (deflate's max. Huffman code size). + */ +# define TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree) \ + do { \ + temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) \ + break; \ + } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); \ + if (temp >= 0) \ + break; \ + } \ + TINFL_GET_BYTE(state_index, c); \ + bit_buf |= (((tinfl_bit_buf_t) c) << num_bits); \ + num_bits += 8; \ + } while (num_bits < 15); + +/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's + * more complex than you would initially expect because the zlib API + * expects the decompressor to never read */ +/* beyond the final byte of the deflate stream. (In other words, when + * this macro wants to read another byte from the input, it REALLY + * needs another byte in order to fully */ +/* decode the next Huffman code.) Handling this properly is + * particularly important on raw deflate (non-zlib) streams, which + * aren't followed by a byte aligned adler-32. */ +/* The slow path is only executed at the very end of the input buffer. + */ +/* v1.16: The original macro handled the case at the very end of the + * passed-in input buffer, but we also need to handle the case where + * the user passes in 1+zillion bytes */ +/* following the deflate data and our non-conservative read-ahead path + * won't kick in here on this code. This is much trickier. */ +# define TINFL_HUFF_DECODE(state_index, sym, pLookUp, pTree) \ + do { \ + int temp; \ + mz_uint code_len, c; \ + if (num_bits < 15) { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) { \ + TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree); \ + } else { \ + bit_buf |= (((tinfl_bit_buf_t) pIn_buf_cur[0]) \ + << num_bits) | \ + (((tinfl_bit_buf_t) pIn_buf_cur[1]) \ + << (num_bits + 8)); \ + pIn_buf_cur += 2; \ + num_bits += 16; \ + } \ + } \ + if ((temp = \ + pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \ + 0) \ + code_len = temp >> 9, temp &= 511; \ + else { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while (temp < 0); \ + } \ + sym = temp; \ + bit_buf >>= code_len; \ + num_bits -= code_len; \ + } \ + MZ_MACRO_END + +static void tinfl_clear_tree(tinfl_decompressor *r) { + if (r->m_type == 0) + MZ_CLEAR_ARR(r->m_tree_0); + else if (r->m_type == 1) + MZ_CLEAR_ARR(r->m_tree_1); + else + MZ_CLEAR_ARR(r->m_tree_2); +} + +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) { + static const mz_uint16 s_length_base[31] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, + 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, + 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + static const mz_uint8 s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, + 5, 5, 5, 5, 0, 0, 0 }; + static const mz_uint16 s_dist_base[32] = { + 1, 2, 3, 4, 5, 7, 9, 13, + 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, + 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 + }; + static const mz_uint8 s_dist_extra[32] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, + 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 + }; + static const mz_uint8 s_length_dezigzag[19] = { + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + }; + static const mz_uint16 s_min_table_sizes[3] = { 257, 1, 4 }; + + mz_int16 *pTrees[3]; + mz_uint8 *pCode_sizes[3]; + + tinfl_status status = TINFL_STATUS_FAILED; + mz_uint32 num_bits, dist, counter, num_extra; + tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = + pIn_buf_next + + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = + pOut_buf_next + ? pOut_buf_next + + *pOut_buf_size + : NULL; + 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; + + /* Ensure the output buffer's size is a power of 2, unless the + * output buffer is large enough to hold the entire output file (in + * which case it doesn't matter). */ + if (((out_buf_size_mask + 1) & out_buf_size_mask) || + (pOut_buf_next < pOut_buf_start)) { + *pIn_buf_size = *pOut_buf_size = 0; + return TINFL_STATUS_BAD_PARAM; + } + + pTrees[0] = r->m_tree_0; + pTrees[1] = r->m_tree_1; + pTrees[2] = r->m_tree_2; + pCode_sizes[0] = r->m_code_size_0; + pCode_sizes[1] = r->m_code_size_1; + pCode_sizes[2] = r->m_code_size_2; + + num_bits = r->m_num_bits; + bit_buf = r->m_bit_buf; + dist = r->m_dist; + counter = r->m_counter; + num_extra = r->m_num_extra; + dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = + r->m_zhdr1 = 0; + r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { + TINFL_GET_BYTE(1, r->m_zhdr0); + TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || + (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || + ((out_buf_size_mask + 1) < + (size_t) ((size_t) 1 + << (8U + (r->m_zhdr0 >> 4))))); + if (counter) { + TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); + } + } + + do { + TINFL_GET_BITS(3, r->m_final, 3); + r->m_type = r->m_final >> 1; + if (r->m_type == 0) { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) { + if (num_bits) + TINFL_GET_BITS(6, r->m_raw_header[counter], 8); + else + TINFL_GET_BYTE(7, r->m_raw_header[counter]); + } + if ((counter = (r->m_raw_header[0] | + (r->m_raw_header[1] << 8))) != + (mz_uint) (0xFFFF ^ (r->m_raw_header[2] | + (r->m_raw_header[3] << 8)))) { + TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); + } + while ((counter) && (num_bits)) { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8) dist; + counter--; + } + while (counter) { + size_t n; + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); + } + while (pIn_buf_cur >= pIn_buf_end) { + TINFL_CR_RETURN( + 38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) + ? TINFL_STATUS_NEEDS_MORE_INPUT + : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); + } + n = MZ_MIN(MZ_MIN((size_t) (pOut_buf_end - pOut_buf_cur), + (size_t) (pIn_buf_end - pIn_buf_cur)), + counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); + pIn_buf_cur += n; + pOut_buf_cur += n; + counter -= (mz_uint) n; + } + } else if (r->m_type == 3) { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } else { + if (r->m_type == 1) { + mz_uint8 *p = r->m_code_size_0; + mz_uint i; + r->m_table_sizes[0] = 288; + r->m_table_sizes[1] = 32; + TINFL_MEMSET(r->m_code_size_1, 5, 32); + for (i = 0; i <= 143; ++i) *p++ = 8; + for (; i <= 255; ++i) *p++ = 9; + for (; i <= 279; ++i) *p++ = 7; + for (; i <= 287; ++i) *p++ = 8; + } else { + for (counter = 0; counter < 3; counter++) { + TINFL_GET_BITS(11, r->m_table_sizes[counter], + "\05\05\04"[counter]); + r->m_table_sizes[counter] += s_min_table_sizes[counter]; + } + MZ_CLEAR_ARR(r->m_code_size_2); + for (counter = 0; counter < r->m_table_sizes[2]; counter++) { + mz_uint s; + TINFL_GET_BITS(14, s, 3); + r->m_code_size_2[s_length_dezigzag[counter]] = (mz_uint8) s; + } + r->m_table_sizes[2] = 19; + } + for (; (int) r->m_type >= 0; r->m_type--) { + int tree_next, tree_cur; + mz_int16 *pLookUp; + mz_int16 *pTree; + mz_uint8 *pCode_size; + mz_uint i, j, used_syms, total, sym_index, next_code[17], + total_syms[16]; + pLookUp = r->m_look_up[r->m_type]; + pTree = pTrees[r->m_type]; + pCode_size = pCode_sizes[r->m_type]; + MZ_CLEAR_ARR(total_syms); + TINFL_MEMSET(pLookUp, 0, sizeof(r->m_look_up[0])); + tinfl_clear_tree(r); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) + total_syms[pCode_size[i]]++; + used_syms = 0, total = 0; + next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) { + used_syms += total_syms[i]; + next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); + } + if ((65536 != total) && (used_syms > 1)) { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; + sym_index < r->m_table_sizes[r->m_type]; ++sym_index) { + mz_uint rev_code = 0, l, cur_code, + code_size = pCode_size[sym_index]; + if (!code_size) + continue; + cur_code = next_code[code_size]++; + for (l = code_size; l > 0; l--, cur_code >>= 1) + rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) { + mz_int16 k = (mz_int16) ((code_size << 9) | sym_index); + while (rev_code < TINFL_FAST_LOOKUP_SIZE) { + pLookUp[rev_code] = k; + rev_code += (1 << code_size); + } + continue; + } + if (0 == + (tree_cur = pLookUp[rev_code & + (TINFL_FAST_LOOKUP_SIZE - 1)])) { + pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = + (mz_int16) tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTree[-tree_cur - 1]) { + pTree[-tree_cur - 1] = (mz_int16) tree_next; + tree_cur = tree_next; + tree_next -= 2; + } else + tree_cur = pTree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); + pTree[-tree_cur - 1] = (mz_int16) sym_index; + } + if (r->m_type == 2) { + for (counter = 0; counter < (r->m_table_sizes[0] + + r->m_table_sizes[1]);) { + mz_uint s; + TINFL_HUFF_DECODE(16, dist, r->m_look_up[2], r->m_tree_2); + if (dist < 16) { + r->m_len_codes[counter++] = (mz_uint8) dist; + continue; + } + if ((dist == 16) && (!counter)) { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; + TINFL_GET_BITS(18, s, num_extra); + s += "\03\03\013"[dist - 16]; + TINFL_MEMSET( + r->m_len_codes + counter, + (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); + counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != + counter) { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_code_size_0, r->m_len_codes, + r->m_table_sizes[0]); + TINFL_MEMCPY(r->m_code_size_1, + r->m_len_codes + r->m_table_sizes[0], + r->m_table_sizes[1]); + } + } + for (;;) { + mz_uint8 *pSrc; + for (;;) { + if (((pIn_buf_end - pIn_buf_cur) < 4) || + ((pOut_buf_end - pOut_buf_cur) < 2)) { + TINFL_HUFF_DECODE(23, counter, r->m_look_up[0], + r->m_tree_0); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = (mz_uint8) counter; + } else { + int sym2; + mz_uint code_len; +# if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) { + bit_buf |= + (((tinfl_bit_buf_t) MZ_READ_LE32(pIn_buf_cur)) + << num_bits); + pIn_buf_cur += 4; + num_bits += 32; + } +# else + if (num_bits < 15) { + bit_buf |= + (((tinfl_bit_buf_t) MZ_READ_LE16(pIn_buf_cur)) + << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +# endif + if ((sym2 = + r->m_look_up[0][bit_buf & + (TINFL_FAST_LOOKUP_SIZE - 1)]) >= + 0) + code_len = sym2 >> 9; + else { + code_len = TINFL_FAST_LOOKUP_BITS; + do { + sym2 = r->m_tree_0[~sym2 + + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + counter = sym2; + bit_buf >>= code_len; + num_bits -= code_len; + if (counter & 256) + break; + +# if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) { + bit_buf |= + (((tinfl_bit_buf_t) MZ_READ_LE16(pIn_buf_cur)) + << num_bits); + pIn_buf_cur += 2; + num_bits += 16; + } +# endif + if ((sym2 = + r->m_look_up[0][bit_buf & + (TINFL_FAST_LOOKUP_SIZE - 1)]) >= + 0) + code_len = sym2 >> 9; + else { + code_len = TINFL_FAST_LOOKUP_BITS; + do { + sym2 = r->m_tree_0[~sym2 + + ((bit_buf >> code_len++) & 1)]; + } while (sym2 < 0); + } + bit_buf >>= code_len; + num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8) counter; + if (sym2 & 256) { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8) sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) + break; + + num_extra = s_length_extra[counter - 257]; + counter = s_length_base[counter - 257]; + if (num_extra) { + mz_uint extra_bits; + TINFL_GET_BITS(25, extra_bits, num_extra); + counter += extra_bits; + } + + TINFL_HUFF_DECODE(26, dist, r->m_look_up[1], r->m_tree_1); + num_extra = s_dist_extra[dist]; + dist = s_dist_base[dist]; + if (num_extra) { + mz_uint extra_bits; + TINFL_GET_BITS(27, extra_bits, num_extra); + dist += extra_bits; + } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist == 0 || dist > dist_from_out_buf_start || + dist_from_out_buf_start == 0) && + (decomp_flags & + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) { + while (counter--) { + while (pOut_buf_cur >= pOut_buf_end) { + TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); + } + *pOut_buf_cur++ = + pOut_buf_start[(dist_from_out_buf_start++ - dist) & + out_buf_size_mask]; + } + continue; + } +# if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) { + const mz_uint8 *pSrc_end = pSrc + (counter & ~7); + do { +# ifdef MINIZ_UNALIGNED_USE_MEMCPY + memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32) * 2); +# else + ((mz_uint32 *) pOut_buf_cur)[0] = (( + const mz_uint32 *) pSrc)[0]; + ((mz_uint32 *) pOut_buf_cur)[1] = (( + const mz_uint32 *) pSrc)[1]; +# endif + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) { + if (counter) { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +# endif + while (counter > 2) { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; + pSrc += 3; + counter -= 3; + } + if (counter > 0) { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } while (!(r->m_final & 1)); + + /* Ensure byte alignment and put back any bytes from the bitbuf if + * we've looked ahead too far on gzip, or other Deflate streams + * followed by arbitrary data. */ + /* I'm being super conservative here. A number of simplifications + * can be made to the byte alignment part, and the Adler32 check + * shouldn't ever need to worry about reading from the bitbuf now. + */ + TINFL_SKIP_BITS(32, num_bits & 7); + while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) { + --pIn_buf_cur; + num_bits -= 8; + } + bit_buf &= ~(~(tinfl_bit_buf_t) 0 << num_bits); + 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). */ + + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { + for (counter = 0; counter < 4; ++counter) { + mz_uint s; + if (num_bits) + TINFL_GET_BITS(41, s, 8); + else + TINFL_GET_BYTE(42, s); + r->m_z_adler32 = (r->m_z_adler32 << 8) | s; + } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + + TINFL_CR_FINISH + +common_exit: + /* As long as we aren't telling the caller that we NEED more input + * to make forward progress: */ + /* Put back any bytes from the bitbuf in case we've looked ahead too + * far on gzip, or other Deflate streams followed by arbitrary data. + */ + /* We need to be very careful here to NOT push back any bytes we + * definitely know we need to make forward progress, though, or + * we'll lock the caller up into an inf loop. */ + if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && + (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) { + while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) { + --pIn_buf_cur; + num_bits -= 8; + } + } + r->m_num_bits = num_bits; + r->m_bit_buf = bit_buf & ~(~(tinfl_bit_buf_t) 0 << num_bits); + r->m_dist = dist; + r->m_counter = counter; + r->m_num_extra = num_extra; + r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; + *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & + (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && + (status >= 0)) { + const mz_uint8 *ptr = pOut_buf_next; + size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, + s2 = r->m_check_adler32 >> 16; + size_t block_len = buf_len % 5552; + while (buf_len) { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { + s1 += ptr[0], s2 += s1; + s1 += ptr[1], s2 += s1; + s1 += ptr[2], s2 += s1; + s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; + s1 += ptr[5], s2 += s1; + s1 += ptr[6], s2 += s1; + s1 += ptr[7], s2 += s1; + } + for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; + buf_len -= block_len; + block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; + if ((status == TINFL_STATUS_DONE) && + (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && + (r->m_check_adler32 != r->m_z_adler32)) + status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; +} + +/* Higher level helper functions. */ +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, + size_t src_buf_len, + size_t *pOut_len, int flags) { + tinfl_decompressor decomp; + void *pBuf = NULL, *pNew_buf; + size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for (;;) { + size_t src_buf_size = src_buf_len - src_buf_ofs, + dst_buf_size = out_buf_capacity - *pOut_len, + new_out_buf_capacity; + 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, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) + break; + new_out_buf_capacity = out_buf_capacity * 2; + if (new_out_buf_capacity < 128) + new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) { + MZ_FREE(pBuf); + *pOut_len = 0; + return NULL; + } + pBuf = pNew_buf; + out_buf_capacity = new_out_buf_capacity; + } + return pBuf; +} + +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) { + tinfl_decompressor decomp; + tinfl_status status; + tinfl_init(&decomp); + 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); + return (status != TINFL_STATUS_DONE) + ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED + : out_buf_len; +} + +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) { + int result = 0; + tinfl_decompressor decomp; + mz_uint8 *pDict = (mz_uint8 *) MZ_MALLOC(TINFL_LZ_DICT_SIZE); + size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + memset(pDict, 0, TINFL_LZ_DICT_SIZE); + tinfl_init(&decomp); + for (;;) { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, + dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress( + &decomp, (const mz_uint8 *) pIn_buf + in_buf_ofs, + &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && + (!(*pPut_buf_func)(pDict + dict_ofs, (int) dst_buf_size, + pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; +} + +# ifndef MINIZ_NO_MALLOC +tinfl_decompressor *tinfl_decompressor_alloc(void) { + tinfl_decompressor *pDecomp = (tinfl_decompressor *) MZ_MALLOC( + sizeof(tinfl_decompressor)); + if (pDecomp) + tinfl_init(pDecomp); + return pDecomp; +} + +void tinfl_decompressor_free(tinfl_decompressor *pDecomp) { + MZ_FREE(pDecomp); +} +# endif + +# ifdef __cplusplus +} +# endif + +#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/ |