mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 02:08:38 +09:00
import changes from tenfourfox:
- #622: update brotli to 1.0.9, woff2 to tip (7c24b77e7) - #622: actually add new brotli files (fc50954e6)
This commit is contained in:
parent
64ccce7c22
commit
1bdcd46977
64 changed files with 3990 additions and 2780 deletions
|
|
@ -15,6 +15,17 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
const uint32_t kBrotliBitMask[33] = { 0x00000000,
|
||||
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
|
||||
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
|
||||
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
|
||||
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
|
||||
0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
|
||||
0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
|
||||
0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
|
||||
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
void BrotliInitBitReader(BrotliBitReader* const br) {
|
||||
br->val_ = 0;
|
||||
br->bit_pos_ = sizeof(br->val_) << 3;
|
||||
|
|
@ -43,6 +54,23 @@ BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
|
|||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
BROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,
|
||||
uint32_t n_bits, uint32_t* val) {
|
||||
uint32_t low_val;
|
||||
uint32_t high_val;
|
||||
BrotliBitReaderState memento;
|
||||
BROTLI_DCHECK(n_bits <= 32);
|
||||
BROTLI_DCHECK(n_bits > 24);
|
||||
BrotliBitReaderSaveState(br, &memento);
|
||||
if (!BrotliSafeReadBits(br, 16, &low_val) ||
|
||||
!BrotliSafeReadBits(br, n_bits - 16, &high_val)) {
|
||||
BrotliBitReaderRestoreState(br, &memento);
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
*val = low_val | (high_val << 16);
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
#include "../common/constants.h"
|
||||
#include "../common/platform.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
|
|
@ -20,16 +21,7 @@ extern "C" {
|
|||
|
||||
#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)
|
||||
|
||||
static const uint32_t kBitMask[33] = { 0x00000000,
|
||||
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
|
||||
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
|
||||
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
|
||||
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
|
||||
0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
|
||||
0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
|
||||
0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
|
||||
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
|
||||
};
|
||||
BROTLI_INTERNAL extern const uint32_t kBrotliBitMask[33];
|
||||
|
||||
static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
|
||||
if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) {
|
||||
|
|
@ -37,7 +29,7 @@ static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
|
|||
"Unsigned Bit Field Extract" UBFX instruction on ARM. */
|
||||
return ~((0xFFFFFFFFu) << n);
|
||||
} else {
|
||||
return kBitMask[n];
|
||||
return kBrotliBitMask[n];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +57,12 @@ BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
|
|||
reading. */
|
||||
BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);
|
||||
|
||||
/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
|
||||
the main code-path. Never called for RFC brotli streams, required only for
|
||||
"large-window" mode and other extensions. */
|
||||
BROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val);
|
||||
|
||||
static BROTLI_INLINE void BrotliBitReaderSaveState(
|
||||
BrotliBitReader* const from, BrotliBitReaderState* to) {
|
||||
to->val_ = from->val_;
|
||||
|
|
@ -87,8 +85,11 @@ static BROTLI_INLINE uint32_t BrotliGetAvailableBits(
|
|||
}
|
||||
|
||||
/* Returns amount of unread bytes the bit reader still has buffered from the
|
||||
BrotliInput, including whole bytes in br->val_. */
|
||||
BrotliInput, including whole bytes in br->val_. Result is capped with
|
||||
maximal ring-buffer size (larger number won't be utilized anyway). */
|
||||
static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
|
||||
static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;
|
||||
if (br->avail_in > kCap) return kCap;
|
||||
return br->avail_in + (BrotliGetAvailableBits(br) >> 3);
|
||||
}
|
||||
|
||||
|
|
@ -237,15 +238,17 @@ static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {
|
|||
static BROTLI_INLINE void BrotliTakeBits(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
*val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
BROTLI_LOG(("[BrotliReadBits] %d %d %d val: %6x\n",
|
||||
BROTLI_LOG(("[BrotliTakeBits] %d %d %d val: %6x\n",
|
||||
(int)br->avail_in, (int)br->bit_pos_, (int)n_bits, (int)*val));
|
||||
BrotliDropBits(br, n_bits);
|
||||
}
|
||||
|
||||
/* Reads the specified number of bits from |br| and advances the bit pos.
|
||||
Assumes that there is enough input to perform BrotliFillBitWindow. */
|
||||
static BROTLI_INLINE uint32_t BrotliReadBits(
|
||||
Assumes that there is enough input to perform BrotliFillBitWindow.
|
||||
Up to 24 bits are allowed to be requested from this method. */
|
||||
static BROTLI_INLINE uint32_t BrotliReadBits24(
|
||||
BrotliBitReader* const br, uint32_t n_bits) {
|
||||
BROTLI_DCHECK(n_bits <= 24);
|
||||
if (BROTLI_64_BITS || (n_bits <= 16)) {
|
||||
uint32_t val;
|
||||
BrotliFillBitWindow(br, n_bits);
|
||||
|
|
@ -262,10 +265,32 @@ static BROTLI_INLINE uint32_t BrotliReadBits(
|
|||
}
|
||||
}
|
||||
|
||||
/* Same as BrotliReadBits24, but allows reading up to 32 bits. */
|
||||
static BROTLI_INLINE uint32_t BrotliReadBits32(
|
||||
BrotliBitReader* const br, uint32_t n_bits) {
|
||||
BROTLI_DCHECK(n_bits <= 32);
|
||||
if (BROTLI_64_BITS || (n_bits <= 16)) {
|
||||
uint32_t val;
|
||||
BrotliFillBitWindow(br, n_bits);
|
||||
BrotliTakeBits(br, n_bits, &val);
|
||||
return val;
|
||||
} else {
|
||||
uint32_t low_val;
|
||||
uint32_t high_val;
|
||||
BrotliFillBitWindow(br, 16);
|
||||
BrotliTakeBits(br, 16, &low_val);
|
||||
BrotliFillBitWindow(br, 16);
|
||||
BrotliTakeBits(br, n_bits - 16, &high_val);
|
||||
return low_val | (high_val << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there
|
||||
is not enough input. |n_bits| MUST be positive. */
|
||||
is not enough input. |n_bits| MUST be positive.
|
||||
Up to 24 bits are allowed to be requested from this method. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
BROTLI_DCHECK(n_bits <= 24);
|
||||
while (BrotliGetAvailableBits(br) < n_bits) {
|
||||
if (!BrotliPullByte(br)) {
|
||||
return BROTLI_FALSE;
|
||||
|
|
@ -275,6 +300,23 @@ static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
|
|||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
BROTLI_DCHECK(n_bits <= 32);
|
||||
if (BROTLI_64_BITS || (n_bits <= 24)) {
|
||||
while (BrotliGetAvailableBits(br) < n_bits) {
|
||||
if (!BrotliPullByte(br)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
BrotliTakeBits(br, n_bits, val);
|
||||
return BROTLI_TRUE;
|
||||
} else {
|
||||
return BrotliSafeReadBits32Slow(br, n_bits, val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Advances the bit reader position to the next byte boundary and verifies
|
||||
that any skipped bits are set to zero. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ extern "C" {
|
|||
|
||||
/* We need the slack region for the following reasons:
|
||||
- doing up to two 16-byte copies for fast backward copying
|
||||
- inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */
|
||||
- inserting transformed dictionary word:
|
||||
5 prefix + 24 base + 8 suffix */
|
||||
static const uint32_t kRingBufferWriteAheadSlack = 42;
|
||||
|
||||
static const uint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = {
|
||||
|
|
@ -274,7 +275,8 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|||
s->loop_counter = i;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
if (i + 1 == s->size_nibbles && s->size_nibbles > 4 && bits == 0) {
|
||||
if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 &&
|
||||
bits == 0) {
|
||||
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);
|
||||
}
|
||||
s->meta_block_remaining_len |= (int)(bits << (i * 4));
|
||||
|
|
@ -323,7 +325,8 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
|
|||
s->loop_counter = i;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
if (i + 1 == s->size_nibbles && s->size_nibbles > 1 && bits == 0) {
|
||||
if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 &&
|
||||
bits == 0) {
|
||||
return BROTLI_FAILURE(
|
||||
BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
|
||||
}
|
||||
|
|
@ -470,32 +473,34 @@ static BROTLI_INLINE uint32_t Log2Floor(uint32_t x) {
|
|||
Totally 1..4 symbols are read, 1..11 bits each.
|
||||
The list of symbols MUST NOT contain duplicates. */
|
||||
static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
|
||||
uint32_t alphabet_size, uint32_t max_symbol, BrotliDecoderState* s) {
|
||||
uint32_t alphabet_size_max, uint32_t alphabet_size_limit,
|
||||
BrotliDecoderState* s) {
|
||||
/* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */
|
||||
BrotliBitReader* br = &s->br;
|
||||
uint32_t max_bits = Log2Floor(alphabet_size - 1);
|
||||
uint32_t i = s->sub_loop_counter;
|
||||
uint32_t num_symbols = s->symbol;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
uint32_t max_bits = Log2Floor(alphabet_size_max - 1);
|
||||
uint32_t i = h->sub_loop_counter;
|
||||
uint32_t num_symbols = h->symbol;
|
||||
while (i <= num_symbols) {
|
||||
uint32_t v;
|
||||
if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {
|
||||
s->sub_loop_counter = i;
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
|
||||
h->sub_loop_counter = i;
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
if (v >= max_symbol) {
|
||||
if (v >= alphabet_size_limit) {
|
||||
return
|
||||
BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
|
||||
}
|
||||
s->symbols_lists_array[i] = (uint16_t)v;
|
||||
BROTLI_LOG_UINT(s->symbols_lists_array[i]);
|
||||
h->symbols_lists_array[i] = (uint16_t)v;
|
||||
BROTLI_LOG_UINT(h->symbols_lists_array[i]);
|
||||
++i;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_symbols; ++i) {
|
||||
uint32_t k = i + 1;
|
||||
for (; k <= num_symbols; ++k) {
|
||||
if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) {
|
||||
if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) {
|
||||
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
|
||||
}
|
||||
}
|
||||
|
|
@ -588,27 +593,28 @@ static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len,
|
|||
static BrotliDecoderErrorCode ReadSymbolCodeLengths(
|
||||
uint32_t alphabet_size, BrotliDecoderState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
uint32_t symbol = s->symbol;
|
||||
uint32_t repeat = s->repeat;
|
||||
uint32_t space = s->space;
|
||||
uint32_t prev_code_len = s->prev_code_len;
|
||||
uint32_t repeat_code_len = s->repeat_code_len;
|
||||
uint16_t* symbol_lists = s->symbol_lists;
|
||||
uint16_t* code_length_histo = s->code_length_histo;
|
||||
int* next_symbol = s->next_symbol;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
uint32_t symbol = h->symbol;
|
||||
uint32_t repeat = h->repeat;
|
||||
uint32_t space = h->space;
|
||||
uint32_t prev_code_len = h->prev_code_len;
|
||||
uint32_t repeat_code_len = h->repeat_code_len;
|
||||
uint16_t* symbol_lists = h->symbol_lists;
|
||||
uint16_t* code_length_histo = h->code_length_histo;
|
||||
int* next_symbol = h->next_symbol;
|
||||
if (!BrotliWarmupBitReader(br)) {
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
while (symbol < alphabet_size && space > 0) {
|
||||
const HuffmanCode* p = s->table;
|
||||
const HuffmanCode* p = h->table;
|
||||
uint32_t code_len;
|
||||
BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
|
||||
if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) {
|
||||
s->symbol = symbol;
|
||||
s->repeat = repeat;
|
||||
s->prev_code_len = prev_code_len;
|
||||
s->repeat_code_len = repeat_code_len;
|
||||
s->space = space;
|
||||
h->symbol = symbol;
|
||||
h->repeat = repeat;
|
||||
h->prev_code_len = prev_code_len;
|
||||
h->repeat_code_len = repeat_code_len;
|
||||
h->space = space;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
BrotliFillBitWindow16(br);
|
||||
|
|
@ -630,16 +636,17 @@ static BrotliDecoderErrorCode ReadSymbolCodeLengths(
|
|||
symbol_lists, code_length_histo, next_symbol);
|
||||
}
|
||||
}
|
||||
s->space = space;
|
||||
h->space = space;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
|
||||
uint32_t alphabet_size, BrotliDecoderState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
BROTLI_BOOL get_byte = BROTLI_FALSE;
|
||||
while (s->symbol < alphabet_size && s->space > 0) {
|
||||
const HuffmanCode* p = s->table;
|
||||
while (h->symbol < alphabet_size && h->space > 0) {
|
||||
const HuffmanCode* p = h->table;
|
||||
uint32_t code_len;
|
||||
uint32_t available_bits;
|
||||
uint32_t bits = 0;
|
||||
|
|
@ -659,9 +666,9 @@ static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
|
|||
code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
|
||||
if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
|
||||
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));
|
||||
ProcessSingleCodeLength(code_len, &s->symbol, &s->repeat, &s->space,
|
||||
&s->prev_code_len, s->symbol_lists, s->code_length_histo,
|
||||
s->next_symbol);
|
||||
ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space,
|
||||
&h->prev_code_len, h->symbol_lists, h->code_length_histo,
|
||||
h->next_symbol);
|
||||
} else { /* code_len == 16..17, extra_bits == 2..3 */
|
||||
uint32_t extra_bits = code_len - 14U;
|
||||
uint32_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &
|
||||
|
|
@ -672,9 +679,9 @@ static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
|
|||
}
|
||||
BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);
|
||||
ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
|
||||
&s->symbol, &s->repeat, &s->space, &s->prev_code_len,
|
||||
&s->repeat_code_len, s->symbol_lists, s->code_length_histo,
|
||||
s->next_symbol);
|
||||
&h->symbol, &h->repeat, &h->space, &h->prev_code_len,
|
||||
&h->repeat_code_len, h->symbol_lists, h->code_length_histo,
|
||||
h->next_symbol);
|
||||
}
|
||||
}
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
|
|
@ -684,9 +691,10 @@ static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
|
|||
Each code is 2..4 bits long. In total 30..72 bits are used. */
|
||||
static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
uint32_t num_codes = s->repeat;
|
||||
unsigned space = s->space;
|
||||
uint32_t i = s->sub_loop_counter;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
uint32_t num_codes = h->repeat;
|
||||
unsigned space = h->space;
|
||||
uint32_t i = h->sub_loop_counter;
|
||||
for (; i < BROTLI_CODE_LENGTH_CODES; ++i) {
|
||||
const uint8_t code_len_idx = kCodeLengthCodeOrder[i];
|
||||
uint32_t ix;
|
||||
|
|
@ -699,21 +707,21 @@ static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
|
|||
ix = 0;
|
||||
}
|
||||
if (kCodeLengthPrefixLength[ix] > available_bits) {
|
||||
s->sub_loop_counter = i;
|
||||
s->repeat = num_codes;
|
||||
s->space = space;
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
|
||||
h->sub_loop_counter = i;
|
||||
h->repeat = num_codes;
|
||||
h->space = space;
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
}
|
||||
v = kCodeLengthPrefixValue[ix];
|
||||
BrotliDropBits(br, kCodeLengthPrefixLength[ix]);
|
||||
s->code_length_code_lengths[code_len_idx] = (uint8_t)v;
|
||||
BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx);
|
||||
h->code_length_code_lengths[code_len_idx] = (uint8_t)v;
|
||||
BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx);
|
||||
if (v != 0) {
|
||||
space = space - (32U >> v);
|
||||
++num_codes;
|
||||
++s->code_length_histo[v];
|
||||
++h->code_length_histo[v];
|
||||
if (space - 1U >= 32U) {
|
||||
/* space is 0 or wrapped around. */
|
||||
break;
|
||||
|
|
@ -737,49 +745,48 @@ static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
|
|||
encoded with predefined entropy code. 32 - 74 bits are used.
|
||||
B.2) Decoded table is used to decode code lengths of symbols in resulting
|
||||
Huffman table. In worst case 3520 bits are read. */
|
||||
static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
||||
uint32_t max_symbol,
|
||||
static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size_max,
|
||||
uint32_t alphabet_size_limit,
|
||||
HuffmanCode* table,
|
||||
uint32_t* opt_table_size,
|
||||
BrotliDecoderState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
/* Unnecessary masking, but might be good for safety. */
|
||||
alphabet_size &= 0x7FF;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
/* State machine. */
|
||||
for (;;) {
|
||||
switch (s->substate_huffman) {
|
||||
switch (h->substate_huffman) {
|
||||
case BROTLI_STATE_HUFFMAN_NONE:
|
||||
if (!BrotliSafeReadBits(br, 2, &s->sub_loop_counter)) {
|
||||
if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) {
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
BROTLI_LOG_UINT(s->sub_loop_counter);
|
||||
BROTLI_LOG_UINT(h->sub_loop_counter);
|
||||
/* The value is used as follows:
|
||||
1 for simple code;
|
||||
0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
|
||||
if (s->sub_loop_counter != 1) {
|
||||
s->space = 32;
|
||||
s->repeat = 0; /* num_codes */
|
||||
memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo[0]) *
|
||||
if (h->sub_loop_counter != 1) {
|
||||
h->space = 32;
|
||||
h->repeat = 0; /* num_codes */
|
||||
memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo[0]) *
|
||||
(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));
|
||||
memset(&s->code_length_code_lengths[0], 0,
|
||||
sizeof(s->code_length_code_lengths));
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
|
||||
memset(&h->code_length_code_lengths[0], 0,
|
||||
sizeof(h->code_length_code_lengths));
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
|
||||
continue;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:
|
||||
/* Read symbols, codes & code lengths directly. */
|
||||
if (!BrotliSafeReadBits(br, 2, &s->symbol)) { /* num_symbols */
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
|
||||
if (!BrotliSafeReadBits(br, 2, &h->symbol)) { /* num_symbols */
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
s->sub_loop_counter = 0;
|
||||
h->sub_loop_counter = 0;
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
|
||||
BrotliDecoderErrorCode result =
|
||||
ReadSimpleHuffmanSymbols(alphabet_size, max_symbol, s);
|
||||
ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
|
@ -788,21 +795,21 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
|||
|
||||
case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {
|
||||
uint32_t table_size;
|
||||
if (s->symbol == 3) {
|
||||
if (h->symbol == 3) {
|
||||
uint32_t bits;
|
||||
if (!BrotliSafeReadBits(br, 1, &bits)) {
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
s->symbol += bits;
|
||||
h->symbol += bits;
|
||||
}
|
||||
BROTLI_LOG_UINT(s->symbol);
|
||||
BROTLI_LOG_UINT(h->symbol);
|
||||
table_size = BrotliBuildSimpleHuffmanTable(
|
||||
table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, s->symbol);
|
||||
table, HUFFMAN_TABLE_BITS, h->symbols_lists_array, h->symbol);
|
||||
if (opt_table_size) {
|
||||
*opt_table_size = table_size;
|
||||
}
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -813,44 +820,45 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
|
|||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
BrotliBuildCodeLengthsHuffmanTable(s->table,
|
||||
s->code_length_code_lengths,
|
||||
s->code_length_histo);
|
||||
memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo));
|
||||
BrotliBuildCodeLengthsHuffmanTable(h->table,
|
||||
h->code_length_code_lengths,
|
||||
h->code_length_histo);
|
||||
memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo));
|
||||
for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {
|
||||
s->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
|
||||
s->symbol_lists[s->next_symbol[i]] = 0xFFFF;
|
||||
h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
|
||||
h->symbol_lists[h->next_symbol[i]] = 0xFFFF;
|
||||
}
|
||||
|
||||
s->symbol = 0;
|
||||
s->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
|
||||
s->repeat = 0;
|
||||
s->repeat_code_len = 0;
|
||||
s->space = 32768;
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
|
||||
h->symbol = 0;
|
||||
h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
|
||||
h->repeat = 0;
|
||||
h->repeat_code_len = 0;
|
||||
h->space = 32768;
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
|
||||
uint32_t table_size;
|
||||
BrotliDecoderErrorCode result = ReadSymbolCodeLengths(max_symbol, s);
|
||||
BrotliDecoderErrorCode result = ReadSymbolCodeLengths(
|
||||
alphabet_size_limit, s);
|
||||
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
|
||||
result = SafeReadSymbolCodeLengths(max_symbol, s);
|
||||
result = SafeReadSymbolCodeLengths(alphabet_size_limit, s);
|
||||
}
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (s->space != 0) {
|
||||
BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)s->space));
|
||||
if (h->space != 0) {
|
||||
BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)h->space));
|
||||
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);
|
||||
}
|
||||
table_size = BrotliBuildHuffmanTable(
|
||||
table, HUFFMAN_TABLE_BITS, s->symbol_lists, s->code_length_histo);
|
||||
table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo);
|
||||
if (opt_table_size) {
|
||||
*opt_table_size = table_size;
|
||||
}
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -867,8 +875,8 @@ static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table,
|
|||
uint32_t code;
|
||||
uint32_t nbits;
|
||||
code = ReadSymbol(table, br);
|
||||
nbits = kBlockLengthPrefixCode[code].nbits; /* nbits == 2..24 */
|
||||
return kBlockLengthPrefixCode[code].offset + BrotliReadBits(br, nbits);
|
||||
nbits = _kBrotliPrefixCodeRanges[code].nbits; /* nbits == 2..24 */
|
||||
return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits);
|
||||
}
|
||||
|
||||
/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then
|
||||
|
|
@ -886,13 +894,14 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(
|
|||
}
|
||||
{
|
||||
uint32_t bits;
|
||||
uint32_t nbits = kBlockLengthPrefixCode[index].nbits; /* nbits == 2..24 */
|
||||
uint32_t nbits = _kBrotliPrefixCodeRanges[index].nbits;
|
||||
uint32_t offset = _kBrotliPrefixCodeRanges[index].offset;
|
||||
if (!BrotliSafeReadBits(br, nbits, &bits)) {
|
||||
s->block_length_index = index;
|
||||
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
*result = kBlockLengthPrefixCode[index].offset + bits;
|
||||
*result = offset + bits;
|
||||
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
|
@ -952,22 +961,22 @@ static BROTLI_NOINLINE void InverseMoveToFrontTransform(
|
|||
/* Decodes a series of Huffman table using ReadHuffmanCode function. */
|
||||
static BrotliDecoderErrorCode HuffmanTreeGroupDecode(
|
||||
HuffmanTreeGroup* group, BrotliDecoderState* s) {
|
||||
if (s->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
|
||||
s->next = group->codes;
|
||||
s->htree_index = 0;
|
||||
s->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
|
||||
h->next = group->codes;
|
||||
h->htree_index = 0;
|
||||
h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
|
||||
}
|
||||
while (s->htree_index < group->num_htrees) {
|
||||
while (h->htree_index < group->num_htrees) {
|
||||
uint32_t table_size;
|
||||
BrotliDecoderErrorCode result =
|
||||
ReadHuffmanCode(group->alphabet_size, group->max_symbol,
|
||||
s->next, &table_size, s);
|
||||
BrotliDecoderErrorCode result = ReadHuffmanCode(group->alphabet_size_max,
|
||||
group->alphabet_size_limit, h->next, &table_size, s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) return result;
|
||||
group->htrees[s->htree_index] = s->next;
|
||||
s->next += table_size;
|
||||
++s->htree_index;
|
||||
group->htrees[h->htree_index] = h->next;
|
||||
h->next += table_size;
|
||||
++h->htree_index;
|
||||
}
|
||||
s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
|
||||
h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -985,15 +994,16 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|||
BrotliDecoderState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
|
||||
switch ((int)s->substate_context_map) {
|
||||
switch ((int)h->substate_context_map) {
|
||||
case BROTLI_STATE_CONTEXT_MAP_NONE:
|
||||
result = DecodeVarLenUint8(s, br, num_htrees);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
(*num_htrees)++;
|
||||
s->context_index = 0;
|
||||
h->context_index = 0;
|
||||
BROTLI_LOG_UINT(context_map_size);
|
||||
BROTLI_LOG_UINT(*num_htrees);
|
||||
*context_map_arg =
|
||||
|
|
@ -1005,7 +1015,7 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|||
memset(*context_map_arg, 0, (size_t)context_map_size);
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
|
||||
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {
|
||||
|
|
@ -1016,38 +1026,38 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
if ((bits & 1) != 0) { /* Use RLE for zeros. */
|
||||
s->max_run_length_prefix = (bits >> 1) + 1;
|
||||
h->max_run_length_prefix = (bits >> 1) + 1;
|
||||
BrotliDropBits(br, 5);
|
||||
} else {
|
||||
s->max_run_length_prefix = 0;
|
||||
h->max_run_length_prefix = 0;
|
||||
BrotliDropBits(br, 1);
|
||||
}
|
||||
BROTLI_LOG_UINT(s->max_run_length_prefix);
|
||||
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
|
||||
BROTLI_LOG_UINT(h->max_run_length_prefix);
|
||||
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {
|
||||
uint32_t alphabet_size = *num_htrees + s->max_run_length_prefix;
|
||||
uint32_t alphabet_size = *num_htrees + h->max_run_length_prefix;
|
||||
result = ReadHuffmanCode(alphabet_size, alphabet_size,
|
||||
s->context_map_table, NULL, s);
|
||||
h->context_map_table, NULL, s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) return result;
|
||||
s->code = 0xFFFF;
|
||||
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
|
||||
h->code = 0xFFFF;
|
||||
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_CONTEXT_MAP_DECODE: {
|
||||
uint32_t context_index = s->context_index;
|
||||
uint32_t max_run_length_prefix = s->max_run_length_prefix;
|
||||
uint32_t context_index = h->context_index;
|
||||
uint32_t max_run_length_prefix = h->max_run_length_prefix;
|
||||
uint8_t* context_map = *context_map_arg;
|
||||
uint32_t code = s->code;
|
||||
uint32_t code = h->code;
|
||||
BROTLI_BOOL skip_preamble = (code != 0xFFFF);
|
||||
while (context_index < context_map_size || skip_preamble) {
|
||||
if (!skip_preamble) {
|
||||
if (!SafeReadSymbol(s->context_map_table, br, &code)) {
|
||||
s->code = 0xFFFF;
|
||||
s->context_index = context_index;
|
||||
if (!SafeReadSymbol(h->context_map_table, br, &code)) {
|
||||
h->code = 0xFFFF;
|
||||
h->context_index = context_index;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
BROTLI_LOG_UINT(code);
|
||||
|
|
@ -1068,8 +1078,8 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|||
{
|
||||
uint32_t reps;
|
||||
if (!BrotliSafeReadBits(br, code, &reps)) {
|
||||
s->code = code;
|
||||
s->context_index = context_index;
|
||||
h->code = code;
|
||||
h->context_index = context_index;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
reps += 1U << code;
|
||||
|
|
@ -1089,13 +1099,13 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
|
|||
case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {
|
||||
uint32_t bits;
|
||||
if (!BrotliSafeReadBits(br, 1, &bits)) {
|
||||
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
|
||||
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
if (bits != 0) {
|
||||
InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);
|
||||
}
|
||||
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
|
||||
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1457,32 +1467,28 @@ static BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {
|
|||
}
|
||||
|
||||
static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {
|
||||
if (s->distance_code == 0) {
|
||||
--s->dist_rb_idx;
|
||||
s->distance_code = s->dist_rb[s->dist_rb_idx & 3];
|
||||
int offset = s->distance_code - 3;
|
||||
if (s->distance_code <= 3) {
|
||||
/* Compensate double distance-ring-buffer roll for dictionary items. */
|
||||
s->distance_context = 1;
|
||||
s->distance_context = 1 >> s->distance_code;
|
||||
s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3];
|
||||
s->dist_rb_idx -= s->distance_context;
|
||||
} else {
|
||||
int distance_code = s->distance_code << 1;
|
||||
/* kDistanceShortCodeIndexOffset has 2-bit values from LSB:
|
||||
3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */
|
||||
const uint32_t kDistanceShortCodeIndexOffset = 0xAAAFFF1B;
|
||||
/* kDistanceShortCodeValueOffset has 2-bit values from LSB:
|
||||
-0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */
|
||||
const uint32_t kDistanceShortCodeValueOffset = 0xFA5FA500;
|
||||
int v = (s->dist_rb_idx +
|
||||
(int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3;
|
||||
s->distance_code = s->dist_rb[v];
|
||||
v = (int)(kDistanceShortCodeValueOffset >> distance_code) & 0x3;
|
||||
if ((distance_code & 0x3) != 0) {
|
||||
s->distance_code += v;
|
||||
int index_delta = 3;
|
||||
int delta;
|
||||
int base = s->distance_code - 10;
|
||||
if (s->distance_code < 10) {
|
||||
base = s->distance_code - 4;
|
||||
} else {
|
||||
s->distance_code -= v;
|
||||
if (s->distance_code <= 0) {
|
||||
/* A huge distance will cause a BROTLI_FAILURE() soon.
|
||||
This is a little faster than failing here. */
|
||||
s->distance_code = 0x7FFFFFFF;
|
||||
}
|
||||
index_delta = 2;
|
||||
}
|
||||
/* Unpack one of six 4-bit values. */
|
||||
delta = ((0x605142 >> (4 * base)) & 0xF) - 3;
|
||||
s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta;
|
||||
if (s->distance_code <= 0) {
|
||||
/* A huge distance will cause a BROTLI_FAILURE() soon.
|
||||
This is a little faster than failing here. */
|
||||
s->distance_code = 0x7FFFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1497,62 +1503,153 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBits(
|
|||
}
|
||||
}
|
||||
|
||||
static BROTLI_INLINE BROTLI_BOOL SafeReadBits32(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
if (n_bits != 0) {
|
||||
return BrotliSafeReadBits32(br, n_bits, val);
|
||||
} else {
|
||||
*val = 0;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RFC 7932 Section 4 with "..." shortenings and "[]" emendations.
|
||||
|
||||
Each distance ... is represented with a pair <distance code, extra bits>...
|
||||
The distance code is encoded using a prefix code... The number of extra bits
|
||||
can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ...
|
||||
NDIRECT (0..120) ... are encoded in the meta-block header...
|
||||
|
||||
The first 16 distance symbols ... reference past distances... ring buffer ...
|
||||
Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT...
|
||||
[For] distance symbols 16 + NDIRECT and greater ... the number of extra bits
|
||||
... is given by the following formula:
|
||||
|
||||
[ xcode = dcode - NDIRECT - 16 ]
|
||||
ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1)
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
/*
|
||||
RFC 7932 Section 9.2 with "..." shortenings and "[]" emendations.
|
||||
|
||||
... to get the actual value of the parameter NDIRECT, left-shift this
|
||||
four-bit number by NPOSTFIX bits ...
|
||||
*/
|
||||
|
||||
/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following:
|
||||
|
||||
alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1))
|
||||
|
||||
half = ((xcode >> NPOSTFIX) & 1) << ndistbits
|
||||
postfix = xcode & ((1 << NPOSTFIX) - 1)
|
||||
range_start = 2 * (1 << ndistbits - 1 - 1)
|
||||
|
||||
distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1
|
||||
|
||||
NB: ndistbits >= 1 -> range_start >= 0
|
||||
NB: range_start has factor 2, as the range is covered by 2 "halves"
|
||||
NB: extra -1 offset in range_start formula covers the absence of
|
||||
ndistbits = 0 case
|
||||
NB: when NPOSTFIX = 0, NDIRECT is not greater than 15
|
||||
|
||||
In other words, xcode has the following binary structure - XXXHPPP:
|
||||
- XXX represent the number of extra distance bits
|
||||
- H selects upper / lower range of distances
|
||||
- PPP represent "postfix"
|
||||
|
||||
"Regular" distance encoding has NPOSTFIX = 0; omitting the postfix part
|
||||
simplifies distance calculation.
|
||||
|
||||
Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where
|
||||
most of distances have the same reminder of division by 2/4/8. For example,
|
||||
the table of int32_t values that come from different sources; if it is likely
|
||||
that 3 highest bytes of values from the same source are the same, then
|
||||
copy distance often looks like 4x + y.
|
||||
|
||||
Distance calculation could be rewritten to:
|
||||
|
||||
ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode]
|
||||
distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX
|
||||
|
||||
NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could
|
||||
change only once per meta-block.
|
||||
*/
|
||||
|
||||
/* Calculates distance lookup table.
|
||||
NB: it is possible to have all 64 tables precalculated. */
|
||||
static void CalculateDistanceLut(BrotliDecoderState* s) {
|
||||
BrotliMetablockBodyArena* b = &s->arena.body;
|
||||
uint32_t npostfix = s->distance_postfix_bits;
|
||||
uint32_t ndirect = s->num_direct_distance_codes;
|
||||
uint32_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit;
|
||||
uint32_t postfix = 1u << npostfix;
|
||||
uint32_t j;
|
||||
uint32_t bits = 1;
|
||||
uint32_t half = 0;
|
||||
|
||||
/* Skip short codes. */
|
||||
uint32_t i = BROTLI_NUM_DISTANCE_SHORT_CODES;
|
||||
|
||||
/* Fill direct codes. */
|
||||
for (j = 0; j < ndirect; ++j) {
|
||||
b->dist_extra_bits[i] = 0;
|
||||
b->dist_offset[i] = j + 1;
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Fill regular distance codes. */
|
||||
while (i < alphabet_size_limit) {
|
||||
uint32_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
|
||||
/* Always fill the complete group. */
|
||||
for (j = 0; j < postfix; ++j) {
|
||||
b->dist_extra_bits[i] = (uint8_t)bits;
|
||||
b->dist_offset[i] = base + j;
|
||||
++i;
|
||||
}
|
||||
bits = bits + half;
|
||||
half = half ^ 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Precondition: s->distance_code < 0. */
|
||||
static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
|
||||
int safe, BrotliDecoderState* s, BrotliBitReader* br) {
|
||||
int distval;
|
||||
BrotliMetablockBodyArena* b = &s->arena.body;
|
||||
uint32_t code;
|
||||
uint32_t bits;
|
||||
BrotliBitReaderState memento;
|
||||
HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index];
|
||||
if (!safe) {
|
||||
s->distance_code = (int)ReadSymbol(distance_tree, br);
|
||||
code = ReadSymbol(distance_tree, br);
|
||||
} else {
|
||||
uint32_t code;
|
||||
BrotliBitReaderSaveState(br, &memento);
|
||||
if (!SafeReadSymbol(distance_tree, br, &code)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
s->distance_code = (int)code;
|
||||
}
|
||||
--s->block_length[2];
|
||||
/* Convert the distance code to the actual distance by possibly
|
||||
looking up past distances from the s->ringbuffer. */
|
||||
looking up past distances from the s->dist_rb. */
|
||||
s->distance_context = 0;
|
||||
if ((s->distance_code & ~0xF) == 0) {
|
||||
if ((code & ~0xFu) == 0) {
|
||||
s->distance_code = (int)code;
|
||||
TakeDistanceFromRingBuffer(s);
|
||||
--s->block_length[2];
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
distval = s->distance_code - (int)s->num_direct_distance_codes;
|
||||
if (distval >= 0) {
|
||||
uint32_t nbits;
|
||||
int postfix;
|
||||
int offset;
|
||||
if (!safe && (s->distance_postfix_bits == 0)) {
|
||||
nbits = ((uint32_t)distval >> 1) + 1;
|
||||
offset = ((2 + (distval & 1)) << nbits) - 4;
|
||||
s->distance_code = (int)s->num_direct_distance_codes + offset +
|
||||
(int)BrotliReadBits(br, nbits);
|
||||
} else {
|
||||
/* This branch also works well when s->distance_postfix_bits == 0. */
|
||||
uint32_t bits;
|
||||
postfix = distval & s->distance_postfix_mask;
|
||||
distval >>= s->distance_postfix_bits;
|
||||
nbits = ((uint32_t)distval >> 1) + 1;
|
||||
if (safe) {
|
||||
if (!SafeReadBits(br, nbits, &bits)) {
|
||||
s->distance_code = -1; /* Restore precondition. */
|
||||
BrotliBitReaderRestoreState(br, &memento);
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
} else {
|
||||
bits = BrotliReadBits(br, nbits);
|
||||
}
|
||||
offset = ((2 + (distval & 1)) << nbits) - 4;
|
||||
s->distance_code = (int)s->num_direct_distance_codes +
|
||||
((offset + (int)bits) << s->distance_postfix_bits) + postfix;
|
||||
if (!safe) {
|
||||
bits = BrotliReadBits32(br, b->dist_extra_bits[code]);
|
||||
} else {
|
||||
if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) {
|
||||
++s->block_length[2];
|
||||
BrotliBitReaderRestoreState(br, &memento);
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
s->distance_code = s->distance_code - BROTLI_NUM_DISTANCE_SHORT_CODES + 1;
|
||||
--s->block_length[2];
|
||||
s->distance_code =
|
||||
(int)(b->dist_offset[code] + (bits << s->distance_postfix_bits));
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1588,9 +1685,9 @@ static BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(
|
|||
*insert_length = v.insert_len_offset;
|
||||
if (!safe) {
|
||||
if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) {
|
||||
insert_len_extra = BrotliReadBits(br, v.insert_len_extra_bits);
|
||||
insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits);
|
||||
}
|
||||
copy_length = BrotliReadBits(br, v.copy_len_extra_bits);
|
||||
copy_length = BrotliReadBits24(br, v.copy_len_extra_bits);
|
||||
} else {
|
||||
if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) ||
|
||||
!SafeReadBits(br, v.copy_len_extra_bits, ©_length)) {
|
||||
|
|
@ -1935,21 +2032,6 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
|
|||
return ProcessCommandsInternal(1, s);
|
||||
}
|
||||
|
||||
/* Returns the maximum number of distance symbols which can only represent
|
||||
distances not exceeding BROTLI_MAX_ALLOWED_DISTANCE. */
|
||||
static uint32_t BrotliMaxDistanceSymbol(uint32_t ndirect, uint32_t npostfix) {
|
||||
static const uint32_t bound[BROTLI_MAX_NPOSTFIX + 1] = {0, 4, 12, 28};
|
||||
static const uint32_t diff[BROTLI_MAX_NPOSTFIX + 1] = {73, 126, 228, 424};
|
||||
uint32_t postfix = 1U << npostfix;
|
||||
if (ndirect < bound[npostfix]) {
|
||||
return ndirect + diff[npostfix] + postfix;
|
||||
} else if (ndirect > bound[npostfix] + postfix) {
|
||||
return ndirect + diff[npostfix];
|
||||
} else {
|
||||
return bound[npostfix] + diff[npostfix] + postfix;
|
||||
}
|
||||
}
|
||||
|
||||
BrotliDecoderResult BrotliDecoderDecompress(
|
||||
size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
|
||||
uint8_t* decoded_buffer) {
|
||||
|
|
@ -2167,33 +2249,23 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|||
s->state = BROTLI_STATE_UNCOMPRESSED;
|
||||
break;
|
||||
}
|
||||
s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER;
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: {
|
||||
BrotliMetablockHeaderArena* h = &s->arena.header;
|
||||
s->loop_counter = 0;
|
||||
/* Initialize compressed metablock header arena. */
|
||||
h->sub_loop_counter = 0;
|
||||
/* Make small negative indexes addressable. */
|
||||
h->symbol_lists =
|
||||
&h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
|
||||
h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
|
||||
h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
|
||||
h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
|
||||
s->state = BROTLI_STATE_HUFFMAN_CODE_0;
|
||||
break;
|
||||
|
||||
case BROTLI_STATE_UNCOMPRESSED: {
|
||||
result = CopyUncompressedBlockToOutput(
|
||||
available_out, next_out, total_out, s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
case BROTLI_STATE_METADATA:
|
||||
for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
|
||||
uint32_t bits;
|
||||
/* Read one byte and ignore it. */
|
||||
if (!BrotliSafeReadBits(br, 8, &bits)) {
|
||||
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == BROTLI_DECODER_SUCCESS) {
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
}
|
||||
break;
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_HUFFMAN_CODE_0:
|
||||
if (s->loop_counter >= 3) {
|
||||
|
|
@ -2247,6 +2319,30 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|||
break;
|
||||
}
|
||||
|
||||
case BROTLI_STATE_UNCOMPRESSED: {
|
||||
result = CopyUncompressedBlockToOutput(
|
||||
available_out, next_out, total_out, s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
case BROTLI_STATE_METADATA:
|
||||
for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
|
||||
uint32_t bits;
|
||||
/* Read one byte and ignore it. */
|
||||
if (!BrotliSafeReadBits(br, 8, &bits)) {
|
||||
result = BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == BROTLI_DECODER_SUCCESS) {
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case BROTLI_STATE_METABLOCK_HEADER_2: {
|
||||
uint32_t bits;
|
||||
if (!BrotliSafeReadBits(br, 6, &bits)) {
|
||||
|
|
@ -2255,11 +2351,9 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|||
}
|
||||
s->distance_postfix_bits = bits & BitMask(2);
|
||||
bits >>= 2;
|
||||
s->num_direct_distance_codes = BROTLI_NUM_DISTANCE_SHORT_CODES +
|
||||
(bits << s->distance_postfix_bits);
|
||||
s->num_direct_distance_codes = bits << s->distance_postfix_bits;
|
||||
BROTLI_LOG_UINT(s->num_direct_distance_codes);
|
||||
BROTLI_LOG_UINT(s->distance_postfix_bits);
|
||||
s->distance_postfix_mask = (int)BitMask(s->distance_postfix_bits);
|
||||
s->context_modes =
|
||||
(uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);
|
||||
if (s->context_modes == 0) {
|
||||
|
|
@ -2291,17 +2385,19 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_CONTEXT_MAP_2: {
|
||||
uint32_t num_direct_codes =
|
||||
s->num_direct_distance_codes - BROTLI_NUM_DISTANCE_SHORT_CODES;
|
||||
uint32_t num_distance_codes = BROTLI_DISTANCE_ALPHABET_SIZE(
|
||||
s->distance_postfix_bits, num_direct_codes,
|
||||
(s->large_window ? BROTLI_LARGE_MAX_DISTANCE_BITS :
|
||||
BROTLI_MAX_DISTANCE_BITS));
|
||||
uint32_t max_distance_symbol = (s->large_window ?
|
||||
BrotliMaxDistanceSymbol(
|
||||
num_direct_codes, s->distance_postfix_bits) :
|
||||
num_distance_codes);
|
||||
uint32_t npostfix = s->distance_postfix_bits;
|
||||
uint32_t ndirect = s->num_direct_distance_codes;
|
||||
uint32_t distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
|
||||
npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);
|
||||
uint32_t distance_alphabet_size_limit = distance_alphabet_size_max;
|
||||
BROTLI_BOOL allocation_success = BROTLI_TRUE;
|
||||
if (s->large_window) {
|
||||
BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
|
||||
BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);
|
||||
distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
|
||||
npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);
|
||||
distance_alphabet_size_limit = limit.max_alphabet_size;
|
||||
}
|
||||
result = DecodeContextMap(
|
||||
s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,
|
||||
&s->num_dist_htrees, &s->dist_context_map, s);
|
||||
|
|
@ -2315,8 +2411,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|||
s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,
|
||||
BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);
|
||||
allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
|
||||
s, &s->distance_hgroup, num_distance_codes,
|
||||
max_distance_symbol, s->num_dist_htrees);
|
||||
s, &s->distance_hgroup, distance_alphabet_size_max,
|
||||
distance_alphabet_size_limit, s->num_dist_htrees);
|
||||
if (!allocation_success) {
|
||||
return SaveErrorCode(s,
|
||||
BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));
|
||||
|
|
@ -2338,18 +2434,24 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
|||
result = HuffmanTreeGroupDecode(hgroup, s);
|
||||
if (result != BROTLI_DECODER_SUCCESS) break;
|
||||
s->loop_counter++;
|
||||
if (s->loop_counter >= 3) {
|
||||
PrepareLiteralDecoding(s);
|
||||
s->dist_context_map_slice = s->dist_context_map;
|
||||
s->htree_command = s->insert_copy_hgroup.htrees[0];
|
||||
if (!BrotliEnsureRingBuffer(s)) {
|
||||
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
|
||||
break;
|
||||
}
|
||||
s->state = BROTLI_STATE_COMMAND_BEGIN;
|
||||
if (s->loop_counter < 3) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY;
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY:
|
||||
PrepareLiteralDecoding(s);
|
||||
s->dist_context_map_slice = s->dist_context_map;
|
||||
s->htree_command = s->insert_copy_hgroup.htrees[0];
|
||||
if (!BrotliEnsureRingBuffer(s)) {
|
||||
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
|
||||
break;
|
||||
}
|
||||
CalculateDistanceLut(s);
|
||||
s->state = BROTLI_STATE_COMMAND_BEGIN;
|
||||
/* Fall through. */
|
||||
|
||||
case BROTLI_STATE_COMMAND_BEGIN:
|
||||
/* Fall through. */
|
||||
|
|
|
|||
|
|
@ -18,12 +18,6 @@ extern "C" {
|
|||
|
||||
#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15
|
||||
|
||||
/* Maximum possible Huffman table size for an alphabet size of (index * 32),
|
||||
max code length 15 and root table bits 8. */
|
||||
static const uint16_t kMaxHuffmanTableSize[] = {
|
||||
256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
|
||||
854, 886, 920, 952, 984, 1016, 1048, 1080, 1112, 1144, 1176, 1208, 1240, 1272,
|
||||
1304, 1336, 1368, 1400, 1432, 1464, 1496, 1528};
|
||||
/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */
|
||||
#define BROTLI_HUFFMAN_MAX_SIZE_26 396
|
||||
/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */
|
||||
|
|
@ -82,7 +76,7 @@ typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;
|
|||
|
||||
static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
|
||||
const uint16_t value) {
|
||||
return ((value & 0xFFFF) << 16) | (bits & 0xFF);
|
||||
return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);
|
||||
}
|
||||
|
||||
#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)
|
||||
|
|
@ -100,7 +94,7 @@ BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
|
|||
/* Builds Huffman lookup table assuming code lengths are in symbol order.
|
||||
Returns size of resulting table. */
|
||||
BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
|
||||
int root_bits, const uint16_t* const symbol_lists, uint16_t* count_arg);
|
||||
int root_bits, const uint16_t* const symbol_lists, uint16_t* count);
|
||||
|
||||
/* Builds a simple Huffman table. The |num_symbols| parameter is to be
|
||||
interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,
|
||||
|
|
@ -110,13 +104,13 @@ BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
|
|||
int root_bits, uint16_t* symbols, uint32_t num_symbols);
|
||||
|
||||
/* Contains a collection of Huffman trees with the same alphabet size. */
|
||||
/* max_symbol is needed due to simple codes since log2(alphabet_size) could be
|
||||
greater than log2(max_symbol). */
|
||||
/* alphabet_size_limit is needed due to simple codes, since
|
||||
log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */
|
||||
typedef struct {
|
||||
HuffmanCode** htrees;
|
||||
HuffmanCode* codes;
|
||||
uint16_t alphabet_size;
|
||||
uint16_t max_symbol;
|
||||
uint16_t alphabet_size_max;
|
||||
uint16_t alphabet_size_limit;
|
||||
uint16_t num_htrees;
|
||||
} HuffmanTreeGroup;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,24 +13,6 @@
|
|||
#include "../common/constants.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
/* Represents the range of values belonging to a prefix code:
|
||||
[offset, offset + 2^nbits) */
|
||||
struct PrefixCodeRange {
|
||||
uint16_t offset;
|
||||
uint8_t nbits;
|
||||
};
|
||||
|
||||
static const struct PrefixCodeRange
|
||||
kBlockLengthPrefixCode[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
|
||||
{ 1, 2}, { 5, 2}, { 9, 2}, { 13, 2},
|
||||
{ 17, 3}, { 25, 3}, { 33, 3}, { 41, 3},
|
||||
{ 49, 4}, { 65, 4}, { 81, 4}, { 97, 4},
|
||||
{ 113, 5}, { 145, 5}, { 177, 5}, { 209, 5},
|
||||
{ 241, 6}, { 305, 6}, { 369, 7}, { 497, 8},
|
||||
{ 753, 9}, { 1265, 10}, {2289, 11}, {4337, 12},
|
||||
{8433, 13}, {16625, 24}
|
||||
};
|
||||
|
||||
typedef struct CmdLutElement {
|
||||
uint8_t insert_len_extra_bits;
|
||||
uint8_t copy_len_extra_bits;
|
||||
|
|
|
|||
|
|
@ -33,10 +33,7 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
|
|||
s->state = BROTLI_STATE_UNINITED;
|
||||
s->large_window = 0;
|
||||
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
|
||||
s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
|
||||
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
|
||||
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
|
||||
s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
|
||||
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
|
||||
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
|
||||
|
||||
|
|
@ -59,8 +56,6 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
|
|||
s->context_map_slice = NULL;
|
||||
s->dist_context_map_slice = NULL;
|
||||
|
||||
s->sub_loop_counter = 0;
|
||||
|
||||
s->literal_hgroup.codes = NULL;
|
||||
s->literal_hgroup.htrees = NULL;
|
||||
s->insert_copy_hgroup.codes = NULL;
|
||||
|
|
@ -84,9 +79,6 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* 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 = 63;
|
||||
|
||||
s->dictionary = BrotliGetDictionary();
|
||||
|
|
@ -142,17 +134,20 @@ void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
|
|||
}
|
||||
|
||||
BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,
|
||||
HuffmanTreeGroup* group, uint32_t alphabet_size, uint32_t max_symbol,
|
||||
uint32_t ntrees) {
|
||||
/* Pack two allocations into one */
|
||||
const size_t max_table_size = kMaxHuffmanTableSize[(alphabet_size + 31) >> 5];
|
||||
HuffmanTreeGroup* group, uint32_t alphabet_size_max,
|
||||
uint32_t alphabet_size_limit, uint32_t ntrees) {
|
||||
/* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)
|
||||
This number is discovered "unlimited" "enough" calculator; it is actually
|
||||
a wee bigger than required in several cases (especially for alphabets with
|
||||
less than 16 symbols). */
|
||||
const size_t max_table_size = alphabet_size_limit + 376;
|
||||
const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
|
||||
const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
|
||||
/* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */
|
||||
HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,
|
||||
code_size + htree_size);
|
||||
group->alphabet_size = (uint16_t)alphabet_size;
|
||||
group->max_symbol = (uint16_t)max_symbol;
|
||||
group->alphabet_size_max = (uint16_t)alphabet_size_max;
|
||||
group->alphabet_size_limit = (uint16_t)alphabet_size_limit;
|
||||
group->num_htrees = (uint16_t)ntrees;
|
||||
group->htrees = p;
|
||||
group->codes = (HuffmanCode*)(&p[ntrees]);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,95 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Graphviz diagram that describes state transitions:
|
||||
|
||||
digraph States {
|
||||
graph [compound=true]
|
||||
concentrate=true
|
||||
node [shape="box"]
|
||||
|
||||
UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}
|
||||
subgraph cluster_metablock_workflow {
|
||||
style="rounded"
|
||||
label=< <B>METABLOCK CYCLE</B> >
|
||||
METABLOCK_BEGIN -> METABLOCK_HEADER
|
||||
METABLOCK_HEADER:sw -> METADATA
|
||||
METABLOCK_HEADER:s -> UNCOMPRESSED
|
||||
METABLOCK_HEADER:se -> METABLOCK_DONE:ne
|
||||
METADATA:s -> METABLOCK_DONE:w
|
||||
UNCOMPRESSED:s -> METABLOCK_DONE:n
|
||||
METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint="false"]
|
||||
}
|
||||
INITIALIZE -> METABLOCK_BEGIN
|
||||
METABLOCK_DONE -> DONE
|
||||
|
||||
subgraph cluster_compressed_metablock {
|
||||
style="rounded"
|
||||
label=< <B>COMPRESSED METABLOCK</B> >
|
||||
|
||||
subgraph cluster_command {
|
||||
style="rounded"
|
||||
label=< <B>HOT LOOP</B> >
|
||||
|
||||
_METABLOCK_DONE_PORT_ [shape=point style=invis]
|
||||
|
||||
{
|
||||
// Set different shape for nodes returning from "compressed metablock".
|
||||
node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;
|
||||
CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;
|
||||
}
|
||||
|
||||
CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY
|
||||
|
||||
// IO ("write") nodes are not in the hot loop!
|
||||
CMD_INNER_WRITE [style=dashed]
|
||||
CMD_INNER -> CMD_INNER_WRITE
|
||||
CMD_POST_WRITE_1 [style=dashed]
|
||||
CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1
|
||||
CMD_POST_WRITE_2 [style=dashed]
|
||||
CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2
|
||||
|
||||
CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint="false"]
|
||||
CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}
|
||||
[constraint="false"]
|
||||
CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint="false"]
|
||||
CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint="false"]
|
||||
CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint="false"]
|
||||
CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint="false"]
|
||||
{rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;
|
||||
CMD_POST_WRAP_COPY}
|
||||
{rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}
|
||||
|
||||
{CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->
|
||||
_METABLOCK_DONE_PORT_ [style=invis]
|
||||
{CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_
|
||||
[constraint="false" style=invis]
|
||||
}
|
||||
|
||||
BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n
|
||||
HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3
|
||||
HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1
|
||||
CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP
|
||||
TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e
|
||||
BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n
|
||||
|
||||
HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint="false"]
|
||||
{rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}
|
||||
{rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;
|
||||
TREE_GROUP}
|
||||
}
|
||||
METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n
|
||||
|
||||
_METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se
|
||||
[constraint="false" ltail=cluster_command]
|
||||
|
||||
UNINITED [shape=Mdiamond];
|
||||
DONE [shape=Msquare];
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
BROTLI_STATE_UNINITED,
|
||||
BROTLI_STATE_LARGE_WINDOW_BITS,
|
||||
|
|
@ -39,6 +128,7 @@ typedef enum {
|
|||
BROTLI_STATE_METABLOCK_DONE,
|
||||
BROTLI_STATE_COMMAND_POST_WRITE_1,
|
||||
BROTLI_STATE_COMMAND_POST_WRITE_2,
|
||||
BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,
|
||||
BROTLI_STATE_HUFFMAN_CODE_0,
|
||||
BROTLI_STATE_HUFFMAN_CODE_1,
|
||||
BROTLI_STATE_HUFFMAN_CODE_2,
|
||||
|
|
@ -46,6 +136,7 @@ typedef enum {
|
|||
BROTLI_STATE_CONTEXT_MAP_1,
|
||||
BROTLI_STATE_CONTEXT_MAP_2,
|
||||
BROTLI_STATE_TREE_GROUP,
|
||||
BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,
|
||||
BROTLI_STATE_DONE
|
||||
} BrotliRunningState;
|
||||
|
||||
|
|
@ -98,6 +189,50 @@ typedef enum {
|
|||
BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
|
||||
} BrotliRunningReadBlockLengthState;
|
||||
|
||||
typedef struct BrotliMetablockHeaderArena {
|
||||
BrotliRunningTreeGroupState substate_tree_group;
|
||||
BrotliRunningContextMapState substate_context_map;
|
||||
BrotliRunningHuffmanState substate_huffman;
|
||||
|
||||
uint32_t sub_loop_counter;
|
||||
|
||||
uint32_t repeat_code_len;
|
||||
uint32_t prev_code_len;
|
||||
|
||||
/* For ReadHuffmanCode. */
|
||||
uint32_t symbol;
|
||||
uint32_t repeat;
|
||||
uint32_t space;
|
||||
|
||||
/* Huffman table for "histograms". */
|
||||
HuffmanCode table[32];
|
||||
/* List of heads of symbol chains. */
|
||||
uint16_t* symbol_lists;
|
||||
/* Storage from symbol_lists. */
|
||||
uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
|
||||
BROTLI_NUM_COMMAND_SYMBOLS];
|
||||
/* Tails of symbol chains. */
|
||||
int next_symbol[32];
|
||||
uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
|
||||
/* Population counts for the code lengths. */
|
||||
uint16_t code_length_histo[16];
|
||||
|
||||
/* For HuffmanTreeGroupDecode. */
|
||||
int htree_index;
|
||||
HuffmanCode* next;
|
||||
|
||||
/* For DecodeContextMap. */
|
||||
uint32_t context_index;
|
||||
uint32_t max_run_length_prefix;
|
||||
uint32_t code;
|
||||
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
|
||||
} BrotliMetablockHeaderArena;
|
||||
|
||||
typedef struct BrotliMetablockBodyArena {
|
||||
uint8_t dist_extra_bits[544];
|
||||
uint32_t dist_offset[544];
|
||||
} BrotliMetablockBodyArena;
|
||||
|
||||
struct BrotliDecoderStateStruct {
|
||||
BrotliRunningState state;
|
||||
|
||||
|
|
@ -110,7 +245,8 @@ struct BrotliDecoderStateStruct {
|
|||
brotli_free_func free_func;
|
||||
void* memory_manager_opaque;
|
||||
|
||||
/* Temporary storage for remaining input. */
|
||||
/* Temporary storage for remaining input. Brotli stream format is designed in
|
||||
a way, that 64 bits are enough to make progress in decoding. */
|
||||
union {
|
||||
uint64_t u64;
|
||||
uint8_t u8[8];
|
||||
|
|
@ -125,7 +261,6 @@ struct BrotliDecoderStateStruct {
|
|||
int dist_rb_idx;
|
||||
int dist_rb[4];
|
||||
int error_code;
|
||||
uint32_t sub_loop_counter;
|
||||
uint8_t* ringbuffer;
|
||||
uint8_t* ringbuffer_end;
|
||||
HuffmanCode* htree_command;
|
||||
|
|
@ -153,13 +288,10 @@ struct BrotliDecoderStateStruct {
|
|||
uint32_t block_type_rb[6];
|
||||
uint32_t distance_postfix_bits;
|
||||
uint32_t num_direct_distance_codes;
|
||||
int distance_postfix_mask;
|
||||
uint32_t num_dist_htrees;
|
||||
uint8_t* dist_context_map;
|
||||
HuffmanCode* literal_htree;
|
||||
uint8_t dist_htree_index;
|
||||
uint32_t repeat_code_len;
|
||||
uint32_t prev_code_len;
|
||||
|
||||
int copy_length;
|
||||
int distance_code;
|
||||
|
|
@ -168,33 +300,6 @@ struct BrotliDecoderStateStruct {
|
|||
size_t rb_roundtrips; /* how many times we went around the ring-buffer */
|
||||
size_t partial_pos_out; /* how much output to the user in total */
|
||||
|
||||
/* For ReadHuffmanCode. */
|
||||
uint32_t symbol;
|
||||
uint32_t repeat;
|
||||
uint32_t space;
|
||||
|
||||
HuffmanCode table[32];
|
||||
/* List of heads of symbol chains. */
|
||||
uint16_t* symbol_lists;
|
||||
/* Storage from symbol_lists. */
|
||||
uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
|
||||
BROTLI_NUM_COMMAND_SYMBOLS];
|
||||
/* Tails of symbol chains. */
|
||||
int next_symbol[32];
|
||||
uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
|
||||
/* Population counts for the code lengths. */
|
||||
uint16_t code_length_histo[16];
|
||||
|
||||
/* For HuffmanTreeGroupDecode. */
|
||||
int htree_index;
|
||||
HuffmanCode* next;
|
||||
|
||||
/* For DecodeContextMap. */
|
||||
uint32_t context_index;
|
||||
uint32_t max_run_length_prefix;
|
||||
uint32_t code;
|
||||
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
|
||||
|
||||
/* For InverseMoveToFrontTransform. */
|
||||
uint32_t mtf_upper_bound;
|
||||
uint32_t mtf[64 + 1];
|
||||
|
|
@ -203,10 +308,7 @@ struct BrotliDecoderStateStruct {
|
|||
|
||||
/* States inside function calls. */
|
||||
BrotliRunningMetablockHeaderState substate_metablock_header;
|
||||
BrotliRunningTreeGroupState substate_tree_group;
|
||||
BrotliRunningContextMapState substate_context_map;
|
||||
BrotliRunningUncompressedState substate_uncompressed;
|
||||
BrotliRunningHuffmanState substate_huffman;
|
||||
BrotliRunningDecodeUint8State substate_decode_uint8;
|
||||
BrotliRunningReadBlockLengthState substate_read_block_length;
|
||||
|
||||
|
|
@ -229,6 +331,11 @@ struct BrotliDecoderStateStruct {
|
|||
const BrotliTransforms* transforms;
|
||||
|
||||
uint32_t trivial_literal_contexts[8]; /* 256 bits */
|
||||
|
||||
union {
|
||||
BrotliMetablockHeaderArena header;
|
||||
BrotliMetablockBodyArena body;
|
||||
} arena;
|
||||
};
|
||||
|
||||
typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;
|
||||
|
|
@ -241,8 +348,8 @@ BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);
|
|||
BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(
|
||||
BrotliDecoderState* s);
|
||||
BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
|
||||
BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size,
|
||||
uint32_t max_symbol, uint32_t ntrees);
|
||||
BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size_max,
|
||||
uint32_t alphabet_size_limit, uint32_t ntrees);
|
||||
|
||||
#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue