mirror of
				https://github.com/eledio-devices/thirdparty-miniz.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			700 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			700 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "miniz_tinfl.h"
 | |
| 
 | |
| // ------------------- 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, pHuff)                             \
 | |
|     do                                                                         \
 | |
|     {                                                                          \
 | |
|         temp = (pHuff)->m_look_up[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 = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
 | |
|             } while ((temp < 0) && (num_bits >= (code_len + 1)));              \
 | |
|             if (temp >= 0)                                                     \
 | |
|                 break;                                                         \
 | |
|         }                                                                      \
 | |
|         TINFL_GET_BYTE(state_index, c);                                        \
 | |
|         bit_buf |= (((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, pHuff)                                                                                  \
 | |
|     do                                                                                                                              \
 | |
|     {                                                                                                                               \
 | |
|         int temp;                                                                                                                   \
 | |
|         mz_uint code_len, c;                                                                                                        \
 | |
|         if (num_bits < 15)                                                                                                          \
 | |
|         {                                                                                                                           \
 | |
|             if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
 | |
|             {                                                                                                                       \
 | |
|                 TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \
 | |
|             }                                                                                                                       \
 | |
|             else                                                                                                                    \
 | |
|             {                                                                                                                       \
 | |
|                 bit_buf |= (((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 = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \
 | |
|             code_len = temp >> 9, temp &= 511;                                                                                      \
 | |
|         else                                                                                                                        \
 | |
|         {                                                                                                                           \
 | |
|             code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
 | |
|             do                                                                                                                      \
 | |
|             {                                                                                                                       \
 | |
|                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \
 | |
|             } while (temp < 0);                                                                                                     \
 | |
|         }                                                                                                                           \
 | |
|         sym = temp;                                                                                                                 \
 | |
|         bit_buf >>= code_len;                                                                                                       \
 | |
|         num_bits -= code_len;                                                                                                       \
 | |
|     }                                                                                                                               \
 | |
|     MZ_MACRO_END
 | |
| 
 | |
| 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 int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
 | |
|     static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
 | |
|     static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
 | |
|     static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
 | |
|     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 int s_min_table_sizes[3] = { 257, 1, 4 };
 | |
| 
 | |
|     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_size;
 | |
|     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;
 | |
|     }
 | |
| 
 | |
|     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)(1U << (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_tables[0].m_code_size;
 | |
|                 mz_uint i;
 | |
|                 r->m_table_sizes[0] = 288;
 | |
|                 r->m_table_sizes[1] = 32;
 | |
|                 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
 | |
|                 for (i = 0; i <= 143; ++i)
 | |
|                     *p++ = 8;
 | |
|                 for (; i <= 255; ++i)
 | |
|                     *p++ = 9;
 | |
|                 for (; i <= 279; ++i)
 | |
|                     *p++ = 7;
 | |
|                 for (; i <= 287; ++i)
 | |
|                     *p++ = 8;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 for (counter = 0; counter < 3; counter++)
 | |
|                 {
 | |
|                     TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
 | |
|                     r->m_table_sizes[counter] += s_min_table_sizes[counter];
 | |
|                 }
 | |
|                 MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
 | |
|                 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
 | |
|                 {
 | |
|                     mz_uint s;
 | |
|                     TINFL_GET_BITS(14, s, 3);
 | |
|                     r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
 | |
|                 }
 | |
|                 r->m_table_sizes[2] = 19;
 | |
|             }
 | |
|             for (; (int)r->m_type >= 0; r->m_type--)
 | |
|             {
 | |
|                 int tree_next, tree_cur;
 | |
|                 tinfl_huff_table *pTable;
 | |
|                 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
 | |
|                 pTable = &r->m_tables[r->m_type];
 | |
|                 MZ_CLEAR_OBJ(total_syms);
 | |
|                 MZ_CLEAR_OBJ(pTable->m_look_up);
 | |
|                 MZ_CLEAR_OBJ(pTable->m_tree);
 | |
|                 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
 | |
|                     total_syms[pTable->m_code_size[i]]++;
 | |
|                 used_syms = 0, total = 0;
 | |
|                 next_code[0] = next_code[1] = 0;
 | |
|                 for (i = 1; i <= 15; ++i)
 | |
|                 {
 | |
|                     used_syms += total_syms[i];
 | |
|                     next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
 | |
|                 }
 | |
|                 if ((65536 != total) && (used_syms > 1))
 | |
|                 {
 | |
|                     TINFL_CR_RETURN_FOREVER(35, 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 = pTable->m_code_size[sym_index];
 | |
|                     if (!code_size)
 | |
|                         continue;
 | |
|                     cur_code = next_code[code_size]++;
 | |
|                     for (l = code_size; l > 0; l--, cur_code >>= 1)
 | |
|                         rev_code = (rev_code << 1) | (cur_code & 1);
 | |
|                     if (code_size <= TINFL_FAST_LOOKUP_BITS)
 | |
|                     {
 | |
|                         mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
 | |
|                         while (rev_code < TINFL_FAST_LOOKUP_SIZE)
 | |
|                         {
 | |
|                             pTable->m_look_up[rev_code] = k;
 | |
|                             rev_code += (1 << code_size);
 | |
|                         }
 | |
|                         continue;
 | |
|                     }
 | |
|                     if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
 | |
|                     {
 | |
|                         pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
 | |
|                         tree_cur = tree_next;
 | |
|                         tree_next -= 2;
 | |
|                     }
 | |
|                     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 (!pTable->m_tree[-tree_cur - 1])
 | |
|                         {
 | |
|                             pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
 | |
|                             tree_cur = tree_next;
 | |
|                             tree_next -= 2;
 | |
|                         }
 | |
|                         else
 | |
|                             tree_cur = pTable->m_tree[-tree_cur - 1];
 | |
|                     }
 | |
|                     tree_cur -= ((rev_code >>= 1) & 1);
 | |
|                     pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
 | |
|                 }
 | |
|                 if (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_tables[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_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
 | |
|                     TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
 | |
|                 }
 | |
|             }
 | |
|             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_tables[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_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
 | |
|                             code_len = sym2 >> 9;
 | |
|                         else
 | |
|                         {
 | |
|                             code_len = TINFL_FAST_LOOKUP_BITS;
 | |
|                             do
 | |
|                             {
 | |
|                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
 | |
|                             } while (sym2 < 0);
 | |
|                         }
 | |
|                         counter = sym2;
 | |
|                         bit_buf >>= code_len;
 | |
|                         num_bits -= code_len;
 | |
|                         if (counter & 256)
 | |
|                             break;
 | |
| 
 | |
| #if !TINFL_USE_64BIT_BITBUF
 | |
|                         if (num_bits < 15)
 | |
|                         {
 | |
|                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
 | |
|                             pIn_buf_cur += 2;
 | |
|                             num_bits += 16;
 | |
|                         }
 | |
| #endif
 | |
|                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
 | |
|                             code_len = sym2 >> 9;
 | |
|                         else
 | |
|                         {
 | |
|                             code_len = TINFL_FAST_LOOKUP_BITS;
 | |
|                             do
 | |
|                             {
 | |
|                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
 | |
|                             } while (sym2 < 0);
 | |
|                         }
 | |
|                         bit_buf >>= code_len;
 | |
|                         num_bits -= code_len;
 | |
| 
 | |
|                         pOut_buf_cur[0] = (mz_uint8)counter;
 | |
|                         if (sym2 & 256)
 | |
|                         {
 | |
|                             pOut_buf_cur++;
 | |
|                             counter = sym2;
 | |
|                             break;
 | |
|                         }
 | |
|                         pOut_buf_cur[1] = (mz_uint8)sym2;
 | |
|                         pOut_buf_cur += 2;
 | |
|                     }
 | |
|                 }
 | |
|                 if ((counter &= 511) == 256)
 | |
|                     break;
 | |
| 
 | |
|                 num_extra = s_length_extra[counter - 257];
 | |
|                 counter = s_length_base[counter - 257];
 | |
|                 if (num_extra)
 | |
|                 {
 | |
|                     mz_uint extra_bits;
 | |
|                     TINFL_GET_BITS(25, extra_bits, num_extra);
 | |
|                     counter += extra_bits;
 | |
|                 }
 | |
| 
 | |
|                 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
 | |
|                 num_extra = s_dist_extra[dist];
 | |
|                 dist = s_dist_base[dist];
 | |
|                 if (num_extra)
 | |
|                 {
 | |
|                     mz_uint extra_bits;
 | |
|                     TINFL_GET_BITS(27, extra_bits, num_extra);
 | |
|                     dist += extra_bits;
 | |
|                 }
 | |
| 
 | |
|                 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
 | |
|                 if ((dist > dist_from_out_buf_start) && (decomp_flags & 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
 | |
|                     {
 | |
|                         ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
 | |
|                         ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
 | |
|                         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
 | |
|                 do
 | |
|                 {
 | |
|                     pOut_buf_cur[0] = pSrc[0];
 | |
|                     pOut_buf_cur[1] = pSrc[1];
 | |
|                     pOut_buf_cur[2] = pSrc[2];
 | |
|                     pOut_buf_cur += 3;
 | |
|                     pSrc += 3;
 | |
|                 } while ((int)(counter -= 3) > 2);
 | |
|                 if ((int)counter > 0)
 | |
|                 {
 | |
|                     pOut_buf_cur[0] = pSrc[0];
 | |
|                     if ((int)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)((1ULL << num_bits) - 1ULL);
 | |
|     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)((1ULL << num_bits) - 1ULL);
 | |
|     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;
 | |
|     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;
 | |
| }
 | |
| 
 | |
| tinfl_decompressor *tinfl_decompressor_alloc()
 | |
| {
 | |
|     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);
 | |
| }
 |