mirror of
https://github.com/google/brotli.git
synced 2024-12-28 18:51:08 +00:00
update brotli decoder with latest improvements
This commit is contained in:
parent
5da4f65c43
commit
db71549ac5
@ -32,8 +32,7 @@ void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input) {
|
||||
br->bit_pos_ = 0;
|
||||
br->avail_in = 0;
|
||||
br->eos_ = 0;
|
||||
br->tmp_bytes_read_ = 0;
|
||||
br->next_in = NULL;
|
||||
br->next_in = br->buf_;
|
||||
}
|
||||
|
||||
|
||||
|
105
dec/bit_reader.h
105
dec/bit_reader.h
@ -29,7 +29,8 @@ extern "C" {
|
||||
|
||||
#define BROTLI_MAX_NUM_BIT_READ 25
|
||||
#define BROTLI_READ_SIZE 1024
|
||||
#define BROTLI_IBUF_SIZE (BROTLI_READ_SIZE + 128)
|
||||
#define BROTLI_IMPLICIT_ZEROES 128
|
||||
#define BROTLI_IBUF_SIZE (BROTLI_READ_SIZE + BROTLI_IMPLICIT_ZEROES)
|
||||
#define BROTLI_IBUF_MASK (BROTLI_READ_SIZE - 1)
|
||||
|
||||
/* Masking with this expression turns to a single "Unsigned Bit Field Extract"
|
||||
@ -48,9 +49,6 @@ typedef struct {
|
||||
int eos_; /* input stream is finished */
|
||||
BrotliInput input_; /* input callback */
|
||||
|
||||
/* indicates how much bytes already read when reading partial data */
|
||||
int tmp_bytes_read_;
|
||||
|
||||
/* Input byte buffer, consist of a ringbuffer and a "slack" region where */
|
||||
/* bytes from the start of the ringbuffer are copied. */
|
||||
uint8_t buf_[BROTLI_IBUF_SIZE];
|
||||
@ -73,8 +71,8 @@ void BrotliWarmupBitReader(BrotliBitReader* const br);
|
||||
when more data is available makes it continue including the partially read
|
||||
data
|
||||
|
||||
If finish is true and the end of the stream is reached, 128 additional zero
|
||||
bytes are copied to the ringbuffer.
|
||||
If finish is true and the end of the stream is reached,
|
||||
BROTLI_IMPLICIT_ZEROES additional zero bytes are copied to the ringbuffer.
|
||||
*/
|
||||
static BROTLI_INLINE int BrotliReadInput(
|
||||
BrotliBitReader* const br, int finish) {
|
||||
@ -83,35 +81,27 @@ static BROTLI_INLINE int BrotliReadInput(
|
||||
} else {
|
||||
size_t i;
|
||||
int bytes_read;
|
||||
uint8_t* dst = br->buf_;
|
||||
if (br->next_in != br->buf_) {
|
||||
int num = (int)(br->avail_in);
|
||||
for (i = 0; i < num; i++) {
|
||||
for (i = 0; i < br->avail_in; i++) {
|
||||
br->buf_[i] = br->next_in[i];
|
||||
}
|
||||
br->next_in = br->buf_;
|
||||
br->tmp_bytes_read_ = num;
|
||||
}
|
||||
|
||||
bytes_read = BrotliRead(br->input_, dst + br->tmp_bytes_read_,
|
||||
(size_t) (BROTLI_READ_SIZE - br->tmp_bytes_read_));
|
||||
bytes_read = BrotliRead(br->input_, br->next_in + br->avail_in,
|
||||
(size_t)(BROTLI_READ_SIZE - br->avail_in));
|
||||
if (bytes_read < 0) {
|
||||
return 0;
|
||||
}
|
||||
bytes_read += br->tmp_bytes_read_;
|
||||
br->tmp_bytes_read_ = 0;
|
||||
if (bytes_read < BROTLI_READ_SIZE) {
|
||||
br->avail_in += (uint32_t)bytes_read;
|
||||
if (br->avail_in < BROTLI_READ_SIZE) {
|
||||
if (!finish) {
|
||||
br->tmp_bytes_read_ = bytes_read;
|
||||
return 0;
|
||||
}
|
||||
br->eos_ = 1;
|
||||
/* Store 128 bytes of zero after the stream end. */
|
||||
memset(dst + bytes_read, 0, 128);
|
||||
bytes_read += 128;
|
||||
/* Store BROTLI_IMPLICIT_ZEROES bytes of zero after the stream end. */
|
||||
memset(br->next_in + br->avail_in, 0, BROTLI_IMPLICIT_ZEROES);
|
||||
br->avail_in += BROTLI_IMPLICIT_ZEROES;
|
||||
}
|
||||
br->avail_in = (uint32_t)bytes_read;
|
||||
br->next_in = br->buf_;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -123,7 +113,8 @@ static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
|
||||
}
|
||||
|
||||
/* Checks if there is at least num bytes left in the input ringbuffer (excluding
|
||||
the bits remaining in br->val_). The maximum value for num is 128 bytes. */
|
||||
the bits remaining in br->val_). The maximum value for num is
|
||||
BROTLI_IMPLICIT_ZEROES bytes. */
|
||||
static BROTLI_INLINE int BrotliCheckInputAmount(
|
||||
BrotliBitReader* const br, size_t num) {
|
||||
return br->avail_in >= num;
|
||||
@ -134,28 +125,56 @@ static BROTLI_INLINE int BrotliCheckInputAmount(
|
||||
static BROTLI_INLINE void BrotliFillBitWindow(
|
||||
BrotliBitReader* const br, int n_bits) {
|
||||
#if (BROTLI_64_BITS_LITTLE_ENDIAN)
|
||||
if (br->bit_pos_ >= 32) {
|
||||
br->val_ >>= 32;
|
||||
br->bit_pos_ ^= 32; /* here same as -= 32 because of the if condition */
|
||||
br->val_ |= ((uint64_t)(*(const uint32_t*)(br->next_in))) << 32;
|
||||
br->avail_in -= 4;
|
||||
br->next_in += 4;
|
||||
if (IS_CONSTANT(n_bits) && n_bits <= 8) {
|
||||
if (br->bit_pos_ >= 56) {
|
||||
br->val_ >>= 56;
|
||||
br->bit_pos_ ^= 56; /* here same as -= 56 because of the if condition */
|
||||
br->val_ |= (*(const uint64_t*)(br->next_in)) << 8;
|
||||
br->avail_in -= 7;
|
||||
br->next_in += 7;
|
||||
}
|
||||
} else if (IS_CONSTANT(n_bits) && n_bits <= 16) {
|
||||
if (br->bit_pos_ >= 48) {
|
||||
br->val_ >>= 48;
|
||||
br->bit_pos_ ^= 48; /* here same as -= 48 because of the if condition */
|
||||
br->val_ |= (*(const uint64_t*)(br->next_in)) << 16;
|
||||
br->avail_in -= 6;
|
||||
br->next_in += 6;
|
||||
}
|
||||
} else {
|
||||
if (br->bit_pos_ >= 32) {
|
||||
br->val_ >>= 32;
|
||||
br->bit_pos_ ^= 32; /* here same as -= 32 because of the if condition */
|
||||
br->val_ |= ((uint64_t)(*(const uint32_t*)(br->next_in))) << 32;
|
||||
br->avail_in -= 4;
|
||||
br->next_in += 4;
|
||||
}
|
||||
}
|
||||
#elif (BROTLI_LITTLE_ENDIAN)
|
||||
if (br->bit_pos_ >= 16) {
|
||||
br->val_ >>= 16;
|
||||
br->bit_pos_ ^= 16; /* here same as -= 16 because of the if condition */
|
||||
br->val_ |= ((uint32_t)(*(const uint16_t*)(br->next_in))) << 16;
|
||||
br->avail_in -= 2;
|
||||
br->next_in += 2;
|
||||
}
|
||||
if (!IS_CONSTANT(n_bits) || (n_bits > 16)) {
|
||||
if (br->bit_pos_ >= 8) {
|
||||
br->val_ >>= 8;
|
||||
br->bit_pos_ ^= 8; /* here same as -= 8 because of the if condition */
|
||||
br->val_ |= ((uint32_t)*br->next_in) << 24;
|
||||
--br->avail_in;
|
||||
++br->next_in;
|
||||
if (IS_CONSTANT(n_bits) && n_bits <= 8) {
|
||||
if (br->bit_pos_ >= 24) {
|
||||
br->val_ >>= 24;
|
||||
br->bit_pos_ ^= 24; /* here same as -= 24 because of the if condition */
|
||||
br->val_ |= (*(const uint32_t*)(br->next_in)) << 8;
|
||||
br->avail_in -= 3;
|
||||
br->next_in += 3;
|
||||
}
|
||||
} else {
|
||||
if (br->bit_pos_ >= 16) {
|
||||
br->val_ >>= 16;
|
||||
br->bit_pos_ ^= 16; /* here same as -= 16 because of the if condition */
|
||||
br->val_ |= ((uint32_t)(*(const uint16_t*)(br->next_in))) << 16;
|
||||
br->avail_in -= 2;
|
||||
br->next_in += 2;
|
||||
}
|
||||
if (!IS_CONSTANT(n_bits) || (n_bits > 16)) {
|
||||
if (br->bit_pos_ >= 8) {
|
||||
br->val_ >>= 8;
|
||||
br->bit_pos_ ^= 8; /* here same as -= 8 because of the if condition */
|
||||
br->val_ |= ((uint32_t)*br->next_in) << 24;
|
||||
--br->avail_in;
|
||||
++br->next_in;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
1081
dec/decode.c
1081
dec/decode.c
File diff suppressed because it is too large
Load Diff
153
dec/huffman.c
153
dec/huffman.c
@ -25,19 +25,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_LENGTH 15
|
||||
|
||||
/* For current format this constant equals to kNumInsertAndCopyCodes */
|
||||
#define MAX_CODE_LENGTHS_SIZE 704
|
||||
|
||||
/* Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the
|
||||
bit-wise reversal of the len least significant bits of key. */
|
||||
static BROTLI_INLINE int GetNextKey(int key, int len) {
|
||||
int step = 1 << (len - 1);
|
||||
static BROTLI_INLINE uint32_t GetNextKey(uint32_t key, int len) {
|
||||
#ifdef BROTLI_RBIT
|
||||
return BROTLI_RBIT(BROTLI_RBIT(key) + (1 << (8 * sizeof(unsigned) - len)));
|
||||
#else
|
||||
unsigned step = (unsigned)(1 << (len - 1));
|
||||
while (key & step) {
|
||||
step >>= 1;
|
||||
}
|
||||
return (key & (step - 1)) + step;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Stores code in table[0], table[step], table[2*step], ..., table[end] */
|
||||
@ -57,7 +56,7 @@ static BROTLI_INLINE void ReplicateValue(HuffmanCode* table,
|
||||
static BROTLI_INLINE int NextTableBitSize(const uint16_t* const count,
|
||||
int len, int root_bits) {
|
||||
int left = 1 << (len - root_bits);
|
||||
while (len < MAX_LENGTH) {
|
||||
while (len < BROTLI_HUFFMAN_MAX_CODE_LENGTH) {
|
||||
left -= count[len];
|
||||
if (left <= 0) break;
|
||||
++len;
|
||||
@ -66,66 +65,95 @@ static BROTLI_INLINE int NextTableBitSize(const uint16_t* const count,
|
||||
return len - root_bits;
|
||||
}
|
||||
|
||||
|
||||
void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
|
||||
const uint8_t* const code_lengths,
|
||||
uint16_t *count) {
|
||||
HuffmanCode code; /* current table entry */
|
||||
int symbol; /* symbol index in original or sorted table */
|
||||
unsigned key; /* reversed prefix code */
|
||||
int step; /* step size to replicate values in current table */
|
||||
int table_size; /* size of current table */
|
||||
int sorted[18]; /* symbols sorted by code length */
|
||||
/* offsets in sorted table for each length */
|
||||
int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1];
|
||||
int bits;
|
||||
int bits_count;
|
||||
|
||||
/* generate offsets into sorted symbol table by code length */
|
||||
symbol = -1;
|
||||
bits = 1;
|
||||
BROTLI_REPEAT(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH, {
|
||||
symbol += count[bits];
|
||||
offset[bits] = symbol;
|
||||
bits++;
|
||||
});
|
||||
offset[0] = 17;
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
symbol = 18;
|
||||
do {
|
||||
BROTLI_REPEAT(6, {
|
||||
symbol--;
|
||||
sorted[offset[code_lengths[symbol]]--] = symbol;
|
||||
});
|
||||
} while (symbol != 0);
|
||||
|
||||
table_size = 1 << BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH;
|
||||
|
||||
/* special case code with only one value */
|
||||
if (offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH] == 0) {
|
||||
code.bits = 0;
|
||||
code.value = (uint16_t)sorted[0];
|
||||
for (key = 0; key < table_size; ++key) {
|
||||
table[key] = code;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill in table */
|
||||
key = 0;
|
||||
symbol = 0;
|
||||
bits = 1;
|
||||
step = 2;
|
||||
do {
|
||||
code.bits = (uint8_t)bits;
|
||||
for (bits_count = count[bits]; bits_count != 0; --bits_count) {
|
||||
code.value = (uint16_t)sorted[symbol++];
|
||||
ReplicateValue(&table[key], step, table_size, code);
|
||||
key = GetNextKey(key, bits);
|
||||
}
|
||||
step <<= 1;
|
||||
} while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
|
||||
}
|
||||
|
||||
int BrotliBuildHuffmanTable(HuffmanCode* root_table,
|
||||
int root_bits,
|
||||
const uint8_t* const code_lengths,
|
||||
int code_lengths_size,
|
||||
const uint16_t* const symbol_lists,
|
||||
uint16_t *count) {
|
||||
HuffmanCode code; /* current table entry */
|
||||
HuffmanCode* table; /* next available space in table */
|
||||
int len; /* current code length */
|
||||
int symbol; /* symbol index in original or sorted table */
|
||||
int key; /* reversed prefix code */
|
||||
int symbol; /* symbol index in original or sorted table */
|
||||
unsigned key; /* reversed prefix code */
|
||||
int step; /* step size to replicate values in current table */
|
||||
int low; /* low bits for current root entry */
|
||||
int mask; /* mask for low bits */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low bits */
|
||||
int table_bits; /* key length of current table */
|
||||
int table_size; /* size of current table */
|
||||
int total_size; /* sum of root table size and 2nd level table sizes */
|
||||
/* symbols sorted by code length */
|
||||
uint16_t sorted[MAX_CODE_LENGTHS_SIZE];
|
||||
/* offsets in sorted table for each length */
|
||||
uint16_t offset[MAX_LENGTH + 1];
|
||||
int max_length = 1;
|
||||
int max_length = -1;
|
||||
int bits;
|
||||
int bits_count;
|
||||
|
||||
if (PREDICT_FALSE(code_lengths_size > MAX_CODE_LENGTHS_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generate offsets into sorted symbol table by code length */
|
||||
{
|
||||
uint16_t sum = 0;
|
||||
for (len = 1; len <= MAX_LENGTH; len++) {
|
||||
offset[len] = sum;
|
||||
if (count[len]) {
|
||||
sum = (uint16_t)(sum + count[len]);
|
||||
max_length = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (symbol = 0; symbol < code_lengths_size; symbol++) {
|
||||
if (code_lengths[symbol] != 0) {
|
||||
sorted[offset[code_lengths[symbol]]++] = (uint16_t)symbol;
|
||||
}
|
||||
}
|
||||
while (symbol_lists[max_length] == 0xFFFF) max_length--;
|
||||
max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1;
|
||||
|
||||
table = root_table;
|
||||
table_bits = root_bits;
|
||||
table_size = 1 << table_bits;
|
||||
total_size = table_size;
|
||||
|
||||
/* special case code with only one value */
|
||||
if (offset[MAX_LENGTH] == 1) {
|
||||
code.bits = 0;
|
||||
code.value = (uint16_t)sorted[0];
|
||||
for (key = 0; key < total_size; ++key) {
|
||||
table[key] = code;
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
/* fill in root table */
|
||||
/* let's reduce the table size to a smaller size if possible, and */
|
||||
/* create the repetitions by memcpy if possible in the coming loop */
|
||||
@ -134,17 +162,19 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
|
||||
table_size = 1 << table_bits;
|
||||
}
|
||||
key = 0;
|
||||
symbol = 0;
|
||||
code.bits = 1;
|
||||
bits = 1;
|
||||
step = 2;
|
||||
do {
|
||||
for (; count[code.bits] != 0; --count[code.bits]) {
|
||||
code.value = (uint16_t)sorted[symbol++];
|
||||
code.bits = (uint8_t)bits;
|
||||
symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
|
||||
for (bits_count = count[bits]; bits_count != 0; --bits_count) {
|
||||
symbol = symbol_lists[symbol];
|
||||
code.value = (uint16_t)symbol;
|
||||
ReplicateValue(&table[key], step, table_size, code);
|
||||
key = GetNextKey(key, code.bits);
|
||||
key = GetNextKey(key, bits);
|
||||
}
|
||||
step <<= 1;
|
||||
} while (++code.bits <= table_bits);
|
||||
} while (++bits <= table_bits);
|
||||
|
||||
/* if root_bits != table_bits we only created one fraction of the */
|
||||
/* table, and we need to replicate it now. */
|
||||
@ -155,9 +185,10 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
|
||||
}
|
||||
|
||||
/* fill in 2nd level tables and add pointers to root table */
|
||||
mask = total_size - 1;
|
||||
low = -1;
|
||||
mask = (unsigned)(total_size - 1);
|
||||
low = (unsigned)-1;
|
||||
for (len = root_bits + 1, step = 2; len <= max_length; ++len, step <<= 1) {
|
||||
symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
|
||||
for (; count[len] != 0; --count[len]) {
|
||||
if ((key & mask) != low) {
|
||||
table += table_size;
|
||||
@ -169,12 +200,12 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
|
||||
root_table[low].value = (uint16_t)((table - root_table) - low);
|
||||
}
|
||||
code.bits = (uint8_t)(len - root_bits);
|
||||
code.value = (uint16_t)sorted[symbol++];
|
||||
symbol = symbol_lists[symbol];
|
||||
code.value = (uint16_t)symbol;
|
||||
ReplicateValue(&table[key >> root_bits], step, table_size, code);
|
||||
key = GetNextKey(key, len);
|
||||
}
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
|
@ -24,21 +24,33 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15
|
||||
|
||||
/* For current format this constant equals to kNumInsertAndCopyCodes */
|
||||
#define BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE 704
|
||||
|
||||
/* Maximum possible Huffman table size for an alphabet size of 704, max code
|
||||
* length 15 and root table bits 8. */
|
||||
#define BROTLI_HUFFMAN_MAX_TABLE_SIZE 1080
|
||||
#define BROTLI_HUFFMAN_MAX_TABLE_SIZE 1080
|
||||
|
||||
#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5
|
||||
|
||||
typedef struct {
|
||||
uint8_t bits; /* number of bits used for this symbol */
|
||||
uint16_t value; /* symbol value or table offset */
|
||||
} HuffmanCode;
|
||||
|
||||
|
||||
/* Builds Huffman lookup table assuming code lengths are in symbol order. */
|
||||
/* Returns false in case of error (invalid tree or memory error). */
|
||||
void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
|
||||
const uint8_t* const code_lengths,
|
||||
uint16_t *count);
|
||||
|
||||
/* Builds Huffman lookup table assuming code lengths are in symbol order. */
|
||||
/* Returns size of resulting table. */
|
||||
int BrotliBuildHuffmanTable(HuffmanCode* root_table,
|
||||
int root_bits,
|
||||
const uint8_t* const code_lengths,
|
||||
int code_lengths_size,
|
||||
const uint16_t* const symbol_lists,
|
||||
uint16_t *count_arg);
|
||||
|
||||
int BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
|
||||
|
17
dec/port.h
17
dec/port.h
@ -130,4 +130,21 @@ OR:
|
||||
#define BROTLI_NO_ASAN
|
||||
#endif
|
||||
|
||||
#define BROTLI_REPEAT(N, X) { \
|
||||
if ((N & 1) != 0) {X;} \
|
||||
if ((N & 2) != 0) {X; X;} \
|
||||
if ((N & 4) != 0) {X; X; X; X;} \
|
||||
}
|
||||
|
||||
#if (__GNUC__ > 2) || defined(__llvm__)
|
||||
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
|
||||
static BROTLI_INLINE unsigned BrotliRBit(unsigned input) {
|
||||
unsigned output;
|
||||
__asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
|
||||
return output;
|
||||
}
|
||||
#define BROTLI_RBIT(x) BrotliRBit(x)
|
||||
#endif /* armv7 */
|
||||
#endif /* gcc || clang */
|
||||
|
||||
#endif /* BROTLI_DEC_PORT_H_ */
|
||||
|
1419
dec/prefix.h
1419
dec/prefix.h
File diff suppressed because it is too large
Load Diff
14
dec/state.c
14
dec/state.c
@ -45,9 +45,6 @@ void BrotliStateInit(BrotliState* s) {
|
||||
s->distance_hgroup.codes = NULL;
|
||||
s->distance_hgroup.htrees = NULL;
|
||||
|
||||
s->code_lengths = NULL;
|
||||
s->context_map_table = NULL;
|
||||
|
||||
s->custom_dict = NULL;
|
||||
s->custom_dict_size = 0;
|
||||
|
||||
@ -62,6 +59,9 @@ void BrotliStateInit(BrotliState* s) {
|
||||
s->block_type_trees = NULL;
|
||||
s->block_len_trees = NULL;
|
||||
|
||||
/* Make small negative indexes addressable. */
|
||||
s->symbol_lists = &s->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
|
||||
|
||||
s->mtf_upper_bound = 255;
|
||||
}
|
||||
|
||||
@ -84,6 +84,7 @@ void BrotliStateMetablockBegin(BrotliState* s) {
|
||||
s->dist_context_map = NULL;
|
||||
s->context_map_slice = NULL;
|
||||
s->literal_htree_index = 0;
|
||||
s->literal_htree = NULL;
|
||||
s->dist_context_map_slice = NULL;
|
||||
s->dist_htree_index = 0;
|
||||
s->context_lookup1 = NULL;
|
||||
@ -122,13 +123,6 @@ void BrotliStateCleanupAfterMetablock(BrotliState* s) {
|
||||
}
|
||||
|
||||
void BrotliStateCleanup(BrotliState* s) {
|
||||
if (s->context_map_table != 0) {
|
||||
free(s->context_map_table);
|
||||
}
|
||||
if (s->code_lengths != 0) {
|
||||
free(s->code_lengths);
|
||||
}
|
||||
|
||||
if (s->context_modes != 0) {
|
||||
free(s->context_modes);
|
||||
}
|
||||
|
104
dec/state.h
104
dec/state.h
@ -34,17 +34,15 @@ typedef enum {
|
||||
BROTLI_STATE_METABLOCK_BEGIN,
|
||||
BROTLI_STATE_METABLOCK_HEADER_1,
|
||||
BROTLI_STATE_METABLOCK_HEADER_2,
|
||||
BROTLI_STATE_BLOCK_BEGIN,
|
||||
BROTLI_STATE_BLOCK_INNER,
|
||||
BROTLI_STATE_BLOCK_DISTANCE,
|
||||
BROTLI_STATE_BLOCK_POST,
|
||||
BROTLI_STATE_COMMAND_BEGIN,
|
||||
BROTLI_STATE_COMMAND_INNER,
|
||||
BROTLI_STATE_UNCOMPRESSED,
|
||||
BROTLI_STATE_METADATA,
|
||||
BROTLI_STATE_BLOCK_INNER_WRITE,
|
||||
BROTLI_STATE_COMMAND_INNER_WRITE,
|
||||
BROTLI_STATE_METABLOCK_DONE,
|
||||
BROTLI_STATE_BLOCK_POST_WRITE_1,
|
||||
BROTLI_STATE_BLOCK_POST_WRITE_2,
|
||||
BROTLI_STATE_BLOCK_POST_WRAP_COPY,
|
||||
BROTLI_STATE_COMMAND_POST_WRITE_1,
|
||||
BROTLI_STATE_COMMAND_POST_WRITE_2,
|
||||
BROTLI_STATE_COMMAND_POST_WRAP_COPY,
|
||||
BROTLI_STATE_HUFFMAN_CODE_0,
|
||||
BROTLI_STATE_HUFFMAN_CODE_1,
|
||||
BROTLI_STATE_HUFFMAN_CODE_2,
|
||||
@ -70,92 +68,76 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
BROTLI_STATE_SUB1_NONE,
|
||||
BROTLI_STATE_SUB1_HUFFMAN_LENGTH_BEGIN,
|
||||
BROTLI_STATE_SUB1_HUFFMAN_LENGTH_SYMBOLS,
|
||||
BROTLI_STATE_SUB1_HUFFMAN_DONE
|
||||
BROTLI_STATE_SUB1_HUFFMAN_LENGTH_SYMBOLS
|
||||
} BrotliRunningSub1State;
|
||||
|
||||
typedef struct {
|
||||
BrotliRunningState state;
|
||||
BrotliRunningSub0State sub0_state; /* State inside function call */
|
||||
BrotliRunningSub1State sub1_state; /* State inside function call */
|
||||
|
||||
/* This counter is reused for several disjoint loops. */
|
||||
BrotliBitReader br;
|
||||
int loop_counter;
|
||||
int pos;
|
||||
int input_end;
|
||||
uint32_t window_bits;
|
||||
int max_backward_distance;
|
||||
int max_backward_distance_minus_custom_dict_size;
|
||||
int max_distance;
|
||||
int ringbuffer_size;
|
||||
int ringbuffer_mask;
|
||||
int dist_rb_idx;
|
||||
int dist_rb[4];
|
||||
uint8_t* ringbuffer;
|
||||
uint8_t* ringbuffer_end;
|
||||
HuffmanCode* htree_command;
|
||||
const uint8_t* context_lookup1;
|
||||
const uint8_t* context_lookup2;
|
||||
uint8_t* context_map_slice;
|
||||
uint8_t* dist_context_map_slice;
|
||||
|
||||
/* This ring buffer holds a few past copy distances that will be used by */
|
||||
/* some special distance codes. */
|
||||
int dist_rb[4];
|
||||
int dist_rb_idx;
|
||||
HuffmanTreeGroup literal_hgroup;
|
||||
HuffmanTreeGroup insert_copy_hgroup;
|
||||
HuffmanTreeGroup distance_hgroup;
|
||||
|
||||
HuffmanCode* block_type_trees;
|
||||
HuffmanCode* block_len_trees;
|
||||
BrotliBitReader br;
|
||||
/* This counter is reused for several disjoint loops. */
|
||||
int loop_counter;
|
||||
/* This is true if the literal context map histogram type always matches the
|
||||
block type. It is then not needed to keep the context (faster decoding). */
|
||||
int trivial_literal_context;
|
||||
|
||||
int distance_context;
|
||||
int meta_block_remaining_len;
|
||||
int is_metadata;
|
||||
int is_uncompressed;
|
||||
int block_length[3];
|
||||
int num_block_types[3];
|
||||
int block_type_rb[6];
|
||||
int distance_postfix_bits;
|
||||
int num_direct_distance_codes;
|
||||
int distance_postfix_mask;
|
||||
uint8_t* context_map;
|
||||
uint8_t* context_modes;
|
||||
int num_literal_htrees;
|
||||
uint8_t* dist_context_map;
|
||||
int num_dist_htrees;
|
||||
uint8_t* context_map_slice;
|
||||
uint8_t* dist_context_map_slice;
|
||||
uint8_t literal_htree_index;
|
||||
HuffmanCode *literal_htree;
|
||||
uint8_t dist_htree_index;
|
||||
uint8_t prev_code_len;
|
||||
uint8_t repeat_code_len;
|
||||
|
||||
const uint8_t* context_lookup1;
|
||||
const uint8_t* context_lookup2;
|
||||
HuffmanCode* htree_command;
|
||||
uint8_t prev_code_len;
|
||||
|
||||
int copy_length;
|
||||
int distance_code;
|
||||
int distance;
|
||||
|
||||
/* For CopyUncompressedBlockToOutput */
|
||||
int nbytes;
|
||||
|
||||
/* For partial write operations */
|
||||
int to_write;
|
||||
int partially_written;
|
||||
|
||||
/* For HuffmanTreeGroupDecode */
|
||||
int htrees_decoded;
|
||||
|
||||
/* For ReadHuffmanCodeLengths */
|
||||
int symbol;
|
||||
int repeat;
|
||||
int space;
|
||||
HuffmanCode table[32];
|
||||
uint8_t code_length_code_lengths[18];
|
||||
|
||||
/* For ReadHuffmanCode */
|
||||
uint8_t* code_lengths;
|
||||
/* The maximum non-zero code length index in code lengths */
|
||||
uint32_t huffman_max_nonzero;
|
||||
uint32_t symbol;
|
||||
uint32_t repeat;
|
||||
uint32_t space;
|
||||
|
||||
HuffmanCode table[32];
|
||||
/* List of of symbol chains. */
|
||||
uint16_t* symbol_lists;
|
||||
/* Storage from symbol_lists. */
|
||||
uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
|
||||
BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE];
|
||||
/* Tails of symbol chains. */
|
||||
int next_symbol[32];
|
||||
uint8_t code_length_code_lengths[18];
|
||||
/* Population counts for the code lengths */
|
||||
uint16_t code_length_histo[16];
|
||||
|
||||
@ -166,7 +148,7 @@ typedef struct {
|
||||
/* For DecodeContextMap */
|
||||
int context_index;
|
||||
int max_run_length_prefix;
|
||||
HuffmanCode* context_map_table;
|
||||
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_TABLE_SIZE];
|
||||
|
||||
/* For InverseMoveToFrontTransform */
|
||||
int mtf_upper_bound;
|
||||
@ -175,6 +157,20 @@ typedef struct {
|
||||
/* For custom dictionaries */
|
||||
const uint8_t* custom_dict;
|
||||
int custom_dict_size;
|
||||
|
||||
/* less used attributes are in the end of this struct */
|
||||
BrotliRunningSub0State sub0_state; /* State inside function call */
|
||||
BrotliRunningSub1State sub1_state; /* State inside function call */
|
||||
|
||||
int input_end;
|
||||
uint32_t window_bits;
|
||||
|
||||
/* For CopyUncompressedBlockToOutput */
|
||||
int nbytes;
|
||||
|
||||
int num_literal_htrees;
|
||||
uint8_t* context_map;
|
||||
uint8_t* context_modes;
|
||||
} BrotliState;
|
||||
|
||||
void BrotliStateInit(BrotliState* s);
|
||||
|
Loading…
Reference in New Issue
Block a user