Reduce memory usage for inflate

Use Huffman tables with correct sizes instead of always 288
This commit is contained in:
Christian Sandberg
2020-06-20 17:31:32 +02:00
parent 164c81c7d7
commit 8da3cbb64e
2 changed files with 32 additions and 19 deletions

View File

@@ -121,7 +121,7 @@ extern "C" {
code_len = TINFL_FAST_LOOKUP_BITS; \ code_len = TINFL_FAST_LOOKUP_BITS; \
do \ do \
{ \ { \
temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ temp = (pHuff)->m_pTree[~temp + ((bit_buf >> code_len++) & 1)];\
} while ((temp < 0) && (num_bits >= (code_len + 1))); \ } while ((temp < 0) && (num_bits >= (code_len + 1))); \
if (temp >= 0) \ if (temp >= 0) \
break; \ break; \
@@ -162,7 +162,7 @@ extern "C" {
code_len = TINFL_FAST_LOOKUP_BITS; \ code_len = TINFL_FAST_LOOKUP_BITS; \
do \ do \
{ \ { \
temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ temp = (pHuff)->m_pTree[~temp + ((bit_buf >> code_len++) & 1)]; \
} while (temp < 0); \ } while (temp < 0); \
} \ } \
sym = temp; \ sym = temp; \
@@ -271,11 +271,11 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
{ {
if (r->m_type == 1) if (r->m_type == 1)
{ {
mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint8 *p = r->m_code_size_0;
mz_uint i; mz_uint i;
r->m_table_sizes[0] = 288; r->m_table_sizes[0] = 288;
r->m_table_sizes[1] = 32; r->m_table_sizes[1] = 32;
TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); TINFL_MEMSET(r->m_code_size_1, 5, 32);
for (i = 0; i <= 143; ++i) for (i = 0; i <= 143; ++i)
*p++ = 8; *p++ = 8;
for (; i <= 255; ++i) for (; i <= 255; ++i)
@@ -292,12 +292,12 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
r->m_table_sizes[counter] += s_min_table_sizes[counter]; r->m_table_sizes[counter] += s_min_table_sizes[counter];
} }
MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); MZ_CLEAR_OBJ(r->m_code_size_2);
for (counter = 0; counter < r->m_table_sizes[2]; counter++) for (counter = 0; counter < r->m_table_sizes[2]; counter++)
{ {
mz_uint s; mz_uint s;
TINFL_GET_BITS(14, s, 3); TINFL_GET_BITS(14, s, 3);
r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; r->m_code_size_2[s_length_dezigzag[counter]] = (mz_uint8)s;
} }
r->m_table_sizes[2] = 19; r->m_table_sizes[2] = 19;
} }
@@ -309,9 +309,9 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
pTable = &r->m_tables[r->m_type]; pTable = &r->m_tables[r->m_type];
MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(total_syms);
MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_look_up);
MZ_CLEAR_OBJ(pTable->m_tree); TINFL_MEMSET(pTable->m_pTree, 0, r->m_table_sizes[r->m_type] * sizeof(pTable->m_pTree[0]) * 2);
for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
total_syms[pTable->m_code_size[i]]++; total_syms[pTable->m_pCode_size[i]]++;
used_syms = 0, total = 0; used_syms = 0, total = 0;
next_code[0] = next_code[1] = 0; next_code[0] = next_code[1] = 0;
for (i = 1; i <= 15; ++i) for (i = 1; i <= 15; ++i)
@@ -325,7 +325,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
} }
for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) 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]; mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_pCode_size[sym_index];
if (!code_size) if (!code_size)
continue; continue;
cur_code = next_code[code_size]++; cur_code = next_code[code_size]++;
@@ -351,17 +351,17 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
{ {
tree_cur -= ((rev_code >>= 1) & 1); tree_cur -= ((rev_code >>= 1) & 1);
if (!pTable->m_tree[-tree_cur - 1]) if (!pTable->m_pTree[-tree_cur - 1])
{ {
pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; pTable->m_pTree[-tree_cur - 1] = (mz_int16)tree_next;
tree_cur = tree_next; tree_cur = tree_next;
tree_next -= 2; tree_next -= 2;
} }
else else
tree_cur = pTable->m_tree[-tree_cur - 1]; tree_cur = pTable->m_pTree[-tree_cur - 1];
} }
tree_cur -= ((rev_code >>= 1) & 1); tree_cur -= ((rev_code >>= 1) & 1);
pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; pTable->m_pTree[-tree_cur - 1] = (mz_int16)sym_index;
} }
if (r->m_type == 2) if (r->m_type == 2)
{ {
@@ -388,8 +388,8 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
{ {
TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); 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[0].m_pCode_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]); TINFL_MEMCPY(r->m_tables[1].m_pCode_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
} }
} }
for (;;) for (;;)
@@ -434,7 +434,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
code_len = TINFL_FAST_LOOKUP_BITS; code_len = TINFL_FAST_LOOKUP_BITS;
do do
{ {
sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)];
} while (sym2 < 0); } while (sym2 < 0);
} }
counter = sym2; counter = sym2;
@@ -458,7 +458,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
code_len = TINFL_FAST_LOOKUP_BITS; code_len = TINFL_FAST_LOOKUP_BITS;
do do
{ {
sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)];
} while (sym2 < 0); } while (sym2 < 0);
} }
bit_buf >>= code_len; bit_buf >>= code_len;

View File

@@ -91,6 +91,12 @@ typedef enum {
do \ do \
{ \ { \
(r)->m_state = 0; \ (r)->m_state = 0; \
(r)->m_tables[0].m_pCode_size = (r)->m_code_size_0; \
(r)->m_tables[0].m_pTree = (r)->m_tree_0; \
(r)->m_tables[1].m_pCode_size = (r)->m_code_size_1; \
(r)->m_tables[1].m_pTree = (r)->m_tree_1; \
(r)->m_tables[2].m_pCode_size = (r)->m_code_size_2; \
(r)->m_tables[2].m_pTree = (r)->m_tree_2; \
} \ } \
MZ_MACRO_END MZ_MACRO_END
#define tinfl_get_adler32(r) (r)->m_check_adler32 #define tinfl_get_adler32(r) (r)->m_check_adler32
@@ -112,8 +118,9 @@ enum
typedef struct typedef struct
{ {
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; mz_uint8 *m_pCode_size;
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; mz_int16 *m_pTree;
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE];
} tinfl_huff_table; } tinfl_huff_table;
#if MINIZ_HAS_64BIT_REGISTERS #if MINIZ_HAS_64BIT_REGISTERS
@@ -136,6 +143,12 @@ struct tinfl_decompressor_tag
tinfl_bit_buf_t m_bit_buf; tinfl_bit_buf_t m_bit_buf;
size_t m_dist_from_out_buf_start; size_t m_dist_from_out_buf_start;
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
mz_int16 m_tree_0[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
mz_int16 m_tree_1[TINFL_MAX_HUFF_SYMBOLS_1 * 2];
mz_int16 m_tree_2[TINFL_MAX_HUFF_SYMBOLS_2 * 2];
mz_uint8 m_code_size_0[TINFL_MAX_HUFF_SYMBOLS_0];
mz_uint8 m_code_size_1[TINFL_MAX_HUFF_SYMBOLS_1];
mz_uint8 m_code_size_2[TINFL_MAX_HUFF_SYMBOLS_2];
mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
}; };