Index: third_party/brotli/dec/decode.c |
diff --git a/third_party/brotli/dec/decode.c b/third_party/brotli/dec/decode.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ca114c61c19050b2b200f3db5f67ee1f454e37c9 |
--- /dev/null |
+++ b/third_party/brotli/dec/decode.c |
@@ -0,0 +1,1156 @@ |
+/* Copyright 2013 Google Inc. All Rights Reserved. |
+ |
+ Licensed under the Apache License, Version 2.0 (the "License"); |
+ you may not use this file except in compliance with the License. |
+ You may obtain a copy of the License at |
+ |
+ http://www.apache.org/licenses/LICENSE-2.0 |
+ |
+ Unless required by applicable law or agreed to in writing, software |
+ distributed under the License is distributed on an "AS IS" BASIS, |
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+ See the License for the specific language governing permissions and |
+ limitations under the License. |
+*/ |
+ |
+#include <stdlib.h> |
+#include <stdio.h> |
+#include <string.h> |
+#include "./bit_reader.h" |
+#include "./context.h" |
+#include "./decode.h" |
+#include "./dictionary.h" |
+#include "./transform.h" |
+#include "./huffman.h" |
+#include "./prefix.h" |
+#include "./safe_malloc.h" |
+ |
+#if defined(__cplusplus) || defined(c_plusplus) |
+extern "C" { |
+#endif |
+ |
+#ifdef BROTLI_DECODE_DEBUG |
+#define BROTLI_LOG_UINT(name) \ |
+ printf("[%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]) |
+#else |
+#define BROTLI_LOG_UINT(name) |
+#define BROTLI_LOG_ARRAY_INDEX(array_name, idx) |
+#endif |
+ |
+static const uint8_t kDefaultCodeLength = 8; |
+static const uint8_t kCodeLengthRepeatCode = 16; |
+static const int kNumLiteralCodes = 256; |
+static const int kNumInsertAndCopyCodes = 704; |
+static const int kNumBlockLengthCodes = 26; |
+static const int kLiteralContextBits = 6; |
+static const int kDistanceContextBits = 2; |
+ |
+#define HUFFMAN_TABLE_BITS 8 |
+#define HUFFMAN_TABLE_MASK 0xff |
+/* Maximum possible Huffman table size for an alphabet size of 704, max code |
+ * length 15 and root table bits 8. */ |
+#define HUFFMAN_MAX_TABLE_SIZE 1080 |
+ |
+#define CODE_LENGTH_CODES 18 |
+static const uint8_t kCodeLengthCodeOrder[CODE_LENGTH_CODES] = { |
+ 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
+}; |
+ |
+#define NUM_DISTANCE_SHORT_CODES 16 |
+static const int kDistanceShortCodeIndexOffset[NUM_DISTANCE_SHORT_CODES] = { |
+ 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 |
+}; |
+ |
+static const int kDistanceShortCodeValueOffset[NUM_DISTANCE_SHORT_CODES] = { |
+ 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3 |
+}; |
+ |
+static BROTLI_INLINE int DecodeWindowBits(BrotliBitReader* br) { |
+ if (BrotliReadBits(br, 1)) { |
+ return 17 + (int)BrotliReadBits(br, 3); |
+ } else { |
+ return 16; |
+ } |
+} |
+ |
+/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */ |
+static BROTLI_INLINE int DecodeVarLenUint8(BrotliBitReader* br) { |
+ if (BrotliReadBits(br, 1)) { |
+ int nbits = (int)BrotliReadBits(br, 3); |
+ if (nbits == 0) { |
+ return 1; |
+ } else { |
+ return (int)BrotliReadBits(br, nbits) + (1 << nbits); |
+ } |
+ } |
+ return 0; |
+} |
+ |
+static void DecodeMetaBlockLength(BrotliBitReader* br, |
+ int* meta_block_length, |
+ int* input_end, |
+ int* is_uncompressed) { |
+ int size_nibbles; |
+ int i; |
+ *input_end = (int)BrotliReadBits(br, 1); |
+ *meta_block_length = 0; |
+ *is_uncompressed = 0; |
+ if (*input_end && BrotliReadBits(br, 1)) { |
+ return; |
+ } |
+ size_nibbles = (int)BrotliReadBits(br, 2) + 4; |
+ for (i = 0; i < size_nibbles; ++i) { |
+ *meta_block_length |= (int)BrotliReadBits(br, 4) << (i * 4); |
+ } |
+ ++(*meta_block_length); |
+ if (!*input_end) { |
+ *is_uncompressed = (int)BrotliReadBits(br, 1); |
+ } |
+} |
+ |
+/* Decodes the next Huffman code from bit-stream. */ |
+static BROTLI_INLINE int ReadSymbol(const HuffmanCode* table, |
+ BrotliBitReader* br) { |
+ int nbits; |
+ BrotliFillBitWindow(br); |
+ table += (int)(br->val_ >> br->bit_pos_) & HUFFMAN_TABLE_MASK; |
+ nbits = table->bits - HUFFMAN_TABLE_BITS; |
+ if (nbits > 0) { |
+ br->bit_pos_ += HUFFMAN_TABLE_BITS; |
+ table += table->value; |
+ table += (int)(br->val_ >> br->bit_pos_) & ((1 << nbits) - 1); |
+ } |
+ br->bit_pos_ += table->bits; |
+ return table->value; |
+} |
+ |
+static void PrintUcharVector(const uint8_t* v, int len) { |
+ while (len-- > 0) printf(" %d", *v++); |
+ printf("\n"); |
+} |
+ |
+static int ReadHuffmanCodeLengths( |
+ const uint8_t* code_length_code_lengths, |
+ int num_symbols, uint8_t* code_lengths, |
+ BrotliBitReader* br) { |
+ int symbol = 0; |
+ uint8_t prev_code_len = kDefaultCodeLength; |
+ int repeat = 0; |
+ uint8_t repeat_code_len = 0; |
+ int space = 32768; |
+ HuffmanCode table[32]; |
+ |
+ if (!BrotliBuildHuffmanTable(table, 5, |
+ code_length_code_lengths, |
+ CODE_LENGTH_CODES)) { |
+ printf("[ReadHuffmanCodeLengths] Building code length tree failed: "); |
+ PrintUcharVector(code_length_code_lengths, CODE_LENGTH_CODES); |
+ return 0; |
+ } |
+ |
+ while (symbol < num_symbols && space > 0) { |
+ const HuffmanCode* p = table; |
+ uint8_t code_len; |
+ if (!BrotliReadMoreInput(br)) { |
+ printf("[ReadHuffmanCodeLengths] Unexpected end of input.\n"); |
+ return 0; |
+ } |
+ BrotliFillBitWindow(br); |
+ p += (br->val_ >> br->bit_pos_) & 31; |
+ br->bit_pos_ += p->bits; |
+ code_len = (uint8_t)p->value; |
+ if (code_len < kCodeLengthRepeatCode) { |
+ repeat = 0; |
+ code_lengths[symbol++] = code_len; |
+ if (code_len != 0) { |
+ prev_code_len = code_len; |
+ space -= 32768 >> code_len; |
+ } |
+ } else { |
+ const int extra_bits = code_len - 14; |
+ int old_repeat; |
+ int repeat_delta; |
+ uint8_t new_len = 0; |
+ if (code_len == kCodeLengthRepeatCode) { |
+ new_len = prev_code_len; |
+ } |
+ if (repeat_code_len != new_len) { |
+ repeat = 0; |
+ repeat_code_len = new_len; |
+ } |
+ old_repeat = repeat; |
+ if (repeat > 0) { |
+ repeat -= 2; |
+ repeat <<= extra_bits; |
+ } |
+ repeat += (int)BrotliReadBits(br, extra_bits) + 3; |
+ repeat_delta = repeat - old_repeat; |
+ if (symbol + repeat_delta > num_symbols) { |
+ return 0; |
+ } |
+ memset(&code_lengths[symbol], repeat_code_len, (size_t)repeat_delta); |
+ symbol += repeat_delta; |
+ if (repeat_code_len != 0) { |
+ space -= repeat_delta << (15 - repeat_code_len); |
+ } |
+ } |
+ } |
+ if (space != 0) { |
+ printf("[ReadHuffmanCodeLengths] space = %d\n", space); |
+ return 0; |
+ } |
+ memset(&code_lengths[symbol], 0, (size_t)(num_symbols - symbol)); |
+ return 1; |
+} |
+ |
+static int ReadHuffmanCode(int alphabet_size, |
+ HuffmanCode* table, |
+ BrotliBitReader* br) { |
+ int ok = 1; |
+ int table_size = 0; |
+ int simple_code_or_skip; |
+ uint8_t* code_lengths = NULL; |
+ |
+ code_lengths = |
+ (uint8_t*)BrotliSafeMalloc((uint64_t)alphabet_size, |
+ sizeof(*code_lengths)); |
+ if (code_lengths == NULL) { |
+ return 0; |
+ } |
+ if (!BrotliReadMoreInput(br)) { |
+ printf("[ReadHuffmanCode] Unexpected end of input.\n"); |
+ return 0; |
+ } |
+ /* simple_code_or_skip is used as follows: |
+ 1 for simple code; |
+ 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ |
+ simple_code_or_skip = (int)BrotliReadBits(br, 2); |
+ BROTLI_LOG_UINT(simple_code_or_skip); |
+ if (simple_code_or_skip == 1) { |
+ /* Read symbols, codes & code lengths directly. */ |
+ int i; |
+ int max_bits_counter = alphabet_size - 1; |
+ int max_bits = 0; |
+ int symbols[4] = { 0 }; |
+ const int num_symbols = (int)BrotliReadBits(br, 2) + 1; |
+ while (max_bits_counter) { |
+ max_bits_counter >>= 1; |
+ ++max_bits; |
+ } |
+ memset(code_lengths, 0, (size_t)alphabet_size); |
+ for (i = 0; i < num_symbols; ++i) { |
+ symbols[i] = (int)BrotliReadBits(br, max_bits) % alphabet_size; |
+ code_lengths[symbols[i]] = 2; |
+ } |
+ code_lengths[symbols[0]] = 1; |
+ switch (num_symbols) { |
+ case 1: |
+ break; |
+ case 3: |
+ ok = ((symbols[0] != symbols[1]) && |
+ (symbols[0] != symbols[2]) && |
+ (symbols[1] != symbols[2])); |
+ break; |
+ case 2: |
+ ok = (symbols[0] != symbols[1]); |
+ 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 (BrotliReadBits(br, 1)) { |
+ code_lengths[symbols[2]] = 3; |
+ code_lengths[symbols[3]] = 3; |
+ } else { |
+ code_lengths[symbols[0]] = 2; |
+ } |
+ break; |
+ } |
+ BROTLI_LOG_UINT(num_symbols); |
+ } else { /* Decode Huffman-coded code lengths. */ |
+ int i; |
+ uint8_t code_length_code_lengths[CODE_LENGTH_CODES] = { 0 }; |
+ int space = 32; |
+ int num_codes = 0; |
+ /* Static Huffman code for the code length code lengths */ |
+ static const HuffmanCode huff[16] = { |
+ {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1}, |
+ {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5}, |
+ }; |
+ for (i = simple_code_or_skip; i < CODE_LENGTH_CODES && space > 0; ++i) { |
+ const int code_len_idx = kCodeLengthCodeOrder[i]; |
+ const HuffmanCode* p = huff; |
+ uint8_t v; |
+ BrotliFillBitWindow(br); |
+ p += (br->val_ >> br->bit_pos_) & 15; |
+ br->bit_pos_ += p->bits; |
+ v = (uint8_t)p->value; |
+ code_length_code_lengths[code_len_idx] = v; |
+ BROTLI_LOG_ARRAY_INDEX(code_length_code_lengths, code_len_idx); |
+ if (v != 0) { |
+ space -= (32 >> v); |
+ ++num_codes; |
+ } |
+ } |
+ ok = (num_codes == 1 || space == 0) && |
+ ReadHuffmanCodeLengths(code_length_code_lengths, |
+ alphabet_size, code_lengths, br); |
+ } |
+ if (ok) { |
+ table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, |
+ code_lengths, alphabet_size); |
+ if (table_size == 0) { |
+ printf("[ReadHuffmanCode] BuildHuffmanTable failed: "); |
+ PrintUcharVector(code_lengths, alphabet_size); |
+ } |
+ } |
+ free(code_lengths); |
+ return table_size; |
+} |
+ |
+static BROTLI_INLINE int ReadBlockLength(const HuffmanCode* table, |
+ BrotliBitReader* br) { |
+ int code; |
+ int nbits; |
+ code = ReadSymbol(table, br); |
+ nbits = kBlockLengthPrefixCode[code].nbits; |
+ return kBlockLengthPrefixCode[code].offset + (int)BrotliReadBits(br, nbits); |
+} |
+ |
+static int TranslateShortCodes(int code, int* ringbuffer, int index) { |
+ int val; |
+ if (code < NUM_DISTANCE_SHORT_CODES) { |
+ index += kDistanceShortCodeIndexOffset[code]; |
+ index &= 3; |
+ val = ringbuffer[index] + kDistanceShortCodeValueOffset[code]; |
+ } else { |
+ val = code - NUM_DISTANCE_SHORT_CODES + 1; |
+ } |
+ return val; |
+} |
+ |
+static void MoveToFront(uint8_t* v, uint8_t index) { |
+ uint8_t value = v[index]; |
+ uint8_t i = index; |
+ for (; i; --i) v[i] = v[i - 1]; |
+ v[0] = value; |
+} |
+ |
+static void InverseMoveToFrontTransform(uint8_t* v, int v_len) { |
+ uint8_t mtf[256]; |
+ int i; |
+ for (i = 0; i < 256; ++i) { |
+ mtf[i] = (uint8_t)i; |
+ } |
+ for (i = 0; i < v_len; ++i) { |
+ uint8_t index = v[i]; |
+ v[i] = mtf[index]; |
+ if (index) MoveToFront(mtf, index); |
+ } |
+} |
+ |
+/* Contains a collection of huffman trees with the same alphabet size. */ |
+typedef struct { |
+ int alphabet_size; |
+ int num_htrees; |
+ HuffmanCode* codes; |
+ HuffmanCode** htrees; |
+} HuffmanTreeGroup; |
+ |
+static void HuffmanTreeGroupInit(HuffmanTreeGroup* group, int alphabet_size, |
+ int ntrees) { |
+ group->alphabet_size = alphabet_size; |
+ group->num_htrees = ntrees; |
+ group->codes = (HuffmanCode*)malloc( |
+ sizeof(HuffmanCode) * (size_t)(ntrees * HUFFMAN_MAX_TABLE_SIZE)); |
+ group->htrees = (HuffmanCode**)malloc(sizeof(HuffmanCode*) * (size_t)ntrees); |
+} |
+ |
+static void HuffmanTreeGroupRelease(HuffmanTreeGroup* group) { |
+ if (group->codes) { |
+ free(group->codes); |
+ } |
+ if (group->htrees) { |
+ free(group->htrees); |
+ } |
+} |
+ |
+static int HuffmanTreeGroupDecode(HuffmanTreeGroup* group, |
+ BrotliBitReader* br) { |
+ int i; |
+ int table_size; |
+ HuffmanCode* next = group->codes; |
+ for (i = 0; i < group->num_htrees; ++i) { |
+ group->htrees[i] = next; |
+ table_size = ReadHuffmanCode(group->alphabet_size, next, br); |
+ next += table_size; |
+ if (table_size == 0) { |
+ return 0; |
+ } |
+ } |
+ return 1; |
+} |
+ |
+static int DecodeContextMap(int context_map_size, |
+ int* num_htrees, |
+ uint8_t** context_map, |
+ BrotliBitReader* br) { |
+ int ok = 1; |
+ int use_rle_for_zeros; |
+ int max_run_length_prefix = 0; |
+ HuffmanCode* table; |
+ int i; |
+ if (!BrotliReadMoreInput(br)) { |
+ printf("[DecodeContextMap] Unexpected end of input.\n"); |
+ return 0; |
+ } |
+ *num_htrees = DecodeVarLenUint8(br) + 1; |
+ |
+ BROTLI_LOG_UINT(context_map_size); |
+ BROTLI_LOG_UINT(*num_htrees); |
+ |
+ *context_map = (uint8_t*)malloc((size_t)context_map_size); |
+ if (*context_map == 0) { |
+ return 0; |
+ } |
+ if (*num_htrees <= 1) { |
+ memset(*context_map, 0, (size_t)context_map_size); |
+ return 1; |
+ } |
+ |
+ use_rle_for_zeros = (int)BrotliReadBits(br, 1); |
+ if (use_rle_for_zeros) { |
+ max_run_length_prefix = (int)BrotliReadBits(br, 4) + 1; |
+ } |
+ table = (HuffmanCode*)malloc(HUFFMAN_MAX_TABLE_SIZE * sizeof(*table)); |
+ if (table == NULL) { |
+ return 0; |
+ } |
+ if (!ReadHuffmanCode(*num_htrees + max_run_length_prefix, table, br)) { |
+ ok = 0; |
+ goto End; |
+ } |
+ for (i = 0; i < context_map_size;) { |
+ int code; |
+ if (!BrotliReadMoreInput(br)) { |
+ printf("[DecodeContextMap] Unexpected end of input.\n"); |
+ ok = 0; |
+ goto End; |
+ } |
+ code = ReadSymbol(table, br); |
+ if (code == 0) { |
+ (*context_map)[i] = 0; |
+ ++i; |
+ } else if (code <= max_run_length_prefix) { |
+ int reps = 1 + (1 << code) + (int)BrotliReadBits(br, code); |
+ while (--reps) { |
+ if (i >= context_map_size) { |
+ ok = 0; |
+ goto End; |
+ } |
+ (*context_map)[i] = 0; |
+ ++i; |
+ } |
+ } else { |
+ (*context_map)[i] = (uint8_t)(code - max_run_length_prefix); |
+ ++i; |
+ } |
+ } |
+ if (BrotliReadBits(br, 1)) { |
+ InverseMoveToFrontTransform(*context_map, context_map_size); |
+ } |
+End: |
+ free(table); |
+ return ok; |
+} |
+ |
+static BROTLI_INLINE void DecodeBlockType(const int max_block_type, |
+ const HuffmanCode* trees, |
+ int tree_type, |
+ int* block_types, |
+ int* ringbuffers, |
+ int* indexes, |
+ BrotliBitReader* br) { |
+ int* ringbuffer = ringbuffers + tree_type * 2; |
+ int* index = indexes + tree_type; |
+ int type_code = ReadSymbol(&trees[tree_type * HUFFMAN_MAX_TABLE_SIZE], br); |
+ int block_type; |
+ if (type_code == 0) { |
+ block_type = ringbuffer[*index & 1]; |
+ } else if (type_code == 1) { |
+ block_type = ringbuffer[(*index - 1) & 1] + 1; |
+ } else { |
+ block_type = type_code - 2; |
+ } |
+ if (block_type >= max_block_type) { |
+ block_type -= max_block_type; |
+ } |
+ block_types[tree_type] = block_type; |
+ ringbuffer[(*index) & 1] = block_type; |
+ ++(*index); |
+} |
+ |
+/* Copy len bytes from src to dst. It can write up to ten extra bytes |
+ after the end of the copy. |
+ |
+ The main part of this loop is a simple copy of eight bytes at a time until |
+ we've copied (at least) the requested amount of bytes. However, if dst and |
+ src are less than eight bytes apart (indicating a repeating pattern of |
+ length < 8), we first need to expand the pattern in order to get the correct |
+ results. For instance, if the buffer looks like this, with the eight-byte |
+ <src> and <dst> patterns marked as intervals: |
+ |
+ abxxxxxxxxxxxx |
+ [------] src |
+ [------] dst |
+ |
+ a single eight-byte copy from <src> to <dst> will repeat the pattern once, |
+ after which we can move <dst> two bytes without moving <src>: |
+ |
+ ababxxxxxxxxxx |
+ [------] src |
+ [------] dst |
+ |
+ and repeat the exercise until the two no longer overlap. |
+ |
+ This allows us to do very well in the special case of one single byte |
+ repeated many times, without taking a big hit for more general cases. |
+ |
+ The worst case of extra writing past the end of the match occurs when |
+ dst - src == 1 and len == 1; the last copy will read from byte positions |
+ [0..7] and write to [4..11], whereas it was only supposed to write to |
+ position 1. Thus, ten excess bytes. |
+*/ |
+static BROTLI_INLINE void IncrementalCopyFastPath( |
+ uint8_t* dst, const uint8_t* src, int len) { |
+ if (src < dst) { |
+ while (dst - src < 8) { |
+ UNALIGNED_MOVE64(dst, src); |
+ len -= (int)(dst - src); |
+ dst += dst - src; |
+ } |
+ } |
+ while (len > 0) { |
+ UNALIGNED_COPY64(dst, src); |
+ src += 8; |
+ dst += 8; |
+ len -= 8; |
+ } |
+} |
+ |
+int CopyUncompressedBlockToOutput(BrotliOutput output, int len, int pos, |
+ uint8_t* ringbuffer, int ringbuffer_mask, |
+ BrotliBitReader* br) { |
+ const int rb_size = ringbuffer_mask + 1; |
+ uint8_t* ringbuffer_end = ringbuffer + rb_size; |
+ int rb_pos = pos & ringbuffer_mask; |
+ int br_pos = br->pos_ & BROTLI_IBUF_MASK; |
+ int nbytes; |
+ |
+ /* For short lengths copy byte-by-byte */ |
+ if (len < 8 || br->bit_pos_ + (uint32_t)(len << 3) < br->bit_end_pos_) { |
+ while (len-- > 0) { |
+ if (!BrotliReadMoreInput(br)) { |
+ return 0; |
+ } |
+ ringbuffer[rb_pos++]= (uint8_t)BrotliReadBits(br, 8); |
+ if (rb_pos == rb_size) { |
+ if (BrotliWrite(output, ringbuffer, (size_t)rb_size) < rb_size) { |
+ return 0; |
+ } |
+ rb_pos = 0; |
+ } |
+ } |
+ return 1; |
+ } |
+ |
+ if (br->bit_end_pos_ < 64) { |
+ return 0; |
+ } |
+ |
+ /* Copy remaining 0-8 bytes from br->val_ to ringbuffer. */ |
+ while (br->bit_pos_ < 64) { |
+ ringbuffer[rb_pos] = (uint8_t)(br->val_ >> br->bit_pos_); |
+ br->bit_pos_ += 8; |
+ ++rb_pos; |
+ --len; |
+ } |
+ |
+ /* Copy remaining bytes from br->buf_ to ringbuffer. */ |
+ nbytes = (int)(br->bit_end_pos_ - br->bit_pos_) >> 3; |
+ if (br_pos + nbytes > BROTLI_IBUF_MASK) { |
+ int tail = BROTLI_IBUF_MASK + 1 - br_pos; |
+ memcpy(&ringbuffer[rb_pos], &br->buf_[br_pos], (size_t)tail); |
+ nbytes -= tail; |
+ rb_pos += tail; |
+ len -= tail; |
+ br_pos = 0; |
+ } |
+ memcpy(&ringbuffer[rb_pos], &br->buf_[br_pos], (size_t)nbytes); |
+ rb_pos += nbytes; |
+ len -= nbytes; |
+ |
+ /* If we wrote past the logical end of the ringbuffer, copy the tail of the |
+ ringbuffer to its beginning and flush the ringbuffer to the output. */ |
+ if (rb_pos >= rb_size) { |
+ if (BrotliWrite(output, ringbuffer, (size_t)rb_size) < rb_size) { |
+ return 0; |
+ } |
+ rb_pos -= rb_size; |
+ memcpy(ringbuffer, ringbuffer_end, (size_t)rb_pos); |
+ } |
+ |
+ /* 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 ringbuffer to |
+ the output */ |
+ while (rb_pos + len >= rb_size) { |
+ nbytes = rb_size - rb_pos; |
+ if (BrotliRead(br->input_, &ringbuffer[rb_pos], (size_t)nbytes) < nbytes || |
+ BrotliWrite(output, ringbuffer, (size_t)rb_size) < nbytes) { |
+ return 0; |
+ } |
+ len -= nbytes; |
+ rb_pos = 0; |
+ } |
+ |
+ /* Copy straight from the input onto the ringbuffer. The ringbuffer will be |
+ flushed to the output at a later time. */ |
+ if (BrotliRead(br->input_, &ringbuffer[rb_pos], (size_t)len) < len) { |
+ return 0; |
+ } |
+ |
+ /* Restore the state of the bit reader. */ |
+ BrotliInitBitReader(br, br->input_); |
+ return 1; |
+} |
+ |
+int BrotliDecompressedSize(size_t encoded_size, |
+ const uint8_t* encoded_buffer, |
+ size_t* decoded_size) { |
+ int i; |
+ uint64_t val = 0; |
+ int bit_pos = 0; |
+ int is_last; |
+ int is_uncompressed = 0; |
+ int size_nibbles; |
+ int meta_block_len = 0; |
+ if (encoded_size == 0) { |
+ return 0; |
+ } |
+ /* Look at the first 8 bytes, it is enough to decode the length of the first |
+ meta-block. */ |
+ for (i = 0; (size_t)i < encoded_size && i < 8; ++i) { |
+ val |= (uint64_t)encoded_buffer[i] << (8 * i); |
+ } |
+ /* Skip the window bits. */ |
+ bit_pos += (val & 1) ? 4 : 1; |
+ /* Decode the ISLAST bit. */ |
+ is_last = (val >> bit_pos) & 1; |
+ ++bit_pos; |
+ if (is_last) { |
+ /* Decode the ISEMPTY bit, if it is set to 1, we are done. */ |
+ if ((val >> bit_pos) & 1) { |
+ *decoded_size = 0; |
+ return 1; |
+ } |
+ ++bit_pos; |
+ } |
+ /* Decode the length of the first meta-block. */ |
+ size_nibbles = (int)((val >> bit_pos) & 3) + 4; |
+ bit_pos += 2; |
+ for (i = 0; i < size_nibbles; ++i) { |
+ meta_block_len |= (int)((val >> bit_pos) & 0xf) << (4 * i); |
+ bit_pos += 4; |
+ } |
+ ++meta_block_len; |
+ if (is_last) { |
+ /* If this meta-block is the only one, we are done. */ |
+ *decoded_size = (size_t)meta_block_len; |
+ return 1; |
+ } |
+ is_uncompressed = (val >> bit_pos) & 1; |
+ ++bit_pos; |
+ if (is_uncompressed) { |
+ /* If the first meta-block is uncompressed, we skip it and look at the |
+ first two bits (ISLAST and ISEMPTY) of the next meta-block, and if |
+ both are set to 1, we have a stream with an uncompressed meta-block |
+ followed by an empty one, so the decompressed size is the size of the |
+ first meta-block. */ |
+ size_t offset = ((bit_pos + 7) >> 3) + meta_block_len; |
+ if (offset < encoded_size && ((encoded_buffer[offset] & 3) == 3)) { |
+ *decoded_size = (size_t)meta_block_len; |
+ return 1; |
+ } |
+ } |
+ return 0; |
+} |
+ |
+int 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); |
+ *decoded_size = mout.pos; |
+ return success; |
+} |
+ |
+int BrotliDecompress(BrotliInput input, BrotliOutput output) { |
+ int ok = 1; |
+ int i; |
+ int pos = 0; |
+ int input_end = 0; |
+ int window_bits = 0; |
+ int max_backward_distance; |
+ int max_distance = 0; |
+ int ringbuffer_size; |
+ int ringbuffer_mask; |
+ uint8_t* ringbuffer; |
+ uint8_t* ringbuffer_end; |
+ /* This ring buffer holds a few past copy distances that will be used by */ |
+ /* some special distance codes. */ |
+ int dist_rb[4] = { 16, 15, 11, 4 }; |
+ int dist_rb_idx = 0; |
+ /* The previous 2 bytes used for context. */ |
+ uint8_t prev_byte1 = 0; |
+ uint8_t prev_byte2 = 0; |
+ HuffmanTreeGroup hgroup[3]; |
+ HuffmanCode* block_type_trees = NULL; |
+ HuffmanCode* block_len_trees = NULL; |
+ BrotliBitReader br; |
+ |
+ /* We need the slack region for the following reasons: |
+ - always doing two 8-byte copies for fast backward copying |
+ - transforms |
+ - flushing the input ringbuffer when decoding uncompressed blocks */ |
+ static const int kRingBufferWriteAheadSlack = 128 + BROTLI_READ_SIZE; |
+ |
+ if (!BrotliInitBitReader(&br, input)) { |
+ return 0; |
+ } |
+ |
+ /* Decode window size. */ |
+ window_bits = DecodeWindowBits(&br); |
+ max_backward_distance = (1 << window_bits) - 16; |
+ |
+ ringbuffer_size = 1 << window_bits; |
+ ringbuffer_mask = ringbuffer_size - 1; |
+ ringbuffer = (uint8_t*)malloc((size_t)(ringbuffer_size + |
+ kRingBufferWriteAheadSlack + |
+ kMaxDictionaryWordLength)); |
+ if (!ringbuffer) { |
+ ok = 0; |
+ } |
+ ringbuffer_end = ringbuffer + ringbuffer_size; |
+ |
+ if (ok) { |
+ block_type_trees = (HuffmanCode*)malloc( |
+ 3 * HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode)); |
+ block_len_trees = (HuffmanCode*)malloc( |
+ 3 * HUFFMAN_MAX_TABLE_SIZE * sizeof(HuffmanCode)); |
+ if (block_type_trees == NULL || block_len_trees == NULL) { |
+ ok = 0; |
+ } |
+ } |
+ |
+ while (!input_end && ok) { |
+ int meta_block_remaining_len = 0; |
+ int is_uncompressed; |
+ int block_length[3] = { 1 << 28, 1 << 28, 1 << 28 }; |
+ int block_type[3] = { 0 }; |
+ int num_block_types[3] = { 1, 1, 1 }; |
+ int block_type_rb[6] = { 0, 1, 0, 1, 0, 1 }; |
+ int block_type_rb_index[3] = { 0 }; |
+ int distance_postfix_bits; |
+ int num_direct_distance_codes; |
+ int distance_postfix_mask; |
+ int num_distance_codes; |
+ uint8_t* context_map = NULL; |
+ uint8_t* context_modes = NULL; |
+ int num_literal_htrees; |
+ uint8_t* dist_context_map = NULL; |
+ int num_dist_htrees; |
+ int context_offset = 0; |
+ uint8_t* context_map_slice = NULL; |
+ uint8_t literal_htree_index = 0; |
+ int dist_context_offset = 0; |
+ uint8_t* dist_context_map_slice = NULL; |
+ uint8_t dist_htree_index = 0; |
+ int context_lookup_offset1 = 0; |
+ int context_lookup_offset2 = 0; |
+ uint8_t context_mode; |
+ HuffmanCode* htree_command; |
+ |
+ for (i = 0; i < 3; ++i) { |
+ hgroup[i].codes = NULL; |
+ hgroup[i].htrees = NULL; |
+ } |
+ |
+ if (!BrotliReadMoreInput(&br)) { |
+ printf("[BrotliDecompress] Unexpected end of input.\n"); |
+ ok = 0; |
+ goto End; |
+ } |
+ BROTLI_LOG_UINT(pos); |
+ DecodeMetaBlockLength(&br, &meta_block_remaining_len, |
+ &input_end, &is_uncompressed); |
+ BROTLI_LOG_UINT(meta_block_remaining_len); |
+ if (meta_block_remaining_len == 0) { |
+ goto End; |
+ } |
+ if (is_uncompressed) { |
+ BrotliSetBitPos(&br, (br.bit_pos_ + 7) & (uint32_t)(~7UL)); |
+ ok = CopyUncompressedBlockToOutput(output, meta_block_remaining_len, pos, |
+ ringbuffer, ringbuffer_mask, &br); |
+ pos += meta_block_remaining_len; |
+ goto End; |
+ } |
+ for (i = 0; i < 3; ++i) { |
+ num_block_types[i] = DecodeVarLenUint8(&br) + 1; |
+ if (num_block_types[i] >= 2) { |
+ if (!ReadHuffmanCode(num_block_types[i] + 2, |
+ &block_type_trees[i * HUFFMAN_MAX_TABLE_SIZE], |
+ &br) || |
+ !ReadHuffmanCode(kNumBlockLengthCodes, |
+ &block_len_trees[i * HUFFMAN_MAX_TABLE_SIZE], |
+ &br)) { |
+ ok = 0; |
+ goto End; |
+ } |
+ block_length[i] = ReadBlockLength( |
+ &block_len_trees[i * HUFFMAN_MAX_TABLE_SIZE], &br); |
+ block_type_rb_index[i] = 1; |
+ } |
+ } |
+ |
+ BROTLI_LOG_UINT(num_block_types[0]); |
+ BROTLI_LOG_UINT(num_block_types[1]); |
+ BROTLI_LOG_UINT(num_block_types[2]); |
+ BROTLI_LOG_UINT(block_length[0]); |
+ BROTLI_LOG_UINT(block_length[1]); |
+ BROTLI_LOG_UINT(block_length[2]); |
+ |
+ if (!BrotliReadMoreInput(&br)) { |
+ printf("[BrotliDecompress] Unexpected end of input.\n"); |
+ ok = 0; |
+ goto End; |
+ } |
+ distance_postfix_bits = (int)BrotliReadBits(&br, 2); |
+ num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + |
+ ((int)BrotliReadBits(&br, 4) << distance_postfix_bits); |
+ distance_postfix_mask = (1 << distance_postfix_bits) - 1; |
+ num_distance_codes = (num_direct_distance_codes + |
+ (48 << distance_postfix_bits)); |
+ context_modes = (uint8_t*)malloc((size_t)num_block_types[0]); |
+ if (context_modes == 0) { |
+ ok = 0; |
+ goto End; |
+ } |
+ for (i = 0; i < num_block_types[0]; ++i) { |
+ context_modes[i] = (uint8_t)(BrotliReadBits(&br, 2) << 1); |
+ BROTLI_LOG_ARRAY_INDEX(context_modes, i); |
+ } |
+ BROTLI_LOG_UINT(num_direct_distance_codes); |
+ BROTLI_LOG_UINT(distance_postfix_bits); |
+ |
+ if (!DecodeContextMap(num_block_types[0] << kLiteralContextBits, |
+ &num_literal_htrees, &context_map, &br) || |
+ !DecodeContextMap(num_block_types[2] << kDistanceContextBits, |
+ &num_dist_htrees, &dist_context_map, &br)) { |
+ ok = 0; |
+ goto End; |
+ } |
+ |
+ HuffmanTreeGroupInit(&hgroup[0], kNumLiteralCodes, num_literal_htrees); |
+ HuffmanTreeGroupInit(&hgroup[1], kNumInsertAndCopyCodes, |
+ num_block_types[1]); |
+ HuffmanTreeGroupInit(&hgroup[2], num_distance_codes, num_dist_htrees); |
+ |
+ for (i = 0; i < 3; ++i) { |
+ if (!HuffmanTreeGroupDecode(&hgroup[i], &br)) { |
+ ok = 0; |
+ goto End; |
+ } |
+ } |
+ |
+ context_map_slice = context_map; |
+ dist_context_map_slice = dist_context_map; |
+ context_mode = context_modes[block_type[0]]; |
+ context_lookup_offset1 = kContextLookupOffsets[context_mode]; |
+ context_lookup_offset2 = kContextLookupOffsets[context_mode + 1]; |
+ htree_command = hgroup[1].htrees[0]; |
+ |
+ while (meta_block_remaining_len > 0) { |
+ int cmd_code; |
+ int range_idx; |
+ int insert_code; |
+ int copy_code; |
+ int insert_length; |
+ int copy_length; |
+ int distance_code; |
+ int distance; |
+ uint8_t context; |
+ int j; |
+ const uint8_t* copy_src; |
+ uint8_t* copy_dst; |
+ if (!BrotliReadMoreInput(&br)) { |
+ printf("[BrotliDecompress] Unexpected end of input.\n"); |
+ ok = 0; |
+ goto End; |
+ } |
+ if (block_length[1] == 0) { |
+ DecodeBlockType(num_block_types[1], |
+ block_type_trees, 1, block_type, block_type_rb, |
+ block_type_rb_index, &br); |
+ block_length[1] = ReadBlockLength( |
+ &block_len_trees[HUFFMAN_MAX_TABLE_SIZE], &br); |
+ htree_command = hgroup[1].htrees[block_type[1]]; |
+ } |
+ --block_length[1]; |
+ cmd_code = ReadSymbol(htree_command, &br); |
+ range_idx = cmd_code >> 6; |
+ if (range_idx >= 2) { |
+ range_idx -= 2; |
+ distance_code = -1; |
+ } else { |
+ distance_code = 0; |
+ } |
+ insert_code = kInsertRangeLut[range_idx] + ((cmd_code >> 3) & 7); |
+ copy_code = kCopyRangeLut[range_idx] + (cmd_code & 7); |
+ insert_length = kInsertLengthPrefixCode[insert_code].offset + |
+ (int)BrotliReadBits(&br, kInsertLengthPrefixCode[insert_code].nbits); |
+ copy_length = kCopyLengthPrefixCode[copy_code].offset + |
+ (int)BrotliReadBits(&br, kCopyLengthPrefixCode[copy_code].nbits); |
+ BROTLI_LOG_UINT(insert_length); |
+ BROTLI_LOG_UINT(copy_length); |
+ BROTLI_LOG_UINT(distance_code); |
+ for (j = 0; j < insert_length; ++j) { |
+ if (!BrotliReadMoreInput(&br)) { |
+ printf("[BrotliDecompress] Unexpected end of input.\n"); |
+ ok = 0; |
+ goto End; |
+ } |
+ if (block_length[0] == 0) { |
+ DecodeBlockType(num_block_types[0], |
+ block_type_trees, 0, block_type, block_type_rb, |
+ block_type_rb_index, &br); |
+ block_length[0] = ReadBlockLength(block_len_trees, &br); |
+ context_offset = block_type[0] << kLiteralContextBits; |
+ context_map_slice = context_map + context_offset; |
+ context_mode = context_modes[block_type[0]]; |
+ context_lookup_offset1 = kContextLookupOffsets[context_mode]; |
+ context_lookup_offset2 = kContextLookupOffsets[context_mode + 1]; |
+ } |
+ context = (kContextLookup[context_lookup_offset1 + prev_byte1] | |
+ kContextLookup[context_lookup_offset2 + prev_byte2]); |
+ BROTLI_LOG_UINT(context); |
+ literal_htree_index = context_map_slice[context]; |
+ --block_length[0]; |
+ prev_byte2 = prev_byte1; |
+ prev_byte1 = (uint8_t)ReadSymbol(hgroup[0].htrees[literal_htree_index], |
+ &br); |
+ ringbuffer[pos & ringbuffer_mask] = prev_byte1; |
+ BROTLI_LOG_UINT(literal_htree_index); |
+ BROTLI_LOG_ARRAY_INDEX(ringbuffer, pos & ringbuffer_mask); |
+ if ((pos & ringbuffer_mask) == ringbuffer_mask) { |
+ if (BrotliWrite(output, ringbuffer, (size_t)ringbuffer_size) < 0) { |
+ ok = 0; |
+ goto End; |
+ } |
+ } |
+ ++pos; |
+ } |
+ meta_block_remaining_len -= insert_length; |
+ if (meta_block_remaining_len <= 0) break; |
+ |
+ if (distance_code < 0) { |
+ uint8_t context; |
+ if (!BrotliReadMoreInput(&br)) { |
+ printf("[BrotliDecompress] Unexpected end of input.\n"); |
+ ok = 0; |
+ goto End; |
+ } |
+ if (block_length[2] == 0) { |
+ DecodeBlockType(num_block_types[2], |
+ block_type_trees, 2, block_type, block_type_rb, |
+ block_type_rb_index, &br); |
+ block_length[2] = ReadBlockLength( |
+ &block_len_trees[2 * HUFFMAN_MAX_TABLE_SIZE], &br); |
+ dist_context_offset = block_type[2] << kDistanceContextBits; |
+ dist_context_map_slice = dist_context_map + dist_context_offset; |
+ } |
+ --block_length[2]; |
+ context = (uint8_t)(copy_length > 4 ? 3 : copy_length - 2); |
+ dist_htree_index = dist_context_map_slice[context]; |
+ distance_code = ReadSymbol(hgroup[2].htrees[dist_htree_index], &br); |
+ if (distance_code >= num_direct_distance_codes) { |
+ int nbits; |
+ int postfix; |
+ int offset; |
+ distance_code -= num_direct_distance_codes; |
+ postfix = distance_code & distance_postfix_mask; |
+ distance_code >>= distance_postfix_bits; |
+ nbits = (distance_code >> 1) + 1; |
+ offset = ((2 + (distance_code & 1)) << nbits) - 4; |
+ distance_code = num_direct_distance_codes + |
+ ((offset + (int)BrotliReadBits(&br, nbits)) << |
+ distance_postfix_bits) + postfix; |
+ } |
+ } |
+ |
+ /* Convert the distance code to the actual distance by possibly looking */ |
+ /* up past distnaces from the ringbuffer. */ |
+ distance = TranslateShortCodes(distance_code, dist_rb, dist_rb_idx); |
+ if (distance < 0) { |
+ ok = 0; |
+ goto End; |
+ } |
+ BROTLI_LOG_UINT(distance); |
+ |
+ if (pos < max_backward_distance && |
+ max_distance != max_backward_distance) { |
+ max_distance = pos; |
+ } else { |
+ max_distance = max_backward_distance; |
+ } |
+ |
+ copy_dst = &ringbuffer[pos & ringbuffer_mask]; |
+ |
+ if (distance > max_distance) { |
+ if (copy_length >= kMinDictionaryWordLength && |
+ copy_length <= kMaxDictionaryWordLength) { |
+ int offset = kBrotliDictionaryOffsetsByLength[copy_length]; |
+ int word_id = distance - max_distance - 1; |
+ int shift = kBrotliDictionarySizeBitsByLength[copy_length]; |
+ int mask = (1 << shift) - 1; |
+ int word_idx = word_id & mask; |
+ int transform_idx = word_id >> shift; |
+ offset += word_idx * copy_length; |
+ if (transform_idx < kNumTransforms) { |
+ const uint8_t* word = &kBrotliDictionary[offset]; |
+ int len = TransformDictionaryWord( |
+ copy_dst, word, copy_length, transform_idx); |
+ copy_dst += len; |
+ pos += len; |
+ meta_block_remaining_len -= len; |
+ if (copy_dst >= ringbuffer_end) { |
+ if (BrotliWrite(output, ringbuffer, |
+ (size_t)ringbuffer_size) < 0) { |
+ ok = 0; |
+ goto End; |
+ } |
+ memcpy(ringbuffer, ringbuffer_end, |
+ (size_t)(copy_dst - ringbuffer_end)); |
+ } |
+ } else { |
+ printf("Invalid backward reference. pos: %d distance: %d " |
+ "len: %d bytes left: %d\n", pos, distance, copy_length, |
+ meta_block_remaining_len); |
+ ok = 0; |
+ goto End; |
+ } |
+ } else { |
+ printf("Invalid backward reference. pos: %d distance: %d " |
+ "len: %d bytes left: %d\n", pos, distance, copy_length, |
+ meta_block_remaining_len); |
+ ok = 0; |
+ goto End; |
+ } |
+ } else { |
+ if (distance_code > 0) { |
+ dist_rb[dist_rb_idx & 3] = distance; |
+ ++dist_rb_idx; |
+ } |
+ |
+ if (copy_length > meta_block_remaining_len) { |
+ printf("Invalid backward reference. pos: %d distance: %d " |
+ "len: %d bytes left: %d\n", pos, distance, copy_length, |
+ meta_block_remaining_len); |
+ ok = 0; |
+ goto End; |
+ } |
+ |
+ copy_src = &ringbuffer[(pos - distance) & ringbuffer_mask]; |
+ |
+#if (defined(__x86_64__) || defined(_M_X64)) |
+ if (copy_src + copy_length <= ringbuffer_end && |
+ copy_dst + copy_length < ringbuffer_end) { |
+ if (copy_length <= 16 && distance >= 8) { |
+ UNALIGNED_COPY64(copy_dst, copy_src); |
+ UNALIGNED_COPY64(copy_dst + 8, copy_src + 8); |
+ } else { |
+ IncrementalCopyFastPath(copy_dst, copy_src, copy_length); |
+ } |
+ pos += copy_length; |
+ meta_block_remaining_len -= copy_length; |
+ copy_length = 0; |
+ } |
+#endif |
+ |
+ for (j = 0; j < copy_length; ++j) { |
+ ringbuffer[pos & ringbuffer_mask] = |
+ ringbuffer[(pos - distance) & ringbuffer_mask]; |
+ if ((pos & ringbuffer_mask) == ringbuffer_mask) { |
+ if (BrotliWrite(output, ringbuffer, (size_t)ringbuffer_size) < 0) { |
+ ok = 0; |
+ goto End; |
+ } |
+ } |
+ ++pos; |
+ --meta_block_remaining_len; |
+ } |
+ } |
+ |
+ /* When we get here, we must have inserted at least one literal and */ |
+ /* made a copy of at least length two, therefore accessing the last 2 */ |
+ /* bytes is valid. */ |
+ prev_byte1 = ringbuffer[(pos - 1) & ringbuffer_mask]; |
+ prev_byte2 = ringbuffer[(pos - 2) & ringbuffer_mask]; |
+ } |
+ |
+ /* Protect pos from overflow, wrap it around at every GB of input data */ |
+ pos &= 0x3fffffff; |
+ |
+ End: |
+ if (context_modes != 0) { |
+ free(context_modes); |
+ } |
+ if (context_map != 0) { |
+ free(context_map); |
+ } |
+ if (dist_context_map != 0) { |
+ free(dist_context_map); |
+ } |
+ for (i = 0; i < 3; ++i) { |
+ HuffmanTreeGroupRelease(&hgroup[i]); |
+ } |
+ } |
+ |
+ if (ringbuffer != 0) { |
+ if (BrotliWrite(output, ringbuffer, (size_t)(pos & ringbuffer_mask)) < 0) { |
+ ok = 0; |
+ } |
+ free(ringbuffer); |
+ } |
+ if (block_type_trees != 0) { |
+ free(block_type_trees); |
+ } |
+ if (block_len_trees != 0) { |
+ free(block_len_trees); |
+ } |
+ return ok; |
+} |
+ |
+#if defined(__cplusplus) || defined(c_plusplus) |
+} /* extern "C" */ |
+#endif |