Update decoder:

* use BROTLI_MAX_DISTANCE_BITS instead of magic constant
 * introduce BROTLI_DEPRECATED
 * move BROTLI_RESTRICT to common/port.h
 * promote reg_t to dec/port.h
 * remove deprecated decoder API
 * more optimistic ring-buffer allocation
 * fix MSVC warnings
 * fix (not tested) for ARM 64-bit RBIT
This commit is contained in:
Eugene Kliuchnikov 2016-09-21 15:05:12 +02:00
parent 20e36ef2f7
commit f20b3eeb2f
9 changed files with 157 additions and 226 deletions

View File

@ -32,10 +32,12 @@
#define BROTLI_NUM_DISTANCE_SHORT_CODES 16
#define BROTLI_MAX_NPOSTFIX 3
#define BROTLI_MAX_NDIRECT 120
#define BROTLI_MAX_DISTANCE_BITS 24U
/* BROTLI_NUM_DISTANCE_SYMBOLS == 520 */
#define BROTLI_NUM_DISTANCE_SYMBOLS (BROTLI_NUM_DISTANCE_SHORT_CODES + \
BROTLI_MAX_NDIRECT + \
(24 << (BROTLI_MAX_NPOSTFIX + 1)))
(BROTLI_MAX_DISTANCE_BITS << \
(BROTLI_MAX_NPOSTFIX + 1)))
/* 7.1. Context modes and context ID lookup for literals */
/* "context IDs for literals are in the range of 0..63" */

View File

@ -96,12 +96,28 @@ OR:
#define BROTLI_INLINE __forceinline
#endif /* _MSC_VER */
#if !defined(__cplusplus) && !defined(c_plusplus) && \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#define BROTLI_RESTRICT restrict
#elif BROTLI_GCC_VERSION > 295 || defined(__llvm__)
#define BROTLI_RESTRICT __restrict
#else
#define BROTLI_RESTRICT
#endif
#if BROTLI_MODERN_COMPILER || __has_attribute(noinline)
#define BROTLI_NOINLINE __attribute__((noinline))
#else
#define BROTLI_NOINLINE
#endif
#if BROTLI_MODERN_COMPILER || __has_attribute(deprecated)
#define BROTLI_DEPRECATED __attribute__((deprecated))
#else
#define BROTLI_DEPRECATED
#endif
#define BROTLI_UNUSED(X) (void)(X)
#endif /* BROTLI_COMMON_PORT_H_ */

View File

@ -18,13 +18,7 @@
extern "C" {
#endif
#if (BROTLI_64_BITS)
#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 4
typedef uint64_t reg_t;
#else
#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 2
typedef uint32_t reg_t;
#endif
#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(reg_t) >> 1)
static const uint32_t kBitMask[33] = { 0x0000,
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
@ -343,23 +337,6 @@ static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
return TO_BROTLI_BOOL(pad_bits == 0);
}
/* Peeks a byte at specified offset.
Precondition: bit reader is parked to a byte boundary.
Returns -1 if operation is not feasible. */
static BROTLI_INLINE int BrotliPeekByte(BrotliBitReader* br, size_t offset) {
uint32_t available_bits = BrotliGetAvailableBits(br);
size_t bytes_left = available_bits >> 3;
BROTLI_DCHECK((available_bits & 7) == 0);
if (offset < bytes_left) {
return (BrotliGetBitsUnmasked(br) >> (unsigned)(offset << 3)) & 0xFF;
}
offset -= bytes_left;
if (offset < br->avail_in) {
return br->next_in[offset];
}
return -1;
}
/* Copies remaining input bytes stored in the bit reader to the output. Value
num may not be larger than BrotliGetRemainingBytes. The bit reader must be
warmed up again after this. */

View File

@ -220,7 +220,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
case BROTLI_STATE_METABLOCK_HEADER_SIZE:
i = s->loop_counter;
for (; i < s->size_nibbles; ++i) {
for (; i < (int)s->size_nibbles; ++i) {
if (!BrotliSafeReadBits(br, 4, &bits)) {
s->loop_counter = i;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
@ -269,7 +269,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
case BROTLI_STATE_METABLOCK_HEADER_METADATA:
i = s->loop_counter;
for (; i < s->size_nibbles; ++i) {
for (; i < (int)s->size_nibbles; ++i) {
if (!BrotliSafeReadBits(br, 8, &bits)) {
s->loop_counter = i;
return BROTLI_DECODER_NEEDS_MORE_INPUT;
@ -1173,9 +1173,13 @@ static size_t UnwrittenBytes(const BrotliDecoderState* s, BROTLI_BOOL wrap) {
return partial_pos_rb - s->partial_pos_out;
}
/* Dumps output.
Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push
and either ringbuffer is as big as window size, or |force| is true.
*/
static BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(
BrotliDecoderState* s, size_t* available_out, uint8_t** next_out,
size_t* total_out) {
size_t* total_out, BROTLI_BOOL force) {
uint8_t* start =
s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask);
size_t to_write = UnwrittenBytes(s, BROTLI_TRUE);
@ -1198,11 +1202,17 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(
BROTLI_LOG_UINT(to_write);
BROTLI_LOG_UINT(num_written);
s->partial_pos_out += num_written;
if (total_out) *total_out = s->partial_pos_out;
if (total_out) *total_out = s->partial_pos_out - (size_t)s->custom_dict_size;
if (num_written < to_write) {
if (s->ringbuffer_size == (1 << s->window_bits) || force) {
return BROTLI_DECODER_NEEDS_MORE_OUTPUT;
} else {
return BROTLI_DECODER_SUCCESS;
}
if (s->pos >= s->ringbuffer_size) {
}
/* Wrap ring buffer only if it has reached its maximal size. */
if (s->ringbuffer_size == (1 << s->window_bits) &&
s->pos >= s->ringbuffer_size) {
s->pos -= s->ringbuffer_size;
s->rb_roundtrips++;
s->should_wrap_ringbuffer = (size_t)s->pos != 0 ? 1 : 0;
@ -1227,27 +1237,41 @@ static void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState* s) {
Custom dictionary, if any, is copied to the end of ringbuffer.
*/
static BROTLI_BOOL BROTLI_NOINLINE BrotliAllocateRingBuffer(
static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
BrotliDecoderState* s) {
/* 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) */
static const int kRingBufferWriteAheadSlack = 42;
s->ringbuffer = (uint8_t*)BROTLI_ALLOC(s, (size_t)(s->ringbuffer_size +
uint8_t* old_ringbuffer = s->ringbuffer;
if (s->ringbuffer_size == s->new_ringbuffer_size) {
return BROTLI_TRUE;
}
s->ringbuffer = (uint8_t*)BROTLI_ALLOC(s, (size_t)(s->new_ringbuffer_size +
kRingBufferWriteAheadSlack));
if (s->ringbuffer == 0) {
/* Restore previous value. */
s->ringbuffer = old_ringbuffer;
return BROTLI_FALSE;
}
s->ringbuffer[s->new_ringbuffer_size - 2] = 0;
s->ringbuffer[s->new_ringbuffer_size - 1] = 0;
s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;
s->ringbuffer[s->ringbuffer_size - 2] = 0;
s->ringbuffer[s->ringbuffer_size - 1] = 0;
if (!old_ringbuffer) {
if (s->custom_dict) {
memcpy(&s->ringbuffer[(-s->custom_dict_size) & s->ringbuffer_mask],
s->custom_dict, (size_t)s->custom_dict_size);
memcpy(s->ringbuffer, s->custom_dict, (size_t)s->custom_dict_size);
s->partial_pos_out = (size_t)s->custom_dict_size;
s->pos = s->custom_dict_size;
}
} else {
memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos);
BROTLI_FREE(s, old_ringbuffer);
}
s->ringbuffer_size = s->new_ringbuffer_size;
s->ringbuffer_mask = s->new_ringbuffer_size - 1;
s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;
return BROTLI_TRUE;
}
@ -1256,7 +1280,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
size_t* available_out, uint8_t** next_out, size_t* total_out,
BrotliDecoderState* s) {
/* TODO: avoid allocation for single uncompressed block. */
if (!s->ringbuffer && !BrotliAllocateRingBuffer(s)) {
if (!BrotliEnsureRingBuffer(s)) {
return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1);
}
@ -1275,7 +1299,7 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes);
s->pos += nbytes;
s->meta_block_remaining_len -= nbytes;
if (s->pos < s->ringbuffer_size) {
if (s->pos < 1 << s->window_bits) {
if (s->meta_block_remaining_len == 0) {
return BROTLI_DECODER_SUCCESS;
}
@ -1285,12 +1309,15 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
/* No break, continue to next state */
}
case BROTLI_STATE_UNCOMPRESSED_WRITE: {
BrotliDecoderErrorCode result =
WriteRingBuffer(s, available_out, next_out, total_out);
BrotliDecoderErrorCode result;
result = WriteRingBuffer(
s, available_out, next_out, total_out, BROTLI_FALSE);
if (result != BROTLI_DECODER_SUCCESS) {
return result;
}
if (s->ringbuffer_size == 1 << s->window_bits) {
s->max_distance = s->max_backward_distance;
}
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
break;
}
@ -1299,43 +1326,6 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
BROTLI_DCHECK(0); /* Unreachable */
}
BROTLI_BOOL BrotliDecompressedSize(size_t encoded_size,
const uint8_t* encoded_buffer,
size_t* decoded_size) {
size_t total_size = 0;
BrotliDecoderState s;
BrotliBitReader* br;
BrotliDecoderStateInit(&s);
br = &s.br;
*decoded_size = 0;
br->next_in = encoded_buffer;
br->avail_in = encoded_size;
if (!BrotliWarmupBitReader(br)) return BROTLI_FALSE;
DecodeWindowBits(br);
while (1) {
size_t block_size;
if (DecodeMetaBlockLength(&s, br) != BROTLI_DECODER_SUCCESS) {
return BROTLI_FALSE;
}
block_size = (size_t)s.meta_block_remaining_len;
if (!s.is_metadata) {
if ((block_size + total_size) < total_size) return BROTLI_FALSE;
total_size += block_size;
}
if (s.is_last_metablock) {
*decoded_size = total_size;
return BROTLI_TRUE;
}
if (!s.is_uncompressed && !s.is_metadata) return BROTLI_FALSE;
if (!BrotliJumpToByteBoundary(br)) return BROTLI_FALSE;
BrotliBitReaderUnload(br);
if (br->avail_in < block_size) return BROTLI_FALSE;
br->avail_in -= block_size;
br->next_in += block_size;
if (!BrotliWarmupBitReader(br)) return BROTLI_FALSE;
}
}
/* Calculates the smallest feasible ring buffer.
If we know the data size is small, do not allocate more ring buffer
@ -1344,31 +1334,38 @@ BROTLI_BOOL BrotliDecompressedSize(size_t encoded_size,
When this method is called, metablock size and flags MUST be decoded.
*/
static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(
BrotliDecoderState* s, BrotliBitReader* br) {
BROTLI_BOOL is_last = TO_BROTLI_BOOL(s->is_last_metablock);
BrotliDecoderState* s) {
int window_size = 1 << s->window_bits;
s->ringbuffer_size = window_size;
if (s->is_uncompressed) {
int next_block_header =
BrotliPeekByte(br, (size_t)s->meta_block_remaining_len);
if (next_block_header != -1) { /* Peek succeeded */
if ((next_block_header & 3) == 3) { /* ISLAST and ISEMPTY */
is_last = BROTLI_TRUE;
}
}
}
int new_ringbuffer_size = window_size;
/* We need at least 2 bytes of ring buffer size to get the last two
bytes for context from there */
if (is_last) {
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;
}
int min_size = s->ringbuffer_size ? s->ringbuffer_size : 1024;
int output_size;
/* If maxumum is already reached, no further extention is reuired. */
if (s->ringbuffer_size == window_size) {
return;
}
s->ringbuffer_mask = s->ringbuffer_size - 1;
/* Metadata blocks does not touch ring buffer. */
if (s->is_metadata) {
return;
}
if (!s->ringbuffer) {
/* Custom dictionanry counts as a "virtual" output. */
output_size = s->custom_dict_size;
} else {
output_size = s->pos;
}
output_size += s->meta_block_remaining_len;
min_size = min_size < output_size ? output_size : min_size;
while ((new_ringbuffer_size >> 1) >= min_size) {
new_ringbuffer_size >>= 1;
}
s->new_ringbuffer_size = new_ringbuffer_size;
}
/* Reads 1..256 2-bit context modes. */
@ -1719,11 +1716,8 @@ postReadDistance:
BROTLI_LOG(("[ProcessCommandsInternal] pos = %d distance = %d\n",
pos, s->distance_code));
if (s->max_distance != s->max_backward_distance) {
if (pos < s->max_backward_distance_minus_custom_dict_size) {
s->max_distance = pos + s->custom_dict_size;
} else {
s->max_distance = s->max_backward_distance;
}
s->max_distance =
(pos < s->max_backward_distance) ? pos : s->max_backward_distance;
}
i = s->copy_length;
/* Apply copy of LZ77 back-reference, or static dictionary reference if
@ -1905,7 +1899,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
if (result != BROTLI_DECODER_SUCCESS) { /* Error, needs more input/output */
if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
if (s->ringbuffer != 0) { /* Proactively push output. */
WriteRingBuffer(s, available_out, next_out, total_out);
WriteRingBuffer(s, available_out, next_out, total_out, BROTLI_TRUE);
}
if (s->buffer_length != 0) { /* Used with internal buffer. */
if (br->avail_in == 0) { /* Successfully finished read transaction. */
@ -1984,8 +1978,6 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
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;
/* Allocate memory for both block_type_trees and block_len_trees. */
s->block_type_trees = (HuffmanCode*)BROTLI_ALLOC(s,
@ -2028,9 +2020,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
s->state = BROTLI_STATE_METABLOCK_DONE;
break;
}
if (!s->ringbuffer) {
BrotliCalculateRingBufferSize(s, br);
}
BrotliCalculateRingBufferSize(s);
if (s->is_uncompressed) {
s->state = BROTLI_STATE_UNCOMPRESSED;
break;
@ -2039,8 +2029,10 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
s->state = BROTLI_STATE_HUFFMAN_CODE_0;
break;
case BROTLI_STATE_UNCOMPRESSED: {
int bytes_copied = s->meta_block_remaining_len;
result = CopyUncompressedBlockToOutput(
available_out, next_out, total_out, s);
bytes_copied -= s->meta_block_remaining_len;
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
@ -2148,8 +2140,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
/* No break, continue to next state */
case BROTLI_STATE_CONTEXT_MAP_2:
{
uint32_t num_distance_codes =
s->num_direct_distance_codes + (48U << s->distance_postfix_bits);
uint32_t num_distance_codes = s->num_direct_distance_codes +
((2 * BROTLI_MAX_DISTANCE_BITS) << s->distance_postfix_bits);
result = DecodeContextMap(
s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,
&s->num_dist_htrees, &s->dist_context_map, s);
@ -2200,7 +2192,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
PrepareLiteralDecoding(s);
s->dist_context_map_slice = s->dist_context_map;
s->htree_command = s->insert_copy_hgroup.htrees[0];
if (!s->ringbuffer && !BrotliAllocateRingBuffer(s)) {
if (!BrotliEnsureRingBuffer(s)) {
result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
break;
}
@ -2219,12 +2211,15 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
case BROTLI_STATE_COMMAND_INNER_WRITE:
case BROTLI_STATE_COMMAND_POST_WRITE_1:
case BROTLI_STATE_COMMAND_POST_WRITE_2:
result = WriteRingBuffer(s, available_out, next_out, total_out);
result = WriteRingBuffer(
s, available_out, next_out, total_out, BROTLI_FALSE);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
WrapRingBuffer(s);
if (s->ringbuffer_size == 1 << s->window_bits) {
s->max_distance = s->max_backward_distance;
}
if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {
if (s->meta_block_remaining_len == 0) {
/* Next metablock, if any */
@ -2270,7 +2265,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
/* No break, continue to next state */
case BROTLI_STATE_DONE:
if (s->ringbuffer != 0) {
result = WriteRingBuffer(s, available_out, next_out, total_out);
result = WriteRingBuffer(
s, available_out, next_out, total_out, BROTLI_TRUE);
if (result != BROTLI_DECODER_SUCCESS) {
break;
}
@ -2305,7 +2301,7 @@ const uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {
return 0;
}
WrapRingBuffer(s);
status = WriteRingBuffer(s, &available_out, &result, 0);
status = WriteRingBuffer(s, &available_out, &result, 0, BROTLI_TRUE);
if (status == BROTLI_DECODER_SUCCESS ||
status == BROTLI_DECODER_NEEDS_MORE_OUTPUT) {
*size = requested_out - available_out;
@ -2347,45 +2343,6 @@ uint32_t BrotliDecoderVersion() {
return BROTLI_VERSION;
}
/* DEPRECATED >>> */
BrotliState* BrotliCreateState(
brotli_alloc_func alloc, brotli_free_func free, void* opaque) {
return (BrotliState*)BrotliDecoderCreateInstance(alloc, free, opaque);
}
void BrotliDestroyState(BrotliState* state) {
BrotliDecoderDestroyInstance((BrotliDecoderState*)state);
}
BrotliResult BrotliDecompressBuffer(
size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
uint8_t* decoded_buffer) {
return (BrotliResult)BrotliDecoderDecompress(
encoded_size, encoded_buffer, decoded_size, decoded_buffer);
}
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) {
return (BrotliResult)BrotliDecoderDecompressStream((BrotliDecoderState*)s,
available_in, next_in, available_out, next_out, total_out);
}
void BrotliSetCustomDictionary(
size_t size, const uint8_t* dict, BrotliState* s) {
BrotliDecoderSetCustomDictionary((BrotliDecoderState*)s, size, dict);
}
BROTLI_BOOL BrotliStateIsStreamStart(const BrotliState* s) {
return !BrotliDecoderIsUsed((const BrotliDecoderState*)s);
}
BROTLI_BOOL BrotliStateIsStreamEnd(const BrotliState* s) {
return BrotliDecoderIsFinished((const BrotliDecoderState*)s);
}
BrotliErrorCode BrotliGetErrorCode(const BrotliState* s) {
return (BrotliErrorCode)BrotliDecoderGetErrorCode(
(const BrotliDecoderState*)s);
}
const char* BrotliErrorString(BrotliErrorCode c) {
return BrotliDecoderErrorString((BrotliDecoderErrorCode)c);
}
/* <<< DEPRECATED */
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif

View File

@ -21,7 +21,8 @@ extern "C" {
#define BROTLI_REVERSE_BITS_MAX 8
#ifdef BROTLI_RBIT
#define BROTLI_REVERSE_BITS_BASE (32 - BROTLI_REVERSE_BITS_MAX)
#define BROTLI_REVERSE_BITS_BASE \
((sizeof(reg_t) << 3) - BROTLI_REVERSE_BITS_MAX)
#else
#define BROTLI_REVERSE_BITS_BASE 0
static uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {
@ -61,12 +62,12 @@ static uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {
#endif /* BROTLI_RBIT */
#define BROTLI_REVERSE_BITS_LOWEST \
(1U << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE))
((reg_t)1 << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE))
/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX),
where reverse(value, len) is the bit-wise reversal of the len least
significant bits of value. */
static BROTLI_INLINE uint32_t BrotliReverseBits(uint32_t num) {
static BROTLI_INLINE reg_t BrotliReverseBits(reg_t num) {
#ifdef BROTLI_RBIT
return BROTLI_RBIT(num);
#else
@ -105,8 +106,8 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
uint16_t* count) {
HuffmanCode code; /* current table entry */
int symbol; /* symbol index in original or sorted table */
uint32_t key; /* prefix code */
uint32_t key_step; /* prefix code addend */
reg_t key; /* prefix code */
reg_t key_step; /* prefix code addend */
int step; /* step size to replicate values in current table */
int table_size; /* size of current table */
int sorted[BROTLI_CODE_LENGTH_CODES]; /* symbols sorted by code length */
@ -143,7 +144,7 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
if (offset[0] == 0) {
code.bits = 0;
code.value = (uint16_t)sorted[0];
for (key = 0; key < (uint32_t)table_size; ++key) {
for (key = 0; key < (reg_t)table_size; ++key) {
table[key] = code;
}
return;
@ -175,10 +176,10 @@ uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
HuffmanCode* table; /* next available space in table */
int len; /* current code length */
int symbol; /* symbol index in original or sorted table */
uint32_t key; /* prefix code */
uint32_t key_step; /* prefix code addend */
uint32_t sub_key; /* 2nd level table prefix code */
uint32_t sub_key_step; /* 2nd level table prefix code addend */
reg_t key; /* prefix code */
reg_t key_step; /* prefix code addend */
reg_t sub_key; /* 2nd level table prefix code */
reg_t sub_key_step; /* 2nd level table prefix code addend */
int step; /* step size to replicate values in current table */
int table_bits; /* key length of current table */
int table_size; /* size of current table */

View File

@ -16,6 +16,7 @@
features and attributes
* BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
read and overlapping memcpy; this reduces decompression speed by 5%
* BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
* BROTLI_DEBUG dumps file name and line number when decoder detects stream
or memory error
* BROTLI_ENABLE_LOG enables asserts and dumps various state information
@ -101,6 +102,12 @@ static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
#define BROTLI_64_BITS 0
#endif
#if (BROTLI_64_BITS)
#define reg_t uint64_t
#else
#define reg_t uint32_t
#endif
#if defined(BROTLI_BUILD_BIG_ENDIAN)
#define BROTLI_LITTLE_ENDIAN 0
#define BROTLI_BIG_ENDIAN 1
@ -132,10 +139,12 @@ static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
if ((N & 4) != 0) {X; X; X; X;} \
}
#if BROTLI_MODERN_COMPILER || defined(__llvm__)
#if (BROTLI_MODERN_COMPILER || defined(__llvm__)) && \
!defined(BROTLI_BUILD_NO_RBIT)
#if defined(BROTLI_TARGET_ARMV7)
static BROTLI_INLINE unsigned BrotliRBit(unsigned input) {
unsigned output;
/* TODO: detect ARMv6T2 and enable this code for it. */
static BROTLI_INLINE reg_t BrotliRBit(reg_t input) {
reg_t output;
__asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
return output;
}

View File

@ -60,6 +60,9 @@ void BrotliDecoderStateInitWithCustomAllocators(BrotliDecoderState* s,
s->block_type_trees = NULL;
s->block_len_trees = NULL;
s->ringbuffer = NULL;
s->ringbuffer_size = 0;
s->new_ringbuffer_size = 0;
s->ringbuffer_mask = 0;
s->context_map = NULL;
s->context_modes = NULL;

View File

@ -115,7 +115,6 @@ struct BrotliDecoderStateStruct {
int pos;
int max_backward_distance;
int max_backward_distance_minus_custom_dict_size;
int max_distance;
int ringbuffer_size;
int ringbuffer_mask;
@ -162,7 +161,7 @@ struct BrotliDecoderStateStruct {
/* For partial write operations */
size_t rb_roundtrips; /* How many times we went around the ringbuffer */
size_t partial_pos_out; /* How much output to the user in total (<= rb) */
size_t partial_pos_out; /* How much output to the user in total */
/* For ReadHuffmanCode */
uint32_t symbol;
@ -216,6 +215,8 @@ struct BrotliDecoderStateStruct {
unsigned int size_nibbles : 8;
uint32_t window_bits;
int new_ringbuffer_size;
uint32_t num_literal_htrees;
uint8_t* context_map;
uint8_t* context_modes;

View File

@ -126,8 +126,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
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 BrotliCreateInstance
2) Use BrotliSetCustomDictionary
3) Use BrotliDecompressStream
2) Use BrotliDecoderSetCustomDictionary
3) Use BrotliDecoderDecompressStream
4) Clean up and free state with BrotliDestroyState
*/
void BrotliDecoderSetCustomDictionary(
@ -161,7 +161,7 @@ BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s);
and produced all of the output; returns false otherwise. */
BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s);
/* Returns detailed error code after BrotliDecompressStream returns
/* Returns detailed error code after BrotliDecoderDecompressStream returns
BROTLI_DECODER_RESULT_ERROR. */
BrotliDecoderErrorCode BrotliDecoderGetErrorCode(const BrotliDecoderState* s);
@ -170,41 +170,6 @@ const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);
/* Decoder version. Look at BROTLI_VERSION for more information. */
uint32_t BrotliDecoderVersion(void);
/* DEPRECATED >>> */
typedef enum {
BROTLI_RESULT_ERROR = 0,
BROTLI_RESULT_SUCCESS = 1,
BROTLI_RESULT_NEEDS_MORE_INPUT = 2,
BROTLI_RESULT_NEEDS_MORE_OUTPUT = 3
} BrotliResult;
typedef enum {
#define BROTLI_COMMA_ ,
#define BROTLI_ERROR_CODE_ENUM_ITEM_(PREFIX, NAME, CODE) \
BROTLI ## PREFIX ## NAME = CODE
BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_ENUM_ITEM_, BROTLI_COMMA_)
#undef BROTLI_ERROR_CODE_ENUM_ITEM_
#undef BROTLI_COMMA_
} BrotliErrorCode;
typedef struct BrotliStateStruct BrotliState;
BrotliState* BrotliCreateState(
brotli_alloc_func alloc, brotli_free_func free, void* opaque);
void BrotliDestroyState(BrotliState* state);
BROTLI_BOOL BrotliDecompressedSize(
size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size);
BrotliResult BrotliDecompressBuffer(
size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
uint8_t* decoded_buffer);
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);
void BrotliSetCustomDictionary(
size_t size, const uint8_t* dict, BrotliState* s);
BROTLI_BOOL BrotliStateIsStreamStart(const BrotliState* s);
BROTLI_BOOL BrotliStateIsStreamEnd(const BrotliState* s);
BrotliErrorCode BrotliGetErrorCode(const BrotliState* s);
const char* BrotliErrorString(BrotliErrorCode c);
/* <<< DEPRECATED */
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif