Modified: trunk/Source/ThirdParty/brotli/dec/decode.c (202224 => 202225)
--- trunk/Source/ThirdParty/brotli/dec/decode.c 2016-06-20 05:53:20 UTC (rev 202224)
+++ trunk/Source/ThirdParty/brotli/dec/decode.c 2016-06-20 06:56:22 UTC (rev 202225)
@@ -10,7 +10,6 @@
#include <arm_neon.h>
#endif
-#include <stdio.h> /* printf (debug output) */
#include <stdlib.h> /* free, malloc */
#include <string.h> /* memcpy, memset */
@@ -20,6 +19,7 @@
#include "./huffman.h"
#include "./port.h"
#include "./prefix.h"
+#include "./state.h"
#include "./transform.h"
#if defined(__cplusplus) || defined(c_plusplus)
@@ -26,32 +26,13 @@
extern "C" {
#endif
-/* BROTLI_FAILURE macro unwraps to BROTLI_RESULT_ERROR in non-debug build. */
-/* In debug build it dumps file name, line and pretty function name. */
-#if defined(_MSC_VER) || \
- (!defined(BROTLI_DEBUG) && !defined(BROTLI_DECODE_DEBUG))
-#define BROTLI_FAILURE() BROTLI_RESULT_ERROR
-#else
-#define BROTLI_FAILURE() BrotliFailure(__FILE__, __LINE__, __PRETTY_FUNCTION__)
-static inline BrotliResult BrotliFailure(const char* f, int l, const char* fn) {
- fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn);
- fflush(stderr);
- return BROTLI_RESULT_ERROR;
-}
-#endif
+#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE)
-#ifdef BROTLI_DECODE_DEBUG
#define BROTLI_LOG_UINT(name) \
- printf("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name))
+ BROTLI_LOG(("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name)))
#define BROTLI_LOG_ARRAY_INDEX(array_name, idx) \
- printf("[%s] %s[%lu] = %lu\n", __func__, #array_name, \
- (unsigned long)(idx), (unsigned long)array_name[idx])
-#define BROTLI_LOG(x) printf x
-#else
-#define BROTLI_LOG_UINT(name)
-#define BROTLI_LOG_ARRAY_INDEX(array_name, idx)
-#define BROTLI_LOG(x)
-#endif
+ BROTLI_LOG(("[%s] %s[%lu] = %lu\n", __func__, #array_name, \
+ (unsigned long)(idx), (unsigned long)array_name[idx]))
static const uint32_t kDefaultCodeLength = 8;
static const uint32_t kCodeLengthRepeatCode = 16;
@@ -89,10 +70,11 @@
state = (BrotliState*)alloc_func(opaque, sizeof(BrotliState));
}
if (state == 0) {
- (void)BROTLI_FAILURE();
+ BROTLI_DUMP();
return 0;
}
BrotliStateInitWithCustomAllocators(state, alloc_func, free_func, opaque);
+ state->error_code = BROTLI_NO_ERROR;
return state;
}
@@ -108,6 +90,18 @@
}
}
+/* Saves error code and converts it to BrotliResult */
+static BROTLI_NOINLINE BrotliResult SaveErrorCode(
+ BrotliState* s, BrotliErrorCode e) {
+ s->error_code = (int)e;
+ switch (e) {
+ case BROTLI_SUCCESS: return BROTLI_RESULT_SUCCESS;
+ case BROTLI_NEEDS_MORE_INPUT: return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ case BROTLI_NEEDS_MORE_OUTPUT: return BROTLI_RESULT_NEEDS_MORE_OUTPUT;
+ default: return BROTLI_RESULT_ERROR;
+ }
+}
+
/* Decodes a number in the range [9..24], by reading 1 - 7 bits.
Precondition: bit-reader accumulator has at least 7 bits. */
static uint32_t DecodeWindowBits(BrotliBitReader* br) {
@@ -138,17 +132,17 @@
}
/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */
-static BROTLI_NOINLINE BrotliResult DecodeVarLenUint8(BrotliState* s,
+static BROTLI_NOINLINE BrotliErrorCode DecodeVarLenUint8(BrotliState* s,
BrotliBitReader* br, uint32_t* value) {
uint32_t bits;
switch (s->substate_decode_uint8) {
case BROTLI_STATE_DECODE_UINT8_NONE:
if (PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (bits == 0) {
*value = 0;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
/* No break, transit to the next state. */
@@ -155,12 +149,12 @@
case BROTLI_STATE_DECODE_UINT8_SHORT:
if (PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (bits == 0) {
*value = 1;
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
/* Use output value as a temporary storage. It MUST be persisted. */
*value = bits;
@@ -169,20 +163,20 @@
case BROTLI_STATE_DECODE_UINT8_LONG:
if (PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
*value = (1U << *value) + bits;
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
default:
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
}
}
/* Decodes a metablock length and flags by reading 2 - 31 bits. */
-static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s,
- BrotliBitReader* br) {
+static BrotliErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
+ BrotliState* s, BrotliBitReader* br) {
uint32_t bits;
int i;
for (;;) {
@@ -189,7 +183,7 @@
switch (s->substate_metablock_header) {
case BROTLI_STATE_METABLOCK_HEADER_NONE:
if (!BrotliSafeReadBits(br, 1, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->is_last_metablock = (uint8_t)bits;
s->meta_block_remaining_len = 0;
@@ -204,11 +198,11 @@
case BROTLI_STATE_METABLOCK_HEADER_EMPTY:
if (!BrotliSafeReadBits(br, 1, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (bits) {
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
/* No break, transit to the next state. */
@@ -215,7 +209,7 @@
case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:
if (!BrotliSafeReadBits(br, 2, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->size_nibbles = (uint8_t)(bits + 4);
s->loop_counter = 0;
@@ -232,10 +226,10 @@
for (; i < s->size_nibbles; ++i) {
if (!BrotliSafeReadBits(br, 4, &bits)) {
s->loop_counter = i;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (i + 1 == s->size_nibbles && s->size_nibbles > 4 && bits == 0) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_EXUBERANT_NIBBLE);
}
s->meta_block_remaining_len |= (int)(bits << (i * 4));
}
@@ -246,20 +240,20 @@
case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:
if (!s->is_last_metablock) {
if (!BrotliSafeReadBits(br, 1, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->is_uncompressed = (uint8_t)bits;
}
++s->meta_block_remaining_len;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
case BROTLI_STATE_METABLOCK_HEADER_RESERVED:
if (!BrotliSafeReadBits(br, 1, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (bits != 0) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_RESERVED);
}
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;
/* No break, transit to the next state. */
@@ -266,11 +260,11 @@
case BROTLI_STATE_METABLOCK_HEADER_BYTES:
if (!BrotliSafeReadBits(br, 2, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (bits == 0) {
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
s->size_nibbles = (uint8_t)bits;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;
@@ -281,19 +275,19 @@
for (; i < s->size_nibbles; ++i) {
if (!BrotliSafeReadBits(br, 8, &bits)) {
s->loop_counter = i;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (i + 1 == s->size_nibbles && s->size_nibbles > 1 && bits == 0) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
}
s->meta_block_remaining_len |= (int)(bits << (i * 8));
}
++s->meta_block_remaining_len;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
default:
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
}
}
}
@@ -376,7 +370,6 @@
return SafeDecodeSymbol(table, br, result);
}
-
/* Makes a look-up in first level Huffman table. Peeks 8 bits. */
static BROTLI_INLINE void PreloadSymbol(int safe,
const HuffmanCode* table,
@@ -426,8 +419,8 @@
Totally 1..4 symbols are read, 1..10 bits each.
The list of symbols MUST NOT contain duplicates.
*/
-static BrotliResult ReadSimpleHuffmanSymbols(uint32_t alphabet_size,
- BrotliState* s) {
+static BrotliErrorCode ReadSimpleHuffmanSymbols(uint32_t alphabet_size,
+ BrotliState* s) {
/* max_bits == 1..10; symbol == 0..3; 1..40 bits will be read. */
BrotliBitReader* br = &s->br;
uint32_t max_bits = Log2Floor(alphabet_size - 1);
@@ -438,10 +431,10 @@
if (PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {
s->sub_loop_counter = i;
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (v >= alphabet_size) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
}
s->symbols_lists_array[i] = (uint16_t)v;
BROTLI_LOG_UINT(s->symbols_lists_array[i]);
@@ -452,12 +445,12 @@
uint32_t k = i + 1;
for (; k <= num_symbols; ++k) {
if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
}
}
}
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
/* Process single decoded symbol code length:
@@ -514,7 +507,7 @@
*repeat += repeat_delta + 3U;
repeat_delta = *repeat - old_repeat;
if (*symbol + repeat_delta > alphabet_size) {
- (void)BROTLI_FAILURE();
+ BROTLI_DUMP();
*symbol = alphabet_size;
*space = 0xFFFFF;
return;
@@ -538,7 +531,7 @@
}
/* Reads and decodes symbol codelengths. */
-static BrotliResult ReadSymbolCodeLengths(
+static BrotliErrorCode ReadSymbolCodeLengths(
uint32_t alphabet_size, BrotliState* s) {
BrotliBitReader* br = &s->br;
uint32_t symbol = s->symbol;
@@ -550,7 +543,7 @@
uint16_t* code_length_histo = s->code_length_histo;
int* next_symbol = s->next_symbol;
if (!BrotliWarmupBitReader(br)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
while (symbol < alphabet_size && space > 0) {
const HuffmanCode* p = s->table;
@@ -561,7 +554,7 @@
s->prev_code_len = prev_code_len;
s->repeat_code_len = repeat_code_len;
s->space = space;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
BrotliFillBitWindow16(br);
p += BrotliGetBitsUnmasked(br) &
@@ -581,10 +574,10 @@
}
}
s->space = space;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
-static BrotliResult SafeReadSymbolCodeLengths(
+static BrotliErrorCode SafeReadSymbolCodeLengths(
uint32_t alphabet_size, BrotliState* s) {
BrotliBitReader* br = &s->br;
while (s->symbol < alphabet_size && s->space > 0) {
@@ -617,15 +610,15 @@
pullMoreInput:
if (!BrotliPullByte(br)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
}
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
/* Reads and decodes 15..18 codes using static prefix code.
Each code is 2..4 bits long. In total 30..72 bits are used. */
-static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) {
+static BrotliErrorCode ReadCodeLengthCodeLengths(BrotliState* s) {
BrotliBitReader* br = &s->br;
uint32_t num_codes = s->repeat;
unsigned space = s->space;
@@ -646,7 +639,7 @@
s->repeat = num_codes;
s->space = space;
s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
}
v = kCodeLengthPrefixValue[ix];
@@ -664,9 +657,9 @@
}
}
if (!(num_codes == 1 || space == 0)) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_CL_SPACE);
}
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
/* Decodes the Huffman tables.
@@ -681,10 +674,10 @@
B.2) Decoded table is used to decode code lengths of symbols in resulting
Huffman table. In worst case 3520 bits are read.
*/
-static BrotliResult ReadHuffmanCode(uint32_t alphabet_size,
- HuffmanCode* table,
- uint32_t* opt_table_size,
- BrotliState* s) {
+static BrotliErrorCode ReadHuffmanCode(uint32_t alphabet_size,
+ HuffmanCode* table,
+ uint32_t* opt_table_size,
+ BrotliState* s) {
BrotliBitReader* br = &s->br;
/* Unnecessary masking, but might be good for safety. */
alphabet_size &= 0x3ff;
@@ -692,7 +685,7 @@
switch (s->substate_huffman) {
case BROTLI_STATE_HUFFMAN_NONE:
if (!BrotliSafeReadBits(br, 2, &s->sub_loop_counter)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
BROTLI_LOG_UINT(s->sub_loop_counter);
/* The value is used as follows:
@@ -714,13 +707,13 @@
/* Read symbols, codes & code lengths directly. */
if (!BrotliSafeReadBits(br, 2, &s->symbol)) { /* num_symbols */
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->sub_loop_counter = 0;
/* No break, transit to the next state. */
case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
- BrotliResult result = ReadSimpleHuffmanSymbols(alphabet_size, s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ BrotliErrorCode result = ReadSimpleHuffmanSymbols(alphabet_size, s);
+ if (result != BROTLI_SUCCESS) {
return result;
}
/* No break, transit to the next state. */
@@ -731,7 +724,7 @@
uint32_t bits;
if (!BrotliSafeReadBits(br, 1, &bits)) {
s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->symbol += bits;
}
@@ -742,14 +735,14 @@
*opt_table_size = table_size;
}
s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
Complex: /* Decode Huffman-coded code lengths. */
case BROTLI_STATE_HUFFMAN_COMPLEX: {
uint32_t i;
- BrotliResult result = ReadCodeLengthCodeLengths(s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ BrotliErrorCode result = ReadCodeLengthCodeLengths(s);
+ if (result != BROTLI_SUCCESS) {
return result;
}
BrotliBuildCodeLengthsHuffmanTable(s->table,
@@ -771,17 +764,17 @@
}
case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
uint32_t table_size;
- BrotliResult result = ReadSymbolCodeLengths(alphabet_size, s);
- if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) {
+ BrotliErrorCode result = ReadSymbolCodeLengths(alphabet_size, s);
+ if (result == BROTLI_NEEDS_MORE_INPUT) {
result = SafeReadSymbolCodeLengths(alphabet_size, s);
}
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
return result;
}
if (s->space != 0) {
BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", s->space));
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_HUFFMAN_SPACE);
}
table_size = BrotliBuildHuffmanTable(
table, HUFFMAN_TABLE_BITS, s->symbol_lists, s->code_length_histo);
@@ -789,11 +782,11 @@
*opt_table_size = table_size;
}
s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
default:
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
}
}
@@ -855,7 +848,7 @@
/* Reinitialize elements that could have been changed. */
uint32_t i = 4;
uint32_t upper_bound = state->mtf_upper_bound;
- uint8_t* mtf = state->mtf;
+ uint8_t* mtf = &state->mtf[4]; /* Make mtf[-1] addressable. */
/* Load endian-aware constant. */
const uint8_t b0123[4] = {0, 1, 2, 3};
uint32_t pattern;
@@ -876,20 +869,19 @@
uint8_t value = mtf[index];
upper_bound |= v[i];
v[i] = value;
+ mtf[-1] = value;
do {
index--;
mtf[index + 1] = mtf[index];
- } while (index > 0);
- mtf[0] = value;
+ } while (index >= 0);
}
/* Remember amount of elements to be reinitialized. */
state->mtf_upper_bound = upper_bound;
}
-
/* Decodes a series of Huffman table using ReadHuffmanCode function. */
-static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
- BrotliState* s) {
+static BrotliErrorCode HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
+ BrotliState* s) {
if (s->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
s->next = group->codes;
s->htree_index = 0;
@@ -897,15 +889,15 @@
}
while (s->htree_index < group->num_htrees) {
uint32_t table_size;
- BrotliResult result =
+ BrotliErrorCode result =
ReadHuffmanCode(group->alphabet_size, s->next, &table_size, s);
- if (result != BROTLI_RESULT_SUCCESS) return result;
+ if (result != BROTLI_SUCCESS) return result;
group->htrees[s->htree_index] = s->next;
s->next += table_size;
++s->htree_index;
}
s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
/* Decodes a context map.
@@ -917,17 +909,17 @@
3) Read context map items; "0" values could be run-length encoded.
4) Optionally, apply InverseMoveToFront transform to the resulting map.
*/
-static BrotliResult DecodeContextMap(uint32_t context_map_size,
- uint32_t* num_htrees,
- uint8_t** context_map_arg,
- BrotliState* s) {
+static BrotliErrorCode DecodeContextMap(uint32_t context_map_size,
+ uint32_t* num_htrees,
+ uint8_t** context_map_arg,
+ BrotliState* s) {
BrotliBitReader* br = &s->br;
- BrotliResult result = BROTLI_RESULT_SUCCESS;
+ BrotliErrorCode result = BROTLI_SUCCESS;
switch ((int)s->substate_context_map) {
case BROTLI_STATE_CONTEXT_MAP_NONE:
result = DecodeVarLenUint8(s, br, num_htrees);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
return result;
}
(*num_htrees)++;
@@ -936,11 +928,11 @@
BROTLI_LOG_UINT(*num_htrees);
*context_map_arg = (uint8_t*)BROTLI_ALLOC(s, (size_t)context_map_size);
if (*context_map_arg == 0) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_ALLOC_CONTEXT_MAP);
}
if (*num_htrees <= 1) {
memset(*context_map_arg, 0, (size_t)context_map_size);
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
/* No break, continue to next state. */
@@ -949,7 +941,7 @@
/* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
to peek 4 bits ahead. */
if (!BrotliSafeGetBits(br, 5, &bits)) {
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if ((bits & 1) != 0) { /* Use RLE for zeroes. */
s->max_run_length_prefix = (bits >> 1) + 1;
@@ -965,7 +957,7 @@
case BROTLI_STATE_CONTEXT_MAP_HUFFMAN:
result = ReadHuffmanCode(*num_htrees + s->max_run_length_prefix,
s->context_map_table, NULL, s);
- if (result != BROTLI_RESULT_SUCCESS) return result;
+ if (result != BROTLI_SUCCESS) return result;
s->code = 0xFFFF;
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
/* No break, continue to next state. */
@@ -981,7 +973,7 @@
if (!SafeReadSymbol(s->context_map_table, br, &code)) {
s->code = 0xFFFF;
s->context_index = context_index;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
BROTLI_LOG_UINT(code);
@@ -1000,12 +992,12 @@
if (!BrotliSafeReadBits(br, code, &reps)) {
s->code = code;
s->context_index = context_index;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
reps += 1U << code;
BROTLI_LOG_UINT(reps);
if (context_index + reps > context_map_size) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_CONTEXT_MAP_REPEAT);
}
do {
context_map[context_index++] = 0;
@@ -1018,16 +1010,16 @@
uint32_t bits;
if (!BrotliSafeReadBits(br, 1, &bits)) {
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
if (bits != 0) {
InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);
}
s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
default:
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
}
}
@@ -1074,22 +1066,45 @@
return 1;
}
+static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(BrotliState* s) {
+ size_t i;
+ for (i = 0; i < 8; ++i) s->trivial_literal_contexts[i] = 0;
+ for (i = 0; i < s->num_block_types[0]; i++) {
+ size_t offset = i << kLiteralContextBits;
+ size_t error = 0;
+ size_t sample = s->context_map[offset];
+ size_t j;
+ for (j = 0; j < (1u << kLiteralContextBits);) {
+ BROTLI_REPEAT(4, error |= s->context_map[offset + j++] ^ sample;)
+ }
+ if (error == 0) {
+ s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);
+ }
+ }
+}
+
+static BROTLI_INLINE void PrepareLiteralDecoding(BrotliState* s) {
+ uint8_t context_mode;
+ size_t trivial;
+ uint32_t block_type = s->block_type_rb[1];
+ uint32_t context_offset = block_type << kLiteralContextBits;
+ s->context_map_slice = s->context_map + context_offset;
+ trivial = s->trivial_literal_contexts[block_type >> 5];
+ s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;
+ s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];
+ context_mode = s->context_modes[block_type];
+ s->context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode]];
+ s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]];
+}
+
/* Decodes the block type and updates the state for literal context.
Reads 3..54 bits. */
static BROTLI_INLINE int DecodeLiteralBlockSwitchInternal(int safe,
BrotliState* s) {
- uint8_t context_mode;
- uint32_t context_offset;
if (!DecodeBlockTypeAndLength(safe, s, 0)) {
return 0;
}
- context_offset = s->block_type_rb[1] << kLiteralContextBits;
- s->context_map_slice = s->context_map + context_offset;
- s->literal_htree_index = s->context_map_slice[0];
- s->literal_htree = s->literal_hgroup.htrees[s->literal_htree_index];
- context_mode = s->context_modes[s->block_type_rb[1]];
- s->context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode]];
- s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]];
+ PrepareLiteralDecoding(s);
return 1;
}
@@ -1140,8 +1155,8 @@
return DecodeDistanceBlockSwitchInternal(1, s);
}
-static BrotliResult WriteRingBuffer(size_t* available_out, uint8_t** next_out,
- size_t* total_out, BrotliState* s) {
+static BrotliErrorCode BROTLI_NOINLINE WriteRingBuffer(size_t* available_out,
+ uint8_t** next_out, size_t* total_out, BrotliState* s) {
size_t pos = (s->pos > s->ringbuffer_size) ? (size_t)s->ringbuffer_size
: (size_t)(s->pos);
uint8_t* start =
@@ -1153,7 +1168,7 @@
num_written = to_write;
}
if (s->meta_block_remaining_len < 0) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_BLOCK_LENGTH_1);
}
memcpy(*next_out, start, num_written);
*next_out += num_written;
@@ -1161,11 +1176,16 @@
BROTLI_LOG_UINT(to_write);
BROTLI_LOG_UINT(num_written);
s->partial_pos_out += num_written;
- *total_out = s->partial_pos_out;
+ if (total_out) *total_out = s->partial_pos_out;
if (num_written < to_write) {
- return BROTLI_RESULT_NEEDS_MORE_OUTPUT;
+ return BROTLI_NEEDS_MORE_OUTPUT;
}
- return BROTLI_RESULT_SUCCESS;
+
+ if (s->pos >= s->ringbuffer_size) {
+ s->pos -= s->ringbuffer_size;
+ s->rb_roundtrips++;
+ }
+ return BROTLI_SUCCESS;
}
/* Allocates ringbuffer.
@@ -1202,12 +1222,12 @@
return 1;
}
-static BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput(
+static BrotliErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
size_t* available_out, uint8_t** next_out, size_t* total_out,
BrotliState* s) {
/* TODO: avoid allocation for single uncompressed block. */
if (!s->ringbuffer && !BrotliAllocateRingBuffer(s)) {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_ALLOC_RING_BUFFER_1);
}
/* State machine */
@@ -1227,21 +1247,19 @@
s->meta_block_remaining_len -= nbytes;
if (s->pos < s->ringbuffer_size) {
if (s->meta_block_remaining_len == 0) {
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;
/* No break, continue to next state */
}
case BROTLI_STATE_UNCOMPRESSED_WRITE: {
- BrotliResult result =
+ BrotliErrorCode result =
WriteRingBuffer(available_out, next_out, total_out, s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
return result;
}
- s->pos = 0;
- s->rb_roundtrips++;
s->max_distance = s->max_backward_distance;
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
break;
@@ -1248,7 +1266,7 @@
}
}
}
- return BROTLI_FAILURE();
+ BROTLI_DCHECK(0); /* Unreachable */
}
int BrotliDecompressedSize(size_t encoded_size,
@@ -1263,7 +1281,7 @@
return 0;
}
DecodeWindowBits(&s.br);
- if (DecodeMetaBlockLength(&s, &s.br) != BROTLI_RESULT_SUCCESS) {
+ if (DecodeMetaBlockLength(&s, &s.br) != BROTLI_SUCCESS) {
return 0;
}
*decoded_size = (size_t)s.meta_block_remaining_len;
@@ -1287,7 +1305,8 @@
static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(BrotliState* s,
BrotliBitReader* br) {
int is_last = s->is_last_metablock;
- s->ringbuffer_size = 1 << s->window_bits;
+ int window_size = 1 << s->window_bits;
+ s->ringbuffer_size = window_size;
if (s->is_uncompressed) {
int next_block_header =
@@ -1302,22 +1321,17 @@
/* We need at least 2 bytes of ring buffer size to get the last two
bytes for context from there */
if (is_last) {
- while (s->ringbuffer_size >= s->meta_block_remaining_len * 2 &&
- s->ringbuffer_size > 32) {
+ int min_size_x2 = (s->meta_block_remaining_len + s->custom_dict_size) * 2;
+ while (s->ringbuffer_size >= min_size_x2 && s->ringbuffer_size > 32) {
s->ringbuffer_size >>= 1;
}
}
- /* But make it fit the custom dictionary if there is one. */
- while (s->ringbuffer_size < s->custom_dict_size) {
- s->ringbuffer_size <<= 1;
- }
-
s->ringbuffer_mask = s->ringbuffer_size - 1;
}
/* Reads 1..256 2-bit context modes. */
-static BrotliResult ReadContextModes(BrotliState* s) {
+static BrotliErrorCode ReadContextModes(BrotliState* s) {
BrotliBitReader* br = &s->br;
int i = s->loop_counter;
@@ -1325,13 +1339,13 @@
uint32_t bits;
if (!BrotliSafeReadBits(br, 2, &bits)) {
s->loop_counter = i;
- return BROTLI_RESULT_NEEDS_MORE_INPUT;
+ return BROTLI_NEEDS_MORE_INPUT;
}
s->context_modes[i] = (uint8_t)(bits << 1);
BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);
i++;
}
- return BROTLI_RESULT_SUCCESS;
+ return BROTLI_SUCCESS;
}
static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliState* s) {
@@ -1495,27 +1509,27 @@
return BrotliCheckInputAmount(br, num);
}
-#define BROTLI_SAFE(METHOD) \
- { \
- if (safe) { \
- if (!Safe##METHOD) { \
- result = BROTLI_RESULT_NEEDS_MORE_INPUT; \
- goto saveStateAndReturn; \
- } \
- } else { \
- METHOD; \
- } \
+#define BROTLI_SAFE(METHOD) \
+ { \
+ if (safe) { \
+ if (!Safe##METHOD) { \
+ result = BROTLI_NEEDS_MORE_INPUT; \
+ goto saveStateAndReturn; \
+ } \
+ } else { \
+ METHOD; \
+ } \
}
-static BROTLI_INLINE BrotliResult ProcessCommandsInternal(int safe,
+static BROTLI_INLINE BrotliErrorCode ProcessCommandsInternal(int safe,
BrotliState* s) {
int pos = s->pos;
int i = s->loop_counter;
- BrotliResult result = BROTLI_RESULT_SUCCESS;
+ BrotliErrorCode result = BROTLI_SUCCESS;
BrotliBitReader* br = &s->br;
if (!CheckInputAmount(safe, br, 28)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (!safe) {
@@ -1532,7 +1546,7 @@
} else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) {
goto CommandPostWrapCopy;
} else {
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE);
}
CommandBegin:
@@ -1541,7 +1555,7 @@
}
if (!CheckInputAmount(safe, br, 28)) { /* 156 bits + 7 bytes */
s->state = BROTLI_STATE_COMMAND_BEGIN;
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (PREDICT_FALSE(s->block_length[1] == 0)) {
@@ -1569,12 +1583,13 @@
do {
if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
s->state = BROTLI_STATE_COMMAND_INNER;
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (PREDICT_FALSE(s->block_length[0] == 0)) {
BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
+ if (!s->trivial_literal_context) goto CommandInner;
}
if (!safe) {
s->ringbuffer[pos] =
@@ -1582,13 +1597,12 @@
} else {
uint32_t literal;
if (!SafeReadSymbol(s->literal_htree, br, &literal)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
s->ringbuffer[pos] = (uint8_t)literal;
}
--s->block_length[0];
- BROTLI_LOG_UINT(s->literal_htree_index);
BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);
++pos;
if (PREDICT_FALSE(pos == s->ringbuffer_size)) {
@@ -1605,11 +1619,12 @@
uint8_t context;
if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
s->state = BROTLI_STATE_COMMAND_INNER;
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
if (PREDICT_FALSE(s->block_length[0] == 0)) {
BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
+ if (s->trivial_literal_context) goto CommandInner;
}
context = s->context_lookup1[p1] | s->context_lookup2[p2];
BROTLI_LOG_UINT(context);
@@ -1620,7 +1635,7 @@
} else {
uint32_t literal;
if (!SafeReadSymbol(hc, br, &literal)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
goto saveStateAndReturn;
}
p1 = (uint8_t)literal;
@@ -1638,7 +1653,7 @@
} while (--i != 0);
}
BROTLI_LOG_UINT(s->meta_block_remaining_len);
- if (s->meta_block_remaining_len <= 0) {
+ if (PREDICT_FALSE(s->meta_block_remaining_len <= 0)) {
s->state = BROTLI_STATE_METABLOCK_DONE;
goto saveStateAndReturn;
}
@@ -1700,13 +1715,13 @@
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n",
pos, s->distance_code, i, s->meta_block_remaining_len));
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_TRANSFORM);
}
} else {
BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
"len: %d bytes left: %d\n",
pos, s->distance_code, i, s->meta_block_remaining_len));
- return BROTLI_FAILURE();
+ return BROTLI_FAILURE(BROTLI_ERROR_FORMAT_DICTIONARY);
}
} else {
int src_start = (pos - s->distance_code) & s->ringbuffer_mask;
@@ -1718,12 +1733,6 @@
s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
++s->dist_rb_idx;
s->meta_block_remaining_len -= i;
- if (PREDICT_FALSE(s->meta_block_remaining_len < 0)) {
- BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
- "len: %d bytes left: %d\n",
- pos, s->distance_code, i, s->meta_block_remaining_len));
- return BROTLI_FAILURE();
- }
/* There are 32+ bytes of slack in the ringbuffer allocation.
Also, we have 16 short codes, that make these 16 bytes irrelevant
in the ringbuffer. Let's copy over them as a first guess.
@@ -1785,11 +1794,11 @@
#undef BROTLI_SAFE
-static BROTLI_NOINLINE BrotliResult ProcessCommands(BrotliState* s) {
+static BROTLI_NOINLINE BrotliErrorCode ProcessCommands(BrotliState* s) {
return ProcessCommandsInternal(0, s);
}
-static BROTLI_NOINLINE BrotliResult SafeProcessCommands(BrotliState* s) {
+static BROTLI_NOINLINE BrotliErrorCode SafeProcessCommands(BrotliState* s) {
return ProcessCommandsInternal(1, s);
}
@@ -1830,7 +1839,7 @@
BrotliResult BrotliDecompressStream(size_t* available_in,
const uint8_t** next_in, size_t* available_out, uint8_t** next_out,
size_t* total_out, BrotliState* s) {
- BrotliResult result = BROTLI_RESULT_SUCCESS;
+ BrotliErrorCode result = BROTLI_SUCCESS;
BrotliBitReader* br = &s->br;
if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */
br->avail_in = *available_in;
@@ -1839,13 +1848,13 @@
/* At least one byte of input is required. More than one byte of input may
be required to complete the transaction -> reading more data must be
done in a loop -> do it in a main loop. */
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
br->next_in = &s->buffer.u8[0];
}
/* State machine */
for (;;) {
- if (result != BROTLI_RESULT_SUCCESS) { /* Error | needs more input/output */
- if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) {
+ if (result != BROTLI_SUCCESS) { /* Error | needs more input/output */
+ if (result == BROTLI_NEEDS_MORE_INPUT) {
if (s->ringbuffer != 0) { /* Proactively push output. */
WriteRingBuffer(available_out, next_out, total_out, s);
}
@@ -1855,7 +1864,7 @@
is expanded byte-by-byte until it is enough to complete read. */
s->buffer_length = 0;
/* Switch to input stream and restart. */
- result = BROTLI_RESULT_SUCCESS;
+ result = BROTLI_SUCCESS;
br->avail_in = *available_in;
br->next_in = *next_in;
continue;
@@ -1862,7 +1871,7 @@
} else if (*available_in != 0) {
/* Not enough data in buffer, but can take one more byte from
input stream. */
- result = BROTLI_RESULT_SUCCESS;
+ result = BROTLI_SUCCESS;
s->buffer.u8[s->buffer_length] = **next_in;
s->buffer_length++;
br->avail_in = s->buffer_length;
@@ -1908,7 +1917,7 @@
case BROTLI_STATE_UNINITED:
/* Prepare to the first read. */
if (!BrotliWarmupBitReader(br)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
break;
}
/* Decode window size. */
@@ -1916,10 +1925,16 @@
BROTLI_LOG_UINT(s->window_bits);
if (s->window_bits == 9) {
/* Value 9 is reserved for future use. */
- result = BROTLI_FAILURE();
+ result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_WINDOW_BITS);
break;
}
+ /* Maximum distance, see section 9.1. of the spec. */
s->max_backward_distance = (1 << s->window_bits) - 16;
+ /* Limit custom dictionary size. */
+ if (s->custom_dict_size >= s->max_backward_distance) {
+ s->custom_dict += s->custom_dict_size - s->max_backward_distance;
+ s->custom_dict_size = s->max_backward_distance;
+ }
s->max_backward_distance_minus_custom_dict_size =
s->max_backward_distance - s->custom_dict_size;
@@ -1928,7 +1943,7 @@
sizeof(HuffmanCode) * 3 *
(BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26));
if (s->block_type_trees == 0) {
- result = BROTLI_FAILURE();
+ result = BROTLI_FAILURE(BROTLI_ERROR_ALLOC_BLOCK_TYPE_TREES);
break;
}
s->block_len_trees =
@@ -1943,7 +1958,7 @@
/* No break, continue to next state */
case BROTLI_STATE_METABLOCK_HEADER:
result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
BROTLI_LOG_UINT(s->is_last_metablock);
@@ -1952,7 +1967,7 @@
BROTLI_LOG_UINT(s->is_uncompressed);
if (s->is_metadata || s->is_uncompressed) {
if (!BrotliJumpToByteBoundary(br)) {
- result = BROTLI_FAILURE();
+ result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_PADDING_1);
break;
}
}
@@ -1979,7 +1994,7 @@
result = CopyUncompressedBlockToOutput(
available_out, next_out, total_out, s);
bytes_copied -= s->meta_block_remaining_len;
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
s->state = BROTLI_STATE_METABLOCK_DONE;
@@ -1990,11 +2005,11 @@
uint32_t bits;
/* Read one byte and ignore it. */
if (!BrotliSafeReadBits(br, 8, &bits)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
break;
}
}
- if (result == BROTLI_RESULT_SUCCESS) {
+ if (result == BROTLI_SUCCESS) {
s->state = BROTLI_STATE_METABLOCK_DONE;
}
break;
@@ -2005,7 +2020,7 @@
}
/* Reads 1..11 bits. */
result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
s->num_block_types[s->loop_counter]++;
@@ -2020,7 +2035,7 @@
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258;
result = ReadHuffmanCode(s->num_block_types[s->loop_counter] + 2,
&s->block_type_trees[tree_offset], NULL, s);
- if (result != BROTLI_RESULT_SUCCESS) break;
+ if (result != BROTLI_SUCCESS) break;
s->state = BROTLI_STATE_HUFFMAN_CODE_2;
/* No break, continue to next state */
}
@@ -2028,7 +2043,7 @@
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
result = ReadHuffmanCode(kNumBlockLengthCodes,
&s->block_len_trees[tree_offset], NULL, s);
- if (result != BROTLI_RESULT_SUCCESS) break;
+ if (result != BROTLI_SUCCESS) break;
s->state = BROTLI_STATE_HUFFMAN_CODE_3;
/* No break, continue to next state */
}
@@ -2036,7 +2051,7 @@
int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter],
&s->block_len_trees[tree_offset], br)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
break;
}
BROTLI_LOG_UINT(s->block_length[s->loop_counter]);
@@ -2047,7 +2062,7 @@
case BROTLI_STATE_METABLOCK_HEADER_2: {
uint32_t bits;
if (!BrotliSafeReadBits(br, 6, &bits)) {
- result = BROTLI_RESULT_NEEDS_MORE_INPUT;
+ result = BROTLI_NEEDS_MORE_INPUT;
break;
}
s->distance_postfix_bits = bits & BitMask(2);
@@ -2060,7 +2075,7 @@
s->context_modes =
(uint8_t*)BROTLI_ALLOC(s, (size_t)s->num_block_types[0]);
if (s->context_modes == 0) {
- result = BROTLI_FAILURE();
+ result = BROTLI_FAILURE(BROTLI_ERROR_ALLOC_CONTEXT_MODES);
break;
}
s->loop_counter = 0;
@@ -2069,28 +2084,21 @@
}
case BROTLI_STATE_CONTEXT_MODES:
result = ReadContextModes(s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
s->state = BROTLI_STATE_CONTEXT_MAP_1;
/* No break, continue to next state */
- case BROTLI_STATE_CONTEXT_MAP_1: {
- uint32_t j;
- result = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits,
- &s->num_literal_htrees, &s->context_map, s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ case BROTLI_STATE_CONTEXT_MAP_1:
+ result = DecodeContextMap(
+ s->num_block_types[0] << kLiteralContextBits,
+ &s->num_literal_htrees, &s->context_map, s);
+ if (result != BROTLI_SUCCESS) {
break;
}
- s->trivial_literal_context = 1;
- for (j = 0; j < s->num_block_types[0] << kLiteralContextBits; j++) {
- if (s->context_map[j] != j >> kLiteralContextBits) {
- s->trivial_literal_context = 0;
- break;
- }
- }
+ DetectTrivialLiteralBlockTypes(s);
s->state = BROTLI_STATE_CONTEXT_MAP_2;
/* No break, continue to next state */
- }
case BROTLI_STATE_CONTEXT_MAP_2:
{
uint32_t num_distance_codes =
@@ -2098,7 +2106,7 @@
result = DecodeContextMap(
s->num_block_types[2] << kDistanceContextBits,
&s->num_dist_htrees, &s->dist_context_map, s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
BrotliHuffmanTreeGroupInit(s, &s->literal_hgroup, kNumLiteralCodes,
@@ -2111,7 +2119,8 @@
if (s->literal_hgroup.codes == 0 ||
s->insert_copy_hgroup.codes == 0 ||
s->distance_hgroup.codes == 0) {
- return BROTLI_FAILURE();
+ return SaveErrorCode(s,
+ BROTLI_FAILURE(BROTLI_ERROR_ALLOC_TREE_GROUPS));
}
}
s->loop_counter = 0;
@@ -2131,24 +2140,19 @@
hgroup = &s->distance_hgroup;
break;
default:
- return BROTLI_FAILURE();
+ return SaveErrorCode(s,
+ BROTLI_FAILURE(BROTLI_ERROR_UNREACHABLE));
}
result = HuffmanTreeGroupDecode(hgroup, s);
}
- if (result != BROTLI_RESULT_SUCCESS) break;
+ if (result != BROTLI_SUCCESS) break;
s->loop_counter++;
if (s->loop_counter >= 3) {
- uint8_t context_mode = s->context_modes[s->block_type_rb[1]];
- s->context_map_slice = s->context_map;
+ PrepareLiteralDecoding(s);
s->dist_context_map_slice = s->dist_context_map;
- s->context_lookup1 =
- &kContextLookup[kContextLookupOffsets[context_mode]];
- s->context_lookup2 =
- &kContextLookup[kContextLookupOffsets[context_mode + 1]];
s->htree_command = s->insert_copy_hgroup.htrees[0];
- s->literal_htree = s->literal_hgroup.htrees[s->literal_htree_index];
if (!s->ringbuffer && !BrotliAllocateRingBuffer(s)) {
- result = BROTLI_FAILURE();
+ result = BROTLI_FAILURE(BROTLI_ERROR_ALLOC_RING_BUFFER_2);
break;
}
s->state = BROTLI_STATE_COMMAND_BEGIN;
@@ -2159,7 +2163,7 @@
case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS:
case BROTLI_STATE_COMMAND_POST_WRAP_COPY:
result = ProcessCommands(s);
- if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) {
+ if (result == BROTLI_NEEDS_MORE_INPUT) {
result = SafeProcessCommands(s);
}
break;
@@ -2167,11 +2171,9 @@
case BROTLI_STATE_COMMAND_POST_WRITE_1:
case BROTLI_STATE_COMMAND_POST_WRITE_2:
result = WriteRingBuffer(available_out, next_out, total_out, s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
- s->pos -= s->ringbuffer_size;
- s->rb_roundtrips++;
s->max_distance = s->max_backward_distance;
if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {
memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos);
@@ -2197,6 +2199,10 @@
}
break;
case BROTLI_STATE_METABLOCK_DONE:
+ if (s->meta_block_remaining_len < 0) {
+ result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_BLOCK_LENGTH_2);
+ break;
+ }
BrotliStateCleanupAfterMetablock(s);
if (!s->is_last_metablock) {
s->state = BROTLI_STATE_METABLOCK_BEGIN;
@@ -2203,7 +2209,8 @@
break;
}
if (!BrotliJumpToByteBoundary(br)) {
- result = BROTLI_FAILURE();
+ result = BROTLI_FAILURE(BROTLI_ERROR_FORMAT_PADDING_2);
+ break;
}
if (s->buffer_length == 0) {
BrotliBitReaderUnload(br);
@@ -2215,23 +2222,41 @@
case BROTLI_STATE_DONE:
if (s->ringbuffer != 0) {
result = WriteRingBuffer(available_out, next_out, total_out, s);
- if (result != BROTLI_RESULT_SUCCESS) {
+ if (result != BROTLI_SUCCESS) {
break;
}
}
- return result;
+ return SaveErrorCode(s, result);
}
}
- return result;
+ return SaveErrorCode(s, result);
}
void BrotliSetCustomDictionary(
size_t size, const uint8_t* dict, BrotliState* s) {
+ if (size > (1u << 24)) {
+ return;
+ }
s->custom_dict = dict;
s->custom_dict_size = (int)size;
}
+BrotliErrorCode BrotliGetErrorCode(const BrotliState* s) {
+ return (BrotliErrorCode)s->error_code;
+}
+const char* BrotliErrorString(BrotliErrorCode c) {
+ switch (c) {
+#define _BROTLI_ERROR_CODE_CASE(PREFIX, NAME, CODE) \
+ case BROTLI ## PREFIX ## NAME: return #NAME;
+#define _BROTLI_NOTHING
+ BROTLI_ERROR_CODES_LIST(_BROTLI_ERROR_CODE_CASE, _BROTLI_NOTHING)
+#undef _BROTLI_ERROR_CODE_CASE
+#undef _BROTLI_NOTHING
+ default: return "INVALID";
+ }
+}
+
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif
Modified: trunk/Source/ThirdParty/brotli/dec/decode.h (202224 => 202225)
--- trunk/Source/ThirdParty/brotli/dec/decode.h 2016-06-20 05:53:20 UTC (rev 202224)
+++ trunk/Source/ThirdParty/brotli/dec/decode.h 2016-06-20 06:56:22 UTC (rev 202225)
@@ -9,7 +9,6 @@
#ifndef BROTLI_DEC_DECODE_H_
#define BROTLI_DEC_DECODE_H_
-#include "./state.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
@@ -16,6 +15,8 @@
extern "C" {
#endif
+typedef struct BrotliStateStruct BrotliState;
+
typedef enum {
/* Decoding error, e.g. corrupt input or memory allocation problem */
BROTLI_RESULT_ERROR = 0,
@@ -27,6 +28,57 @@
BROTLI_RESULT_NEEDS_MORE_OUTPUT = 3
} BrotliResult;
+#define BROTLI_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR) \
+ BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR \
+ /* Same as BrotliResult values */ \
+ BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR \
+ BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR \
+ BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR \
+ \
+ /* Errors caused by invalid input */ \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \
+ \
+ /* -16..-20 codes are reserved */ \
+ \
+ /* Memory allocation problems */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR \
+ /* Literal, insert and distance trees together */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR \
+ /* -23..-24 codes are reserved for distinct tree groups */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR \
+ /* -28..-29 codes are reserved for dynamic ringbuffer allocation */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR \
+ \
+ /* "Impossible" states */ \
+ BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31)
+
+typedef enum {
+#define _BROTLI_COMMA ,
+#define _BROTLI_ERROR_CODE_ENUM_ITEM(PREFIX, NAME, CODE) \
+ BROTLI ## PREFIX ## NAME = CODE
+ BROTLI_ERROR_CODES_LIST(_BROTLI_ERROR_CODE_ENUM_ITEM, _BROTLI_COMMA)
+#undef _BROTLI_ERROR_CODE_ENUM_ITEM
+#undef _BROTLI_COMMA
+} BrotliErrorCode;
+
+#define BROTLI_LAST_ERROR_CODE BROTLI_ERROR_UNREACHABLE
+
/* Creates the instance of BrotliState and initializes it. |alloc_func| and
|free_func| MUST be both zero or both non-zero. In the case they are both
zero, default memory allocators are used. |opaque| is passed to |alloc_func|
@@ -63,8 +115,8 @@
bytes consumed, and the |*next_in| pointer will be incremented by that
amount. Similarly, |*available_out| will be decremented by the amount of
output bytes written, and the |*next_out| pointer will be incremented by that
- amount. |total_out| will be set to the number of bytes decompressed since
- last state initialization.
+ amount. |total_out|, if it is not a null-pointer, will be set to the number
+ of bytes decompressed since the last state initialization.
Input is never overconsumed, so |next_in| and |available_in| could be passed
to the next consumer after decoding is complete. */
@@ -78,17 +130,31 @@
/* Fills the new state with a dictionary for LZ77, warming up the ringbuffer,
e.g. for custom static dictionaries for data formats.
Not to be confused with the built-in transformable dictionary of Brotli.
- The dictionary must exist in memory until decoding is done and is owned by
- the caller. To use:
- 1) initialize state with BrotliStateInit
- 2) use BrotliSetCustomDictionary
- 3) use BrotliDecompressStream
- 4) clean up with BrotliStateCleanup
+ |size| should be less or equal to 2^24 (16MiB), otherwise the dictionary will
+ be ignored. The dictionary must exist in memory until decoding is done and
+ is owned by the caller. To use:
+ 1) Allocate and initialize state with BrotliCreateState
+ 2) Use BrotliSetCustomDictionary
+ 3) Use BrotliDecompressStream
+ 4) Clean up and free state with BrotliDestroyState
*/
void BrotliSetCustomDictionary(
size_t size, const uint8_t* dict, BrotliState* s);
+/* Returns 1, if s is in a state where we have not read any input bytes yet,
+ and 0 otherwise */
+int BrotliStateIsStreamStart(const BrotliState* s);
+/* Returns 1, if s is in a state where we reached the end of the input and
+ produced all of the output, and 0 otherwise. */
+int BrotliStateIsStreamEnd(const BrotliState* s);
+
+/* Returns detailed error code after BrotliDecompressStream returns
+ BROTLI_RESULT_ERROR. */
+BrotliErrorCode BrotliGetErrorCode(const BrotliState* s);
+
+const char* BrotliErrorString(BrotliErrorCode c);
+
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif