mirror of
https://github.com/google/brotli.git
synced 2024-11-22 03:30:07 +00:00
Change the return value of decoder functions from integer codes to an enum.
This commit is contained in:
parent
c9cc258cdd
commit
c5ccd0dff9
296
dec/decode.c
296
dec/decode.c
@ -129,7 +129,7 @@ static void PrintUcharVector(const uint8_t* v, int len) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int ReadHuffmanCodeLengths(
|
||||
static BrotliResult ReadHuffmanCodeLengths(
|
||||
const uint8_t* code_length_code_lengths,
|
||||
int num_symbols, uint8_t* code_lengths,
|
||||
BrotliState* s) {
|
||||
@ -147,7 +147,7 @@ static int ReadHuffmanCodeLengths(
|
||||
CODE_LENGTH_CODES)) {
|
||||
printf("[ReadHuffmanCodeLengths] Building code length tree failed: ");
|
||||
PrintUcharVector(code_length_code_lengths, CODE_LENGTH_CODES);
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS;
|
||||
/* No break, continue to next state. */
|
||||
@ -156,7 +156,7 @@ static int ReadHuffmanCodeLengths(
|
||||
const HuffmanCode* p = s->table;
|
||||
uint8_t code_len;
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
BrotliFillBitWindow(br);
|
||||
p += (br->val_ >> br->bit_pos_) & 31;
|
||||
@ -189,7 +189,7 @@ static int ReadHuffmanCodeLengths(
|
||||
s->repeat += (int)BrotliReadBits(br, extra_bits) + 3;
|
||||
repeat_delta = s->repeat - old_repeat;
|
||||
if (s->symbol + repeat_delta > num_symbols) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
memset(&code_lengths[s->symbol], s->repeat_code_len,
|
||||
(size_t)repeat_delta);
|
||||
@ -201,36 +201,36 @@ static int ReadHuffmanCodeLengths(
|
||||
}
|
||||
if (s->space != 0) {
|
||||
printf("[ReadHuffmanCodeLengths] s->space = %d\n", s->space);
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
memset(&code_lengths[s->symbol], 0, (size_t)(num_symbols - s->symbol));
|
||||
s->sub_state[1] = BROTLI_STATE_SUB_NONE;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
default:
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
|
||||
static int ReadHuffmanCode(int alphabet_size,
|
||||
HuffmanCode* table,
|
||||
int* opt_table_size,
|
||||
BrotliState* s) {
|
||||
static BrotliResult ReadHuffmanCode(int alphabet_size,
|
||||
HuffmanCode* table,
|
||||
int* opt_table_size,
|
||||
BrotliState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
int ok = 1;
|
||||
BrotliResult result = BROTLI_RESULT_SUCCESS;
|
||||
int table_size = 0;
|
||||
/* State machine */
|
||||
for (;;) {
|
||||
switch(s->sub_state[1]) {
|
||||
case BROTLI_STATE_SUB_NONE:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
s->code_lengths =
|
||||
(uint8_t*)BrotliSafeMalloc((uint64_t)alphabet_size,
|
||||
sizeof(*s->code_lengths));
|
||||
if (s->code_lengths == NULL) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
/* simple_code_or_skip is used as follows:
|
||||
1 for simple code;
|
||||
@ -258,21 +258,27 @@ static int ReadHuffmanCode(int alphabet_size,
|
||||
case 1:
|
||||
break;
|
||||
case 3:
|
||||
ok = ((symbols[0] != symbols[1]) &&
|
||||
(symbols[0] != symbols[2]) &&
|
||||
(symbols[1] != symbols[2]));
|
||||
if ((symbols[0] == symbols[1]) ||
|
||||
(symbols[0] == symbols[2]) ||
|
||||
(symbols[1] == symbols[2])) {
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
ok = (symbols[0] != symbols[1]);
|
||||
if (symbols[0] == symbols[1]) {
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
s->code_lengths[symbols[1]] = 1;
|
||||
break;
|
||||
case 4:
|
||||
ok = ((symbols[0] != symbols[1]) &&
|
||||
(symbols[0] != symbols[2]) &&
|
||||
(symbols[0] != symbols[3]) &&
|
||||
(symbols[1] != symbols[2]) &&
|
||||
(symbols[1] != symbols[3]) &&
|
||||
(symbols[2] != symbols[3]));
|
||||
if ((symbols[0] == symbols[1]) ||
|
||||
(symbols[0] == symbols[2]) ||
|
||||
(symbols[0] == symbols[3]) ||
|
||||
(symbols[1] == symbols[2]) ||
|
||||
(symbols[1] == symbols[3]) ||
|
||||
(symbols[2] == symbols[3])) {
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
if (BrotliReadBits(br, 1)) {
|
||||
s->code_lengths[symbols[2]] = 3;
|
||||
s->code_lengths[symbols[3]] = 3;
|
||||
@ -281,7 +287,6 @@ static int ReadHuffmanCode(int alphabet_size,
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!ok) return 0;
|
||||
BROTLI_LOG_UINT(num_symbols);
|
||||
s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_DONE;
|
||||
break;
|
||||
@ -314,25 +319,25 @@ static int ReadHuffmanCode(int alphabet_size,
|
||||
}
|
||||
}
|
||||
if (!(num_codes == 1 || space == 0)) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN;
|
||||
}
|
||||
/* No break, go to next state */
|
||||
case BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN:
|
||||
case BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS:
|
||||
ok = ReadHuffmanCodeLengths(s->code_length_code_lengths,
|
||||
alphabet_size, s->code_lengths, s);
|
||||
if (ok != 1) return ok;
|
||||
result = ReadHuffmanCodeLengths(s->code_length_code_lengths,
|
||||
alphabet_size, s->code_lengths, s);
|
||||
if (result != BROTLI_RESULT_SUCCESS) return result;
|
||||
s->sub_state[1] = BROTLI_STATE_SUB_HUFFMAN_DONE;
|
||||
/* No break, go to next state */
|
||||
case BROTLI_STATE_SUB_HUFFMAN_DONE:
|
||||
table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS,
|
||||
s->code_lengths, alphabet_size);
|
||||
if (table_size == 0) {
|
||||
ok = 0;
|
||||
printf("[ReadHuffmanCode] BuildHuffmanTable failed: ");
|
||||
PrintUcharVector(s->code_lengths, alphabet_size);
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
free(s->code_lengths);
|
||||
s->code_lengths = NULL;
|
||||
@ -340,13 +345,13 @@ static int ReadHuffmanCode(int alphabet_size,
|
||||
*opt_table_size = table_size;
|
||||
}
|
||||
s->sub_state[1] = BROTLI_STATE_SUB_NONE;
|
||||
return ok;
|
||||
return result;
|
||||
default:
|
||||
return 0; /* unknown state */
|
||||
return BROTLI_RESULT_ERROR; /* unknown state */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
|
||||
static BROTLI_INLINE int ReadBlockLength(const HuffmanCode* table,
|
||||
@ -390,8 +395,8 @@ static void InverseMoveToFrontTransform(uint8_t* v, int v_len) {
|
||||
}
|
||||
}
|
||||
|
||||
static int HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
|
||||
BrotliState* s) {
|
||||
static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
|
||||
BrotliState* s) {
|
||||
switch (s->sub_state[0]) {
|
||||
case BROTLI_STATE_SUB_NONE:
|
||||
s->next = group->codes;
|
||||
@ -401,37 +406,38 @@ static int HuffmanTreeGroupDecode(HuffmanTreeGroup* group,
|
||||
case BROTLI_STATE_SUB_TREE_GROUP:
|
||||
while (s->htree_index < group->num_htrees) {
|
||||
int table_size;
|
||||
int ok = ReadHuffmanCode(group->alphabet_size, s->next, &table_size, s);
|
||||
if (ok != 1) return ok;
|
||||
BrotliResult result =
|
||||
ReadHuffmanCode(group->alphabet_size, s->next, &table_size, s);
|
||||
if (result != BROTLI_RESULT_SUCCESS) return result;
|
||||
group->htrees[s->htree_index] = s->next;
|
||||
s->next += table_size;
|
||||
if (table_size == 0) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
++s->htree_index;
|
||||
}
|
||||
s->sub_state[0] = BROTLI_STATE_SUB_NONE;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
default:
|
||||
return 0; /* unknown state */
|
||||
return BROTLI_RESULT_ERROR; /* unknown state */
|
||||
}
|
||||
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
|
||||
static int DecodeContextMap(int context_map_size,
|
||||
int* num_htrees,
|
||||
uint8_t** context_map,
|
||||
BrotliState* s) {
|
||||
static BrotliResult DecodeContextMap(int context_map_size,
|
||||
int* num_htrees,
|
||||
uint8_t** context_map,
|
||||
BrotliState* s) {
|
||||
BrotliBitReader* br = &s->br;
|
||||
int ok = 1;
|
||||
BrotliResult result = BROTLI_RESULT_SUCCESS;
|
||||
int use_rle_for_zeros;
|
||||
int max_run_length_prefix = 0;
|
||||
|
||||
switch(s->sub_state[0]) {
|
||||
case BROTLI_STATE_SUB_NONE:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
*num_htrees = DecodeVarLenUint8(br) + 1;
|
||||
|
||||
@ -442,11 +448,11 @@ static int DecodeContextMap(int context_map_size,
|
||||
|
||||
*context_map = (uint8_t*)malloc((size_t)context_map_size);
|
||||
if (*context_map == 0) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
if (*num_htrees <= 1) {
|
||||
memset(*context_map, 0, (size_t)context_map_size);
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
use_rle_for_zeros = (int)BrotliReadBits(br, 1);
|
||||
@ -456,19 +462,19 @@ static int DecodeContextMap(int context_map_size,
|
||||
s->context_map_table = (HuffmanCode*)malloc(
|
||||
BROTLI_HUFFMAN_MAX_TABLE_SIZE * sizeof(*s->context_map_table));
|
||||
if (s->context_map_table == NULL) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
/* No break, continue to next state. */
|
||||
case BROTLI_STATE_SUB_CONTEXT_MAP_HUFFMAN:
|
||||
ok = ReadHuffmanCode(
|
||||
result = ReadHuffmanCode(
|
||||
*num_htrees + max_run_length_prefix, s->context_map_table, NULL, s);
|
||||
if (ok != 1) return ok;
|
||||
if (result != BROTLI_RESULT_SUCCESS) return result;
|
||||
/* No break, continue to next state. */
|
||||
case BROTLI_STATE_SUB_CONTEXT_MAPS:
|
||||
while (s->context_index < context_map_size) {
|
||||
int code;
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
code = ReadSymbol(s->context_map_table, br);
|
||||
if (code == 0) {
|
||||
@ -478,7 +484,7 @@ static int DecodeContextMap(int context_map_size,
|
||||
int reps = 1 + (1 << code) + (int)BrotliReadBits(br, code);
|
||||
while (--reps) {
|
||||
if (s->context_index >= context_map_size) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
(*context_map)[s->context_index] = 0;
|
||||
++s->context_index;
|
||||
@ -495,12 +501,12 @@ static int DecodeContextMap(int context_map_size,
|
||||
free(s->context_map_table);
|
||||
s->context_map_table = NULL;
|
||||
s->sub_state[0] = BROTLI_STATE_SUB_NONE;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
default:
|
||||
return 0; /* unknown state */
|
||||
return BROTLI_RESULT_ERROR; /* unknown state */
|
||||
}
|
||||
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void DecodeBlockType(const int max_block_type,
|
||||
@ -578,9 +584,9 @@ static BROTLI_INLINE void IncrementalCopyFastPath(
|
||||
}
|
||||
}
|
||||
|
||||
int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
int pos,
|
||||
BrotliState* s) {
|
||||
BrotliResult CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
int pos,
|
||||
BrotliState* s) {
|
||||
const int rb_size = s->ringbuffer_mask + 1;
|
||||
uint8_t* ringbuffer_end = s->ringbuffer + rb_size;
|
||||
int rb_pos = pos & s->ringbuffer_mask;
|
||||
@ -599,7 +605,7 @@ int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
break;
|
||||
}
|
||||
if (s->br.bit_end_pos_ < 64) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
/*
|
||||
* Copy remaining 0-4 in 32-bit case or 0-8 bytes in the 64-bit case
|
||||
@ -636,7 +642,7 @@ int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
output. */
|
||||
if (rb_pos >= rb_size) {
|
||||
if (BrotliWrite(output, s->ringbuffer, (size_t)rb_size) < rb_size) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
rb_pos -= rb_size;
|
||||
s->meta_block_remaining_len += rb_size;
|
||||
@ -647,18 +653,18 @@ int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
case BROTLI_STATE_SUB_UNCOMPRESSED_SHORT:
|
||||
while (s->meta_block_remaining_len > 0) {
|
||||
if (!BrotliReadMoreInput(&s->br)) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
s->ringbuffer[rb_pos++] = (uint8_t)BrotliReadBits(&s->br, 8);
|
||||
if (rb_pos == rb_size) {
|
||||
if (BrotliWrite(output, s->ringbuffer, (size_t)rb_size) < rb_size) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
rb_pos = 0;
|
||||
}
|
||||
s->meta_block_remaining_len--;
|
||||
}
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
case BROTLI_STATE_SUB_UNCOMPRESSED_FILL:
|
||||
/* If we have more to copy than the remaining size of the ringbuffer,
|
||||
then we first fill the ringbuffer from the input and then flush the
|
||||
@ -667,10 +673,10 @@ int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
s->nbytes = rb_size - rb_pos;
|
||||
if (BrotliRead(s->br.input_, &s->ringbuffer[rb_pos],
|
||||
(size_t)s->nbytes) < s->nbytes) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
if (BrotliWrite(output, s->ringbuffer, (size_t)rb_size) < s->nbytes) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
s->meta_block_remaining_len -= s->nbytes;
|
||||
rb_pos = 0;
|
||||
@ -684,7 +690,7 @@ int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
(size_t)s->meta_block_remaining_len);
|
||||
s->meta_block_remaining_len -= num_read;
|
||||
if (s->meta_block_remaining_len > 0) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
|
||||
/* Restore the state of the bit reader. */
|
||||
@ -693,21 +699,21 @@ int CopyUncompressedBlockToOutput(BrotliOutput output,
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_SUB_UNCOMPRESSED_WARMUP:
|
||||
if (!BrotliWarmupBitReader(&s->br)) {
|
||||
return 2;
|
||||
return BROTLI_RESULT_PARTIAL;
|
||||
}
|
||||
s->sub_state[0] = BROTLI_STATE_SUB_NONE;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
return 0; /* Unknown state */
|
||||
return BROTLI_RESULT_ERROR; /* Unknown state */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
|
||||
int BrotliDecompressedSize(size_t encoded_size,
|
||||
const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size) {
|
||||
BrotliResult BrotliDecompressedSize(size_t encoded_size,
|
||||
const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size) {
|
||||
int i;
|
||||
uint64_t val = 0;
|
||||
int bit_pos = 0;
|
||||
@ -716,7 +722,7 @@ int BrotliDecompressedSize(size_t encoded_size,
|
||||
int size_nibbles;
|
||||
int meta_block_len = 0;
|
||||
if (encoded_size == 0) {
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
/* Look at the first 8 bytes, it is enough to decode the length of the first
|
||||
meta-block. */
|
||||
@ -732,7 +738,7 @@ int BrotliDecompressedSize(size_t encoded_size,
|
||||
/* Decode the ISEMPTY bit, if it is set to 1, we are done. */
|
||||
if ((val >> bit_pos) & 1) {
|
||||
*decoded_size = 0;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
}
|
||||
++bit_pos;
|
||||
}
|
||||
@ -747,7 +753,7 @@ int BrotliDecompressedSize(size_t encoded_size,
|
||||
if (is_last) {
|
||||
/* If this meta-block is the only one, we are done. */
|
||||
*decoded_size = (size_t)meta_block_len;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
}
|
||||
is_uncompressed = (val >> bit_pos) & 1;
|
||||
++bit_pos;
|
||||
@ -760,46 +766,46 @@ int BrotliDecompressedSize(size_t encoded_size,
|
||||
size_t offset = (size_t)((bit_pos + 7) >> 3) + (size_t)meta_block_len;
|
||||
if (offset < encoded_size && ((encoded_buffer[offset] & 3) == 3)) {
|
||||
*decoded_size = (size_t)meta_block_len;
|
||||
return 1;
|
||||
return BROTLI_RESULT_SUCCESS;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return BROTLI_RESULT_ERROR;
|
||||
}
|
||||
|
||||
int BrotliDecompressBuffer(size_t encoded_size,
|
||||
const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size,
|
||||
uint8_t* decoded_buffer) {
|
||||
BrotliResult BrotliDecompressBuffer(size_t encoded_size,
|
||||
const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size,
|
||||
uint8_t* decoded_buffer) {
|
||||
BrotliMemInput memin;
|
||||
BrotliInput in = BrotliInitMemInput(encoded_buffer, encoded_size, &memin);
|
||||
BrotliMemOutput mout;
|
||||
BrotliOutput out = BrotliInitMemOutput(decoded_buffer, *decoded_size, &mout);
|
||||
int success = BrotliDecompress(in, out);
|
||||
BrotliResult success = BrotliDecompress(in, out);
|
||||
*decoded_size = mout.pos;
|
||||
return success;
|
||||
}
|
||||
|
||||
int BrotliDecompress(BrotliInput input, BrotliOutput output) {
|
||||
BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output) {
|
||||
BrotliState s;
|
||||
int ok;
|
||||
BrotliResult result;
|
||||
BrotliStateInit(&s);
|
||||
ok = BrotliDecompressStreaming(input, output, 1, &s);
|
||||
if (ok == 2) {
|
||||
result = BrotliDecompressStreaming(input, output, 1, &s);
|
||||
if (result == BROTLI_RESULT_PARTIAL) {
|
||||
/* Not ok: it didn't finish even though this is a non-streaming function. */
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
}
|
||||
BrotliStateCleanup(&s);
|
||||
return ok;
|
||||
return result;
|
||||
}
|
||||
|
||||
int BrotliDecompressBufferStreaming(size_t* available_in,
|
||||
const uint8_t** next_in,
|
||||
int finish,
|
||||
size_t* available_out,
|
||||
uint8_t** next_out,
|
||||
size_t* total_out,
|
||||
BrotliState* s) {
|
||||
int result;
|
||||
BrotliResult BrotliDecompressBufferStreaming(size_t* available_in,
|
||||
const uint8_t** next_in,
|
||||
int finish,
|
||||
size_t* available_out,
|
||||
uint8_t** next_out,
|
||||
size_t* total_out,
|
||||
BrotliState* s) {
|
||||
BrotliResult result;
|
||||
BrotliMemInput memin;
|
||||
BrotliInput in = BrotliInitMemInput(*next_in, *available_in, &memin);
|
||||
BrotliMemOutput memout;
|
||||
@ -819,12 +825,12 @@ int BrotliDecompressBufferStreaming(size_t* available_in,
|
||||
return result;
|
||||
}
|
||||
|
||||
int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
int finish, BrotliState* s) {
|
||||
BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
int finish, BrotliState* s) {
|
||||
uint8_t context;
|
||||
int pos = s->pos;
|
||||
int i = s->loop_counter;
|
||||
int ok = 1;
|
||||
BrotliResult result = BROTLI_RESULT_SUCCESS;
|
||||
BrotliBitReader* br = &s->br;
|
||||
int initial_remaining_len;
|
||||
|
||||
@ -838,10 +844,10 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
|
||||
/* State machine */
|
||||
for (;;) {
|
||||
if (ok != 1) {
|
||||
if (ok == 2 && finish) {
|
||||
if (result != BROTLI_RESULT_SUCCESS) {
|
||||
if (result == BROTLI_RESULT_PARTIAL && finish) {
|
||||
printf("Unexpected end of input. State: %d\n", s->state);
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
}
|
||||
break; /* Fail, or partial data. */
|
||||
}
|
||||
@ -868,7 +874,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_BITREADER_WARMUP:
|
||||
if (!BrotliWarmupBitReader(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
/* Decode window size. */
|
||||
@ -881,7 +887,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
kRingBufferWriteAheadSlack +
|
||||
kMaxDictionaryWordLength));
|
||||
if (!s->ringbuffer) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;
|
||||
@ -891,7 +897,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
s->block_len_trees = (HuffmanCode*)malloc(
|
||||
3 * BROTLI_HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode));
|
||||
if (s->block_type_trees == NULL || s->block_len_trees == NULL) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -899,7 +905,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_METABLOCK_BEGIN:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
if (s->input_end) {
|
||||
@ -940,7 +946,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_METABLOCK_HEADER_1:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
BROTLI_LOG_UINT(pos);
|
||||
@ -962,9 +968,9 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
BrotliSetBitPos(br, (s->br.bit_pos_ + 7) & (uint32_t)(~7UL));
|
||||
initial_remaining_len = s->meta_block_remaining_len;
|
||||
/* pos is given as argument since s->pos is only updated at the end. */
|
||||
ok = CopyUncompressedBlockToOutput(output, pos, s);
|
||||
result = CopyUncompressedBlockToOutput(output, pos, s);
|
||||
pos += (initial_remaining_len - s->meta_block_remaining_len);
|
||||
if (ok == 2) break;
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
s->state = BROTLI_STATE_METABLOCK_DONE;
|
||||
break;
|
||||
case BROTLI_STATE_HUFFMAN_CODE_0:
|
||||
@ -984,10 +990,10 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_HUFFMAN_CODE_1:
|
||||
if (s->num_block_types[i] >= 2) {
|
||||
ok = ReadHuffmanCode(s->num_block_types[i] + 2,
|
||||
result = ReadHuffmanCode(s->num_block_types[i] + 2,
|
||||
&s->block_type_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE],
|
||||
NULL, s);
|
||||
if (ok != 1) break;
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
s->state = BROTLI_STATE_HUFFMAN_CODE_2;
|
||||
} else {
|
||||
i++;
|
||||
@ -996,10 +1002,10 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
}
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_HUFFMAN_CODE_2:
|
||||
ok = ReadHuffmanCode(kNumBlockLengthCodes,
|
||||
&s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE],
|
||||
NULL, s);
|
||||
if (ok != 1) break;
|
||||
result = ReadHuffmanCode(kNumBlockLengthCodes,
|
||||
&s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE],
|
||||
NULL, s);
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
s->block_length[i] = ReadBlockLength(
|
||||
&s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br);
|
||||
s->block_type_rb_index[i] = 1;
|
||||
@ -1008,7 +1014,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
break;
|
||||
case BROTLI_STATE_METABLOCK_HEADER_2:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
s->distance_postfix_bits = (int)BrotliReadBits(br, 2);
|
||||
@ -1019,7 +1025,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
(48 << s->distance_postfix_bits));
|
||||
s->context_modes = (uint8_t*)malloc((size_t)s->num_block_types[0]);
|
||||
if (s->context_modes == 0) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < s->num_block_types[0]; ++i) {
|
||||
@ -1031,15 +1037,15 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
s->state = BROTLI_STATE_CONTEXT_MAP_1;
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_CONTEXT_MAP_1:
|
||||
ok = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits,
|
||||
&s->num_literal_htrees, &s->context_map, s);
|
||||
if (ok != 1) break;
|
||||
result = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits,
|
||||
&s->num_literal_htrees, &s->context_map, s);
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
s->state = BROTLI_STATE_CONTEXT_MAP_2;
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_CONTEXT_MAP_2:
|
||||
ok = DecodeContextMap(s->num_block_types[2] << kDistanceContextBits,
|
||||
&s->num_dist_htrees, &s->dist_context_map, s);
|
||||
if (ok != 1) break;
|
||||
result = DecodeContextMap(s->num_block_types[2] << kDistanceContextBits,
|
||||
&s->num_dist_htrees, &s->dist_context_map, s);
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
|
||||
BrotliHuffmanTreeGroupInit(&s->hgroup[0], kNumLiteralCodes,
|
||||
s->num_literal_htrees);
|
||||
@ -1051,8 +1057,8 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
s->state = BROTLI_STATE_TREE_GROUP;
|
||||
/* No break, continue to next state */
|
||||
case BROTLI_STATE_TREE_GROUP:
|
||||
ok = HuffmanTreeGroupDecode(&s->hgroup[i], s);
|
||||
if (ok != 1) break;
|
||||
result = HuffmanTreeGroupDecode(&s->hgroup[i], s);
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
i++;
|
||||
|
||||
if (i >= 3) {
|
||||
@ -1073,7 +1079,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* Block decoding is the inner loop, jumping with goto makes it 3% faster */
|
||||
BlockBegin:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
if (s->meta_block_remaining_len <= 0) {
|
||||
@ -1121,7 +1127,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
case BROTLI_STATE_BLOCK_INNER:
|
||||
while (i < s->insert_length) {
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
if (s->block_length[0] == 0) {
|
||||
@ -1151,14 +1157,14 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) {
|
||||
if (BrotliWrite(output, s->ringbuffer,
|
||||
(size_t)s->ringbuffer_size) < 0) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
++i;
|
||||
}
|
||||
if (ok != 1) break;
|
||||
if (result != BROTLI_RESULT_SUCCESS) break;
|
||||
|
||||
s->meta_block_remaining_len -= s->insert_length;
|
||||
if (s->meta_block_remaining_len <= 0) {
|
||||
@ -1173,7 +1179,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* No break, go to next state */
|
||||
case BROTLI_STATE_BLOCK_DISTANCE:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
assert(s->distance_code < 0);
|
||||
@ -1211,7 +1217,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
/* No break, go to next state */
|
||||
case BROTLI_STATE_BLOCK_POST:
|
||||
if (!BrotliReadMoreInput(br)) {
|
||||
ok = 2;
|
||||
result = BROTLI_RESULT_PARTIAL;
|
||||
break;
|
||||
}
|
||||
/* Convert the distance code to the actual distance by possibly */
|
||||
@ -1219,7 +1225,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
s->distance =
|
||||
TranslateShortCodes(s->distance_code, s->dist_rb, s->dist_rb_idx);
|
||||
if (s->distance < 0) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
BROTLI_LOG_UINT(s->distance);
|
||||
@ -1253,7 +1259,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
if (s->copy_dst >= s->ringbuffer_end) {
|
||||
if (BrotliWrite(output, s->ringbuffer,
|
||||
(size_t)s->ringbuffer_size) < 0) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
memcpy(s->ringbuffer, s->ringbuffer_end,
|
||||
@ -1264,14 +1270,14 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
"len: %d bytes left: %d\n",
|
||||
pos, s->distance, s->copy_length,
|
||||
s->meta_block_remaining_len);
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf("Invalid backward reference. pos: %d distance: %d "
|
||||
"len: %d bytes left: %d\n", pos, s->distance, s->copy_length,
|
||||
s->meta_block_remaining_len);
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -1284,7 +1290,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
printf("Invalid backward reference. pos: %d distance: %d "
|
||||
"len: %d bytes left: %d\n", pos, s->distance, s->copy_length,
|
||||
s->meta_block_remaining_len);
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1312,7 +1318,7 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) {
|
||||
if (BrotliWrite(output, s->ringbuffer,
|
||||
(size_t)s->ringbuffer_size) < 0) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1352,19 +1358,19 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
if (s->ringbuffer != 0) {
|
||||
if (BrotliWrite(output, s->ringbuffer,
|
||||
(size_t)(pos & s->ringbuffer_mask)) < 0) {
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
return result;
|
||||
default:
|
||||
printf("Unknown state %d\n", s->state);
|
||||
ok = 0;
|
||||
result = BROTLI_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
s->pos = pos;
|
||||
s->loop_counter = i;
|
||||
return ok;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
37
dec/decode.h
37
dec/decode.h
@ -26,25 +26,37 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* Decoding error, e.g. corrupt input or no memory */
|
||||
BROTLI_RESULT_ERROR = 0,
|
||||
/* Successfully completely done */
|
||||
BROTLI_RESULT_SUCCESS = 1,
|
||||
/* Partially done, but must be called again with more input */
|
||||
BROTLI_RESULT_PARTIAL = 2
|
||||
} BrotliResult;
|
||||
|
||||
/* Sets *decoded_size to the decompressed size of the given encoded stream. */
|
||||
/* This function only works if the encoded buffer has a single meta block, */
|
||||
/* or if it has two meta-blocks, where the first is uncompressed and the */
|
||||
/* second is empty. */
|
||||
/* Returns 1 on success, 0 on failure. */
|
||||
int BrotliDecompressedSize(size_t encoded_size, const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size);
|
||||
BrotliResult BrotliDecompressedSize(size_t encoded_size,
|
||||
const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size);
|
||||
|
||||
/* Decompresses the data in encoded_buffer into decoded_buffer, and sets */
|
||||
/* *decoded_size to the decompressed length. */
|
||||
/* Returns 0 if there was either a bit stream error or memory allocation */
|
||||
/* error, and 1 otherwise. */
|
||||
/* If decoded size is zero, returns 1 and keeps decoded_buffer unchanged. */
|
||||
int BrotliDecompressBuffer(size_t encoded_size, const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size, uint8_t* decoded_buffer);
|
||||
BrotliResult BrotliDecompressBuffer(size_t encoded_size,
|
||||
const uint8_t* encoded_buffer,
|
||||
size_t* decoded_size,
|
||||
uint8_t* decoded_buffer);
|
||||
|
||||
/* Same as above, but uses the specified input and output callbacks instead */
|
||||
/* of reading from and writing to pre-allocated memory buffers. */
|
||||
int BrotliDecompress(BrotliInput input, BrotliOutput output);
|
||||
BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output);
|
||||
|
||||
/* Same as above, but supports the caller to call the decoder repeatedly with
|
||||
partial data to support streaming. The state must be initialized with
|
||||
@ -71,8 +83,8 @@ int BrotliDecompress(BrotliInput input, BrotliOutput output);
|
||||
it returning a smaller value than the amount of bytes to write always results
|
||||
in an error.
|
||||
*/
|
||||
int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
int finish, BrotliState* s);
|
||||
BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
int finish, BrotliState* s);
|
||||
|
||||
/* Same as above, but with memory buffers.
|
||||
Must be called with an allocated input buffer in *next_in and an allocated
|
||||
@ -101,10 +113,13 @@ int BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
|
||||
*available_out yourself before a next call, e.g. to point to a new larger
|
||||
buffer.
|
||||
*/
|
||||
int BrotliDecompressBufferStreaming(size_t* available_in,
|
||||
const uint8_t** next_in, int finish,
|
||||
size_t* available_out, uint8_t** next_out,
|
||||
size_t* total_out, BrotliState* s);
|
||||
BrotliResult BrotliDecompressBufferStreaming(size_t* available_in,
|
||||
const uint8_t** next_in,
|
||||
int finish,
|
||||
size_t* available_out,
|
||||
uint8_t** next_out,
|
||||
size_t* total_out,
|
||||
BrotliState* s);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
|
Loading…
Reference in New Issue
Block a user