Bug 1242904 - Update Brotli to latest upstream revision ; now at 33aa40220b96cf95ad2b9ba61dc8d7fd2f964f2c. r=mcmanus

This commit is contained in:
Frédéric Wang 2016-02-08 12:01:21 +01:00
Родитель c32fd629f0
Коммит a4aeb26856
22 изменённых файлов: 2187 добавлений и 1604 удалений

Просмотреть файл

@ -14,59 +14,4 @@ The in-tree copy is updated by running
sh update.sh
from within the modules/brotli directory.
Current version: [commit 933bb9bd800c8f5f7f6a02382d33c902a98ef73a].
this trivial patch is added to preserve no-warnings behavior in code
that includes the brotli interface. future imports are expected to
have an equivalent change made upstream already.
diff --git a/modules/brotli/dec/bit_reader.h b/modules/brotli/dec/bit_reader.h
--- a/modules/brotli/dec/bit_reader.h
+++ b/modules/brotli/dec/bit_reader.h
@@ -284,17 +284,17 @@ static BROTLI_INLINE int BrotliPeekByte(
int bytes_left = (int)(sizeof(br->val_) - (br->bit_pos_ >> 3));
if (br->bit_pos_ & 7) {
return -1;
}
if (offset < bytes_left) {
return (br->val_ >> (br->bit_pos_ + (unsigned)(offset << 3))) & 0xFF;
}
offset -= bytes_left;
- if (offset < br->avail_in) {
+ if (offset < (long)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. */
This patch fixes a use-before declare error on big endian platforms
in bit_reader.h. Upstream has already fixed this error by re-arranging
some functions in the file.
diff --git a/modules/brotli/dec/bit_reader.h b/modules/brotli/dec/bit_reader.h
--- a/modules/brotli/dec/bit_reader.h
+++ b/modules/brotli/dec/bit_reader.h
@@ -58,17 +58,17 @@ typedef struct {
/* Initializes the bitreader fields. */
void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input);
/* Ensures that accumulator is not empty. May consume one byte of input.
Returns 0 if data is required but there is no input available.
For BROTLI_BUILD_PORTABLE this function also prepares bit reader for aligned
reading. */
int BrotliWarmupBitReader(BrotliBitReader* const br);
-
+static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br);
/* Pulls data from the input to the the read buffer.
Returns 0 if one of:
- the input callback returned an error, or
- there is no more input and the position is past the end of the stream.
- finish is false and less than BROTLI_READ_SIZE are available - a next call
when more data is available makes it continue including the partially read
data
Current version: [commit 33aa40220b96cf95ad2b9ba61dc8d7fd2f964f2c].

Просмотреть файл

@ -4,7 +4,7 @@ include ../shared.mk
CFLAGS += -Wall
OBJS = bit_reader.o decode.o dictionary.o huffman.o state.o streams.o
OBJS = bit_reader.o decode.o dictionary.o huffman.o state.o
all : $(OBJS)

Просмотреть файл

@ -1,38 +1,23 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Bit reading helpers */
#include <stdlib.h>
#include "./bit_reader.h"
#include "./port.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input) {
BROTLI_DCHECK(br != NULL);
br->input_ = input;
void BrotliInitBitReader(BrotliBitReader* const br) {
br->val_ = 0;
br->bit_pos_ = sizeof(br->val_) << 3;
br->avail_in = 0;
br->eos_ = 0;
br->next_in = br->buf_;
}
int BrotliWarmupBitReader(BrotliBitReader* const br) {
@ -43,12 +28,17 @@ int BrotliWarmupBitReader(BrotliBitReader* const br) {
if (!BROTLI_ALIGNED_READ) {
aligned_read_mask = 0;
}
while (br->bit_pos_ == (sizeof(br->val_) << 3) ||
(((size_t)br->next_in) & aligned_read_mask) != 0) {
if (!br->avail_in) {
if (BrotliGetAvailableBits(br) == 0) {
if (!BrotliPullByte(br)) {
return 0;
}
BrotliPullByte(br);
}
while ((((size_t)br->next_in) & aligned_read_mask) != 0) {
if (!BrotliPullByte(br)) {
/* If we consumed all the input, we don't care about the alignment. */
return 1;
}
}
return 1;
}

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Bit reading helpers */
@ -18,129 +9,171 @@
#ifndef BROTLI_DEC_BIT_READER_H_
#define BROTLI_DEC_BIT_READER_H_
#include <string.h>
#include <string.h> /* memcpy */
#include "./port.h"
#include "./streams.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#define BROTLI_READ_SIZE 1024
/* 128 bytes, plus 8 bytes slack for valid 128-byte BrotliCheckInputAmount with
some bytes read in val_ of bit reader. */
#define BROTLI_IMPLICIT_ZEROES 136
#define BROTLI_IBUF_SIZE (BROTLI_READ_SIZE + BROTLI_IMPLICIT_ZEROES)
#define BROTLI_IBUF_MASK (BROTLI_READ_SIZE - 1)
#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
/* Masking with this expression turns to a single "Unsigned Bit Field Extract"
UBFX instruction on ARM. */
static BROTLI_INLINE uint32_t BitMask(int n) { return ~((0xffffffff) << n); }
static const uint32_t kBitMask[33] = { 0x0000,
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
};
static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
if (IS_CONSTANT(n) || BROTLI_HAS_UBFX) {
/* Masking with this expression turns to a single
"Unsigned Bit Field Extract" UBFX instruction on ARM. */
return ~((0xffffffffU) << n);
} else {
return kBitMask[n];
}
}
typedef struct {
#if (BROTLI_64_BITS_LITTLE_ENDIAN)
uint64_t val_; /* pre-fetched bits */
#else
uint32_t val_; /* pre-fetched bits */
#endif
reg_t val_; /* pre-fetched bits */
uint32_t bit_pos_; /* current bit-reading position in val_ */
uint8_t* next_in; /* the byte we're reading from */
uint32_t avail_in;
int eos_; /* input stream is finished */
BrotliInput input_; /* input callback */
/* Input byte buffer, consist of a ringbuffer and a "slack" region where */
/* bytes from the start of the ringbuffer are copied. */
uint8_t buf_[BROTLI_IBUF_SIZE];
const uint8_t* next_in; /* the byte we're reading from */
size_t avail_in;
} BrotliBitReader;
typedef struct {
reg_t val_;
uint32_t bit_pos_;
const uint8_t* next_in;
size_t avail_in;
} BrotliBitReaderState;
/* Initializes the bitreader fields. */
void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input);
void BrotliInitBitReader(BrotliBitReader* const br);
/* Ensures that accumulator is not empty. May consume one byte of input.
Returns 0 if data is required but there is no input available.
For BROTLI_BUILD_PORTABLE this function also prepares bit reader for aligned
reading. */
int BrotliWarmupBitReader(BrotliBitReader* const br);
static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br);
/* Pulls data from the input to the the read buffer.
Returns 0 if one of:
- the input callback returned an error, or
- there is no more input and the position is past the end of the stream.
- finish is false and less than BROTLI_READ_SIZE are available - a next call
when more data is available makes it continue including the partially read
data
static BROTLI_INLINE void BrotliBitReaderSaveState(
BrotliBitReader* const from, BrotliBitReaderState* to) {
to->val_ = from->val_;
to->bit_pos_ = from->bit_pos_;
to->next_in = from->next_in;
to->avail_in = from->avail_in;
}
If finish is true and the end of the stream is reached,
BROTLI_IMPLICIT_ZEROES additional zero bytes are copied to the ringbuffer.
*/
static BROTLI_INLINE int BrotliReadInput(
BrotliBitReader* const br, int finish) {
if (PREDICT_FALSE(br->eos_)) {
return 0;
} else {
size_t i;
int bytes_read;
if (br->next_in != br->buf_) {
for (i = 0; i < br->avail_in; i++) {
br->buf_[i] = br->next_in[i];
}
br->next_in = br->buf_;
}
bytes_read = BrotliRead(br->input_, br->next_in + br->avail_in,
(size_t)(BROTLI_READ_SIZE - br->avail_in));
if (bytes_read < 0) {
return 0;
}
br->avail_in += (uint32_t)bytes_read;
if (br->avail_in < BROTLI_READ_SIZE) {
if (!finish) {
return 0;
}
br->eos_ = 1;
/* Store BROTLI_IMPLICIT_ZEROES bytes of zero after the stream end. */
memset(br->next_in + br->avail_in, 0, BROTLI_IMPLICIT_ZEROES);
br->avail_in += BROTLI_IMPLICIT_ZEROES;
}
return 1;
}
static BROTLI_INLINE void BrotliBitReaderRestoreState(
BrotliBitReader* const to, BrotliBitReaderState* from) {
to->val_ = from->val_;
to->bit_pos_ = from->bit_pos_;
to->next_in = from->next_in;
to->avail_in = from->avail_in;
}
static BROTLI_INLINE uint32_t BrotliGetAvailableBits(
const BrotliBitReader* br) {
return (BROTLI_64_BITS ? 64 : 32) - br->bit_pos_;
}
/* Returns amount of unread bytes the bit reader still has buffered from the
BrotliInput, including whole bytes in br->val_. */
static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
size_t result = br->avail_in + sizeof(br->val_) - (br->bit_pos_ >> 3);
if (!br->eos_) {
return result;
}
if (result <= BROTLI_IMPLICIT_ZEROES) {
return 0;
}
return result - BROTLI_IMPLICIT_ZEROES;
return br->avail_in + (BrotliGetAvailableBits(br) >> 3);
}
/* Checks if there is at least num bytes left in the input ringbuffer (excluding
the bits remaining in br->val_). The maximum value for num is
BROTLI_IMPLICIT_ZEROES bytes. */
the bits remaining in br->val_). */
static BROTLI_INLINE int BrotliCheckInputAmount(
BrotliBitReader* const br, size_t num) {
return br->avail_in >= num;
}
static BROTLI_INLINE uint16_t BrotliLoad16LE(const uint8_t* in) {
if (BROTLI_LITTLE_ENDIAN) {
return *((const uint16_t*)in);
} else if (BROTLI_BIG_ENDIAN) {
uint16_t value = *((const uint16_t*)in);
return (uint16_t)(
((value & 0xFFU) << 8) |
((value & 0xFF00U) >> 8));
} else {
return (uint16_t)(in[0] | (in[1] << 8));
}
}
static BROTLI_INLINE uint32_t BrotliLoad32LE(const uint8_t* in) {
if (BROTLI_LITTLE_ENDIAN) {
return *((const uint32_t*)in);
} else if (BROTLI_BIG_ENDIAN) {
uint32_t value = *((const uint32_t*)in);
return ((value & 0xFFU) << 24) | ((value & 0xFF00U) << 8) |
((value & 0xFF0000U) >> 8) | ((value & 0xFF000000U) >> 24);
} else {
uint32_t value = (uint32_t)(*(in++));
value |= (uint32_t)(*(in++)) << 8;
value |= (uint32_t)(*(in++)) << 16;
value |= (uint32_t)(*(in++)) << 24;
return value;
}
}
#if (BROTLI_64_BITS)
static BROTLI_INLINE uint64_t BrotliLoad64LE(const uint8_t* in) {
if (BROTLI_LITTLE_ENDIAN) {
return *((const uint64_t*)in);
} else if (BROTLI_BIG_ENDIAN) {
uint64_t value = *((const uint64_t*)in);
return
((value & 0xFFU) << 56) |
((value & 0xFF00U) << 40) |
((value & 0xFF0000U) << 24) |
((value & 0xFF000000U) << 8) |
((value & 0xFF00000000U) >> 8) |
((value & 0xFF0000000000U) >> 24) |
((value & 0xFF000000000000U) >> 40) |
((value & 0xFF00000000000000U) >> 56);
} else {
uint64_t value = (uint64_t)(*(in++));
value |= (uint64_t)(*(in++)) << 8;
value |= (uint64_t)(*(in++)) << 16;
value |= (uint64_t)(*(in++)) << 24;
value |= (uint64_t)(*(in++)) << 32;
value |= (uint64_t)(*(in++)) << 40;
value |= (uint64_t)(*(in++)) << 48;
value |= (uint64_t)(*(in++)) << 56;
return value;
}
}
#endif
/* Guarantees that there are at least n_bits + 1 bits in accumulator.
Precondition: accumulator contains at least 1 bit.
n_bits should be in the range [1..24] for regular build. For portable
non-64-bit little endian build only 16 bits are safe to request. */
static BROTLI_INLINE void BrotliFillBitWindow(
BrotliBitReader* const br, int n_bits) {
#if (BROTLI_64_BITS_LITTLE_ENDIAN)
BrotliBitReader* const br, uint32_t n_bits) {
#if (BROTLI_64_BITS)
if (!BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 8)) {
if (br->bit_pos_ >= 56) {
br->val_ >>= 56;
br->bit_pos_ ^= 56; /* here same as -= 56 because of the if condition */
br->val_ |= (*(const uint64_t*)(br->next_in)) << 8;
br->val_ |= BrotliLoad64LE(br->next_in) << 8;
br->avail_in -= 7;
br->next_in += 7;
}
@ -148,7 +181,7 @@ static BROTLI_INLINE void BrotliFillBitWindow(
if (br->bit_pos_ >= 48) {
br->val_ >>= 48;
br->bit_pos_ ^= 48; /* here same as -= 48 because of the if condition */
br->val_ |= (*(const uint64_t*)(br->next_in)) << 16;
br->val_ |= BrotliLoad64LE(br->next_in) << 16;
br->avail_in -= 6;
br->next_in += 6;
}
@ -156,17 +189,17 @@ static BROTLI_INLINE void BrotliFillBitWindow(
if (br->bit_pos_ >= 32) {
br->val_ >>= 32;
br->bit_pos_ ^= 32; /* here same as -= 32 because of the if condition */
br->val_ |= ((uint64_t)(*(const uint32_t*)(br->next_in))) << 32;
br->avail_in -= 4;
br->next_in += 4;
br->val_ |= ((uint64_t)BrotliLoad32LE(br->next_in)) << 32;
br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
}
}
#elif (BROTLI_LITTLE_ENDIAN)
#else
if (!BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 8)) {
if (br->bit_pos_ >= 24) {
br->val_ >>= 24;
br->bit_pos_ ^= 24; /* here same as -= 24 because of the if condition */
br->val_ |= (*(const uint32_t*)(br->next_in)) << 8;
br->val_ |= BrotliLoad32LE(br->next_in) << 8;
br->avail_in -= 3;
br->next_in += 3;
}
@ -174,22 +207,27 @@ static BROTLI_INLINE void BrotliFillBitWindow(
if (br->bit_pos_ >= 16) {
br->val_ >>= 16;
br->bit_pos_ ^= 16; /* here same as -= 16 because of the if condition */
br->val_ |= ((uint32_t)(*(const uint16_t*)(br->next_in))) << 16;
br->avail_in -= 2;
br->next_in += 2;
br->val_ |= ((uint32_t)BrotliLoad16LE(br->next_in)) << 16;
br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
}
}
#else
while (br->bit_pos_ >= 16) {
BrotliPullByte(br);
}
#endif
}
/* Mosltly like BrotliFillBitWindow, but guarantees only 16 bits and reads no
more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */
static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {
BrotliFillBitWindow(br, 17);
}
/* Pulls one byte of input to accumulator. */
static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br) {
static BROTLI_INLINE int BrotliPullByte(BrotliBitReader* const br) {
if (br->avail_in == 0) {
return 0;
}
br->val_ >>= 8;
#if (BROTLI_64_BITS_LITTLE_ENDIAN)
#if (BROTLI_64_BITS)
br->val_ |= ((uint64_t)*br->next_in) << 56;
#else
br->val_ |= ((uint32_t)*br->next_in) << 24;
@ -197,46 +235,79 @@ static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br) {
br->bit_pos_ -= 8;
--br->avail_in;
++br->next_in;
return 1;
}
/* Like BrotliGetBits, but does not mask the result, it is only guaranteed
that it has minimum n_bits. */
static BROTLI_INLINE uint32_t BrotliGetBitsUnmasked(
BrotliBitReader* const br, int n_bits) {
BrotliFillBitWindow(br, n_bits);
return (uint32_t)(br->val_ >> br->bit_pos_);
/* Returns currently available bits.
The number of valid bits could be calclulated by BrotliGetAvailableBits. */
static BROTLI_INLINE reg_t BrotliGetBitsUnmasked(BrotliBitReader* const br) {
return br->val_ >> br->bit_pos_;
}
/* Like BrotliGetBits, but does not mask the result.
The result contains at least 16 valid bits. */
static BROTLI_INLINE uint32_t BrotliGet16BitsUnmasked(
BrotliBitReader* const br) {
BrotliFillBitWindow(br, 16);
return (uint32_t)BrotliGetBitsUnmasked(br);
}
/* Returns the specified number of bits from br without advancing bit pos. */
static BROTLI_INLINE uint32_t BrotliGetBits(
BrotliBitReader* const br, int n_bits) {
BrotliBitReader* const br, uint32_t n_bits) {
BrotliFillBitWindow(br, n_bits);
return (uint32_t)(br->val_ >> br->bit_pos_) & BitMask(n_bits);
return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
}
/* Tries to peek the specified amount of bits. Returns 0, if there is not
enough input. */
static BROTLI_INLINE int BrotliSafeGetBits(
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
while (BrotliGetAvailableBits(br) < n_bits) {
if (!BrotliPullByte(br)) {
return 0;
}
}
*val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
return 1;
}
/* Advances the bit pos by n_bits. */
static BROTLI_INLINE void BrotliDropBits(
BrotliBitReader* const br, int n_bits) {
br->bit_pos_ += (uint32_t)n_bits;
BrotliBitReader* const br, uint32_t n_bits) {
br->bit_pos_ += n_bits;
}
static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {
uint32_t unused_bytes = BrotliGetAvailableBits(br) >> 3;
uint32_t unused_bits = unused_bytes << 3;
br->avail_in += unused_bytes;
br->next_in -= unused_bytes;
if (unused_bits == sizeof(br->val_) << 3) {
br->val_ = 0;
} else {
br->val_ <<= unused_bits;
}
br->bit_pos_ += unused_bits;
}
/* Reads the specified number of bits from br and advances the bit pos.
Precondition: accumulator MUST contain at least n_bits. */
static BROTLI_INLINE void BrotliTakeBits(
BrotliBitReader* const br, int n_bits, uint32_t* val) {
*val = (uint32_t)(br->val_ >> br->bit_pos_) & BitMask(n_bits);
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
*val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
#ifdef BROTLI_DECODE_DEBUG
printf("[BrotliReadBits] %d %d %d val: %6x\n",
(int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val);
#endif
br->bit_pos_ += (uint32_t)n_bits;
BrotliDropBits(br, n_bits);
}
/* Reads the specified number of bits from br and advances the bit pos.
Assumes that there is enough input to perform BrotliFillBitWindow. */
static BROTLI_INLINE uint32_t BrotliReadBits(
BrotliBitReader* const br, int n_bits) {
if (BROTLI_64_BITS_LITTLE_ENDIAN || (n_bits <= 16)) {
BrotliBitReader* const br, uint32_t n_bits) {
if (BROTLI_64_BITS || (n_bits <= 16)) {
uint32_t val;
BrotliFillBitWindow(br, n_bits);
BrotliTakeBits(br, n_bits, &val);
@ -253,14 +324,13 @@ static BROTLI_INLINE uint32_t BrotliReadBits(
}
/* Tries to read the specified amount of bits. Returns 0, if there is not
enough input. */
enough input. n_bits MUST be positive. */
static BROTLI_INLINE int BrotliSafeReadBits(
BrotliBitReader* const br, int n_bits, uint32_t* val) {
while (br->bit_pos_ + (uint32_t)n_bits > (sizeof(br->val_) << 3)) {
if (br->avail_in == 0) {
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
while (BrotliGetAvailableBits(br) < n_bits) {
if (!BrotliPullByte(br)) {
return 0;
}
BrotliPullByte(br);
}
BrotliTakeBits(br, n_bits, val);
return 1;
@ -269,7 +339,7 @@ static BROTLI_INLINE int BrotliSafeReadBits(
/* Advances the bit reader position to the next byte boundary and verifies
that any skipped bits are set to zero. */
static BROTLI_INLINE int BrotliJumpToByteBoundary(BrotliBitReader* br) {
int pad_bits_count = (64 - (int)br->bit_pos_) & 0x7;
uint32_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;
uint32_t pad_bits = 0;
if (pad_bits_count != 0) {
BrotliTakeBits(br, pad_bits_count, &pad_bits);
@ -280,16 +350,15 @@ static BROTLI_INLINE int BrotliJumpToByteBoundary(BrotliBitReader* br) {
/* 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, int offset) {
int bytes_left = (int)(sizeof(br->val_) - (br->bit_pos_ >> 3));
if (br->bit_pos_ & 7) {
return -1;
}
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 (br->val_ >> (br->bit_pos_ + (unsigned)(offset << 3))) & 0xFF;
return (BrotliGetBitsUnmasked(br) >> (unsigned)(offset << 3)) & 0xFF;
}
offset -= bytes_left;
if (offset < (long)br->avail_in) {
if (offset < br->avail_in) {
return br->next_in[offset];
}
return -1;
@ -300,30 +369,17 @@ static BROTLI_INLINE int BrotliPeekByte(BrotliBitReader* br, int offset) {
warmed up again after this. */
static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
BrotliBitReader* br, size_t num) {
while (br->bit_pos_ + 8 <= (BROTLI_64_BITS_LITTLE_ENDIAN ? 64 : 32)
&& num > 0) {
*dest = (uint8_t)(br->val_ >> br->bit_pos_);
br->bit_pos_ += 8;
while (BrotliGetAvailableBits(br) >= 8 && num > 0) {
*dest = (uint8_t)BrotliGetBitsUnmasked(br);
BrotliDropBits(br, 8);
++dest;
--num;
}
memcpy(dest, br->next_in, num);
br->avail_in -= (uint32_t)num;
br->avail_in -= num;
br->next_in += num;
}
/* Checks that bit reader hasn't read after the end of input.
Returns 0 if bit reader has used implicit zeroes after the end of input. */
static BROTLI_INLINE int BrotliIsBitReaderOK(BrotliBitReader* br) {
size_t remaining_bytes =
br->avail_in + sizeof(br->val_) - (br->bit_pos_ >> 3);
return !br->eos_ || (remaining_bytes >= BROTLI_IMPLICIT_ZEROES);
}
#undef BROTLI_IMPLICIT_ZEROES
#undef BROTLI_IBUF_SIZE
#undef BROTLI_IBUF_MASK
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Lookup table to map the previous two bytes to a context id.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* API for Brotli decompression */
@ -19,7 +10,6 @@
#define BROTLI_DEC_DECODE_H_
#include "./state.h"
#include "./streams.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
@ -27,133 +17,78 @@ extern "C" {
#endif
typedef enum {
/* Decoding error, e.g. corrupt input or no memory */
/* Decoding error, e.g. corrupt input or memory allocation problem */
BROTLI_RESULT_ERROR = 0,
/* Successfully completely done */
/* Decoding successfully completed */
BROTLI_RESULT_SUCCESS = 1,
/* Partially done, but must be called again with more input */
/* Partially done; should be called again with more input */
BROTLI_RESULT_NEEDS_MORE_INPUT = 2,
/* Partially done, but must be called again with more output */
/* Partially done; should be called again with more output */
BROTLI_RESULT_NEEDS_MORE_OUTPUT = 3
} BrotliResult;
/* BROTLI_FAILURE macro unwraps to BROTLI_RESULT_ERROR in non-debug build. */
/* In debug build it dumps file name, line and pretty function name. */
#if defined(_MSC_VER) || !defined(BROTLI_DEBUG)
#define BROTLI_FAILURE() BROTLI_RESULT_ERROR
#else
#define BROTLI_FAILURE() \
BrotliFailure(__FILE__, __LINE__, __PRETTY_FUNCTION__)
static inline BrotliResult BrotliFailure(const char *f, int l, const char *fn) {
fprintf(stderr, "ERROR at %s:%d (%s)\n", f, l, fn);
fflush(stderr);
return BROTLI_RESULT_ERROR;
}
#endif
/* Creates the instance of BrotliState and initializes it. |alloc_func| and
|free_func| MUST be both zero or both non-zero. In the case they are both
zero, default memory allocators are used. |opaque| is passed to |alloc_func|
and |free_func| when they are called. */
BrotliState* BrotliCreateState(
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
/* 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. */
/* Deinitializes and frees BrotliState instance. */
void BrotliDestroyState(BrotliState* state);
/* 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);
/* 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. */
/* Decompresses the data in |encoded_buffer| into |decoded_buffer|, and sets
|*decoded_size| to the decompressed length. */
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. */
BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output);
/* Decompresses the data. Supports partial input and 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
BrotliStateInit and reused with every call for the same stream.
Return values:
0: failure.
1: success, and done.
2: success so far, end not reached so should call again with more input.
The finish parameter is used as follows, for a series of calls with the
same state:
0: Every call except the last one must be called with finish set to 0. The
last call may have finish set to either 0 or 1. Only if finish is 0, can
the function return 2. It may also return 0 or 1, in that case no more
calls (even with finish 1) may be made.
1: Only the last call may have finish set to 1. It's ok to give empty input
if all input was already given to previous calls. It is also ok to have
only one single call in total, with finish 1, and with all input
available immediately. That matches the non-streaming case. If finish is
1, the function can only return 0 or 1, never 2. After a finish, no more
calls may be done.
After everything is done, the state must be cleaned with BrotliStateCleanup
to free allocated resources.
The given BrotliOutput must always accept all output and make enough space,
it returning a smaller value than the amount of bytes to write always results
in an error.
*/
BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output,
int finish, BrotliState* s);
Must be called with an allocated input buffer in |*next_in| and an allocated
output buffer in |*next_out|. The values |*available_in| and |*available_out|
must specify the allocated size in |*next_in| and |*next_out| respectively.
/* Same as above, but with memory buffers.
Must be called with an allocated input buffer in *next_in and an allocated
output buffer in *next_out. The values *available_in and *available_out
must specify the allocated size in *next_in and *next_out respectively.
The value *total_out must be 0 initially, and will be summed with the
amount of output bytes written after each call, so that at the end it
gives the complete decoded size.
After each call, *available_in will be decremented by the amount of input
bytes consumed, and the *next_in pointer will be incremented by that amount.
Similarly, *available_out will be decremented by the amount of output
bytes written, and the *next_out pointer will be incremented by that
amount.
After each call, |*available_in| will be decremented by the amount of input
bytes consumed, and the |*next_in| pointer will be incremented by that
amount. Similarly, |*available_out| will be decremented by the amount of
output bytes written, and the |*next_out| pointer will be incremented by that
amount. |total_out| will be set to the number of bytes decompressed since
last state initialization.
The input may be partial. With each next function call, *next_in and
*available_in must be updated to point to a next part of the compressed
input. The current implementation will always consume all input unless
an error occurs, so normally *available_in will always be 0 after
calling this function and the next adjacent part of input is desired.
In the current implementation, the function requires that there is enough
output buffer size to write all currently processed input, so
*available_out must be large enough. Since the function updates *next_out
each time, as long as the output buffer is large enough you can keep
reusing this variable. It is also possible to update *next_out and
*available_out yourself before a next call, e.g. to point to a new larger
buffer.
*/
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);
Input is never overconsumed, so |next_in| and |available_in| could be passed
to the next consumer after decoding is complete. */
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);
/* Fills the new state with a dictionary for LZ77, warming up the ringbuffer,
e.g. for custom static dictionaries for data formats.
Not to be confused with the built-in transformable dictionary of Brotli.
The dictionary must exist in memory until decoding is done and is owned by
the caller. To use:
-initialize state with BrotliStateInit
-use BrotliSetCustomDictionary
-use BrotliDecompressBufferStreaming
-clean up with BrotliStateCleanup
1) initialize state with BrotliStateInit
2) use BrotliSetCustomDictionary
3) use BrotliDecompressStream
4) clean up with BrotliStateCleanup
*/
void BrotliSetCustomDictionary(
size_t size, const uint8_t* dict, BrotliState* s);
/* Escalate internal functions visibility; for testing purposes only. */
void InverseMoveToFrontTransformForTesting(uint8_t* v, int l, BrotliState* s);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif

Просмотреть файл

@ -1,20 +1,15 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
#include "./dictionary.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* In case of multiple definition linker error with dictionary.cc from the
encoder: include only one of enc/dictionary.cc or dec/dictionary.c in a
target using both enc and dec. */
@ -9465,3 +9460,7 @@ const uint8_t kBrotliDictionary[122784] = {
0x88, 0xe0, 0xa4, 0xb8, 0xe0, 0xa4, 0x95, 0xe0, 0xa5, 0x8d, 0xe0, 0xa4, 0xb0,
0xe0, 0xa4, 0xbf, 0xe0, 0xa4, 0xaf, 0xe0, 0xa4, 0xa4, 0xe0, 0xa4, 0xbe,
};
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Collection of static dictionary words. */
@ -26,13 +17,13 @@ extern "C" {
extern const uint8_t kBrotliDictionary[122784];
static const int kBrotliDictionaryOffsetsByLength[] = {
static const uint32_t kBrotliDictionaryOffsetsByLength[] = {
0, 0, 0, 0, 0, 4096, 9216, 21504, 35840, 44032,
53248, 63488, 74752, 87040, 93696, 100864, 104704, 106752, 108928, 113536,
115968, 118528, 119872, 121280, 122016,
};
static const int8_t kBrotliDictionarySizeBitsByLength[] = {
static const uint8_t kBrotliDictionarySizeBitsByLength[] = {
0, 0, 0, 0, 10, 10, 11, 11, 10, 10,
10, 10, 10, 9, 9, 8, 7, 7, 8, 7,
7, 6, 6, 5, 5,

Просмотреть файл

@ -1,41 +1,75 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Utilities for building Huffman decoding tables. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "./huffman.h"
#include <string.h> /* memcpy, memset */
#include "./port.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/* Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the
bit-wise reversal of the len least significant bits of key. */
static BROTLI_INLINE uint32_t GetNextKey(uint32_t key, int len) {
#define BROTLI_REVERSE_BITS_MAX 8
#ifdef BROTLI_RBIT
return BROTLI_RBIT(BROTLI_RBIT(key) + (1 << (8 * sizeof(unsigned) - len)));
#define BROTLI_REVERSE_BITS_BASE (32 - BROTLI_REVERSE_BITS_MAX)
#else
unsigned step = (unsigned)(1 << (len - 1));
while (key & step) {
step >>= 1;
}
return (key & (step - 1)) + step;
#define BROTLI_REVERSE_BITS_BASE 0
static uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
#endif /* BROTLI_RBIT */
#define BROTLI_REVERSE_BITS_LOWEST \
(1U << (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) {
#ifdef BROTLI_RBIT
return BROTLI_RBIT(num);
#else
return kReverseBits[num];
#endif
}
@ -71,7 +105,8 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
uint16_t *count) {
HuffmanCode code; /* current table entry */
int symbol; /* symbol index in original or sorted table */
unsigned key; /* reversed prefix code */
uint32_t key; /* prefix code */
uint32_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[18]; /* symbols sorted by code length */
@ -79,6 +114,8 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1];
int bits;
int bits_count;
BROTLI_DCHECK(
BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <= BROTLI_REVERSE_BITS_MAX);
/* generate offsets into sorted symbol table by code length */
symbol = -1;
@ -106,7 +143,7 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
if (offset[0] == 0) {
code.bits = 0;
code.value = (uint16_t)sorted[0];
for (key = 0; key < table_size; ++key) {
for (key = 0; key < (uint32_t)table_size; ++key) {
table[key] = code;
}
return;
@ -114,6 +151,7 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
/* fill in table */
key = 0;
key_step = BROTLI_REVERSE_BITS_LOWEST;
symbol = 0;
bits = 1;
step = 2;
@ -121,25 +159,27 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
code.bits = (uint8_t)bits;
for (bits_count = count[bits]; bits_count != 0; --bits_count) {
code.value = (uint16_t)sorted[symbol++];
ReplicateValue(&table[key], step, table_size, code);
key = GetNextKey(key, bits);
ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
key += key_step;
}
step <<= 1;
key_step >>= 1;
} while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
}
int BrotliBuildHuffmanTable(HuffmanCode* root_table,
int root_bits,
const uint16_t* const symbol_lists,
uint16_t *count) {
uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
int root_bits,
const uint16_t* const symbol_lists,
uint16_t *count) {
HuffmanCode code; /* current table entry */
HuffmanCode* table; /* next available space in table */
int len; /* current code length */
int symbol; /* symbol index in original or sorted table */
unsigned key; /* reversed prefix code */
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 */
int step; /* step size to replicate values in current table */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low bits */
int table_bits; /* key length of current table */
int table_size; /* size of current table */
int total_size; /* sum of root table size and 2nd level table sizes */
@ -147,6 +187,10 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
int bits;
int bits_count;
BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX);
BROTLI_DCHECK(
BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <= BROTLI_REVERSE_BITS_MAX);
while (symbol_lists[max_length] == 0xFFFF) max_length--;
max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1;
@ -163,6 +207,7 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
table_size = 1 << table_bits;
}
key = 0;
key_step = BROTLI_REVERSE_BITS_LOWEST;
bits = 1;
step = 2;
do {
@ -171,10 +216,11 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
for (bits_count = count[bits]; bits_count != 0; --bits_count) {
symbol = symbol_lists[symbol];
code.value = (uint16_t)symbol;
ReplicateValue(&table[key], step, table_size, code);
key = GetNextKey(key, bits);
ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
key += key_step;
}
step <<= 1;
key_step >>= 1;
} while (++bits <= table_bits);
/* if root_bits != table_bits we only created one fraction of the */
@ -186,37 +232,43 @@ int BrotliBuildHuffmanTable(HuffmanCode* root_table,
}
/* fill in 2nd level tables and add pointers to root table */
mask = (unsigned)(total_size - 1);
low = (unsigned)-1;
for (len = root_bits + 1, step = 2; len <= max_length; ++len, step <<= 1) {
key_step = BROTLI_REVERSE_BITS_LOWEST >> (root_bits - 1);
sub_key = (BROTLI_REVERSE_BITS_LOWEST << 1);
sub_key_step = BROTLI_REVERSE_BITS_LOWEST;
for (len = root_bits + 1, step = 2; len <= max_length; ++len) {
symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
for (; count[len] != 0; --count[len]) {
if ((key & mask) != low) {
if (sub_key == (BROTLI_REVERSE_BITS_LOWEST << 1U)) {
table += table_size;
table_bits = NextTableBitSize(count, len, root_bits);
table_size = 1 << table_bits;
total_size += table_size;
low = key & mask;
root_table[low].bits = (uint8_t)(table_bits + root_bits);
root_table[low].value = (uint16_t)(
((size_t)(table - root_table)) - low);
sub_key = BrotliReverseBits(key);
key += key_step;
root_table[sub_key].bits = (uint8_t)(table_bits + root_bits);
root_table[sub_key].value = (uint16_t)(
((size_t)(table - root_table)) - sub_key);
sub_key = 0;
}
code.bits = (uint8_t)(len - root_bits);
symbol = symbol_lists[symbol];
code.value = (uint16_t)symbol;
ReplicateValue(&table[key >> root_bits], step, table_size, code);
key = GetNextKey(key, len);
ReplicateValue(
&table[BrotliReverseBits(sub_key)], step, table_size, code);
sub_key += sub_key_step;
}
step <<= 1;
sub_key_step >>= 1;
}
return total_size;
return (uint32_t)total_size;
}
int BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
int root_bits,
uint16_t *val,
uint32_t num_symbols) {
int table_size = 1;
const int goal_size = 1 << root_bits;
uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
int root_bits,
uint16_t *val,
uint32_t num_symbols) {
uint32_t table_size = 1;
const uint32_t goal_size = 1U << root_bits;
switch (num_symbols) {
case 0:
table[0].bits = 0;
@ -302,25 +354,6 @@ int BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
return goal_size;
}
void BrotliHuffmanTreeGroupInit(HuffmanTreeGroup* group, int alphabet_size,
int ntrees) {
/* Pack two mallocs into one */
const size_t code_size =
sizeof(HuffmanCode) * (size_t)(ntrees * BROTLI_HUFFMAN_MAX_TABLE_SIZE);
const size_t htree_size = sizeof(HuffmanCode*) * (size_t)ntrees;
char *p = (char*)malloc(code_size + htree_size);
group->alphabet_size = (int16_t)alphabet_size;
group->num_htrees = (int16_t)ntrees;
group->codes = (HuffmanCode*)p;
group->htrees = (HuffmanCode**)(p + code_size);
}
void BrotliHuffmanTreeGroupRelease(HuffmanTreeGroup* group) {
if (group->codes) {
free(group->codes);
}
}
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Utilities for building Huffman decoding tables. */
@ -29,9 +20,14 @@ extern "C" {
/* For current format this constant equals to kNumInsertAndCopyCodes */
#define BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE 704
/* Maximum possible Huffman table size for an alphabet size of 704, max code
* length 15 and root table bits 8. */
#define BROTLI_HUFFMAN_MAX_TABLE_SIZE 1080
/* Maximum possible Huffman table size for an alphabet size of (index * 32),
* max code length 15 and root table bits 8. */
static const uint16_t kMaxHuffmanTableSize[] = {
256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
854, 886, 920, 952, 984, 1016, 1048, 1080};
#define BROTLI_HUFFMAN_MAX_SIZE_26 396
#define BROTLI_HUFFMAN_MAX_SIZE_258 632
#define BROTLI_HUFFMAN_MAX_SIZE_272 646
#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5
@ -48,32 +44,28 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
/* Builds Huffman lookup table assuming code lengths are in symbol order. */
/* Returns size of resulting table. */
int BrotliBuildHuffmanTable(HuffmanCode* root_table,
int root_bits,
const uint16_t* const symbol_lists,
uint16_t *count_arg);
uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
int root_bits,
const uint16_t* const symbol_lists,
uint16_t *count_arg);
/* Builds a simple Huffman table. The num_symbols parameter is to be */
/* interpreted as follows: 0 means 1 symbol, 1 means 2 symbols, 2 means 3 */
/* symbols, 3 means 4 symbols with lengths 2,2,2,2, 4 means 4 symbols with */
/* lengths 1,2,3,3. */
int BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
int root_bits,
uint16_t *symbols,
uint32_t num_symbols);
uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
int root_bits,
uint16_t *symbols,
uint32_t num_symbols);
/* Contains a collection of Huffman trees with the same alphabet size. */
typedef struct {
HuffmanCode** htrees;
HuffmanCode* codes;
int16_t alphabet_size;
int16_t num_htrees;
uint16_t alphabet_size;
uint16_t num_htrees;
} HuffmanTreeGroup;
void BrotliHuffmanTreeGroupInit(HuffmanTreeGroup* group,
int alphabet_size, int ntrees);
void BrotliHuffmanTreeGroupRelease(HuffmanTreeGroup* group);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */
#endif

Просмотреть файл

@ -1,21 +1,19 @@
/* Copyright 2015 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Macros for compiler / platform specific features and build options.
Build options are:
* BROTLI_BUILD_32_BIT disables 64-bit optimizations
* BROTLI_BUILD_64_BIT forces to use 64-bit optimizations
* BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations
* BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations
* BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations
* BROTLI_BUILD_MODERN_COMPILER forces to use modern compilers built-ins,
features and attributes
* BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
read and overlapping memcpy; this reduces decompression speed by 5%
* BROTLI_DEBUG dumps file name and line number when decoder detects stream
@ -41,15 +39,64 @@
#define __has_feature(x) 0
#endif
#ifdef BROTLI_BUILD_PORTABLE
#define BROTLI_ALIGNED_READ 1
#define BROTLI_SAFE_MEMMOVE 1
#else
#define BROTLI_ALIGNED_READ 0
#define BROTLI_SAFE_MEMMOVE 0
#if defined(__sparc)
#define BROTLI_TARGET_SPARC
#endif
#define BROTLI_ASAN_BUILD __has_feature(address_sanitizer)
#if defined(__arm__) || defined(__thumb__) || \
defined(_M_ARM) || defined(_M_ARMT)
#define BROTLI_TARGET_ARM
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) || \
(defined(M_ARM) && (M_ARM >= 7))
#define BROTLI_TARGET_ARMV7
#endif /* ARMv7 */
#if defined(__aarch64__)
#define BROTLI_TARGET_ARMV8
#endif /* ARMv8 */
#endif /* ARM */
#if defined(__x86_64__) || defined(_M_X64)
#define BROTLI_TARGET_X64
#endif
#if defined(__PPC64__)
#define BROTLI_TARGET_POWERPC64
#endif
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
#define BROTLI_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
#define BROTLI_GCC_VERSION 0
#endif
#if defined(__ICC)
#define BROTLI_ICC_VERSION __ICC
#else
#define BROTLI_ICC_VERSION 0
#endif
#if defined(BROTLI_BUILD_MODERN_COMPILER)
#define BROTLI_MODERN_COMPILER 1
#elif (BROTLI_GCC_VERSION > 300) || (BROTLI_ICC_VERSION >= 1600)
#define BROTLI_MODERN_COMPILER 1
#else
#define BROTLI_MODERN_COMPILER 0
#endif
/* SPARC and ARMv6 don't support unaligned read.
Choose portable build for them. */
#if !defined(BROTLI_BUILD_PORTABLE)
#if defined(BROTLI_TARGET_SPARC) || \
(defined(BROTLI_TARGET_ARM) && !defined(BROTLI_TARGET_ARMV7))
#define BROTLI_BUILD_PORTABLE
#endif /* SPARK or ARMv6 */
#endif /* portable build */
#ifdef BROTLI_BUILD_PORTABLE
#define BROTLI_ALIGNED_READ 1
#else
#define BROTLI_ALIGNED_READ 0
#endif
/* Define "PREDICT_TRUE" and "PREDICT_FALSE" macros for capable compilers.
@ -68,8 +115,7 @@ OR:
}
*/
#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \
(defined(__llvm__) && __has_builtin(__builtin_expect))
#if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_expect)
#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
#else
@ -78,15 +124,13 @@ OR:
#endif
/* IS_CONSTANT macros returns true for compile-time constant expressions. */
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \
(defined(__llvm__) && __has_builtin(__builtin_constant_p))
#if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_constant_p)
#define IS_CONSTANT(x) __builtin_constant_p(x)
#else
#define IS_CONSTANT(x) 0
#endif
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \
(defined(__llvm__) && __has_attribute(always_inline))
#if BROTLI_MODERN_COMPILER || __has_attribute(always_inline)
#define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
#else
#define ATTRIBUTE_ALWAYS_INLINE
@ -109,49 +153,56 @@ OR:
#define BROTLI_DCHECK(x)
#endif
#if (defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || \
defined(__PPC64__))
#if defined(BROTLI_BUILD_64_BIT)
#define BROTLI_64_BITS 1
#elif defined(BROTLI_BUILD_32_BIT)
#define BROTLI_64_BITS 0
#elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \
defined(BROTLI_TARGET_POWERPC64)
#define BROTLI_64_BITS 1
#else
#define BROTLI_64_BITS 0
#endif
#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
#if defined(BROTLI_BUILD_BIG_ENDIAN)
#define BROTLI_LITTLE_ENDIAN 0
#define BROTLI_BIG_ENDIAN 1
#elif defined(BROTLI_BUILD_LITTLE_ENDIAN)
#define BROTLI_LITTLE_ENDIAN 1
#define BROTLI_BIG_ENDIAN 0
#elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL)
#define BROTLI_LITTLE_ENDIAN 0
#define BROTLI_BIG_ENDIAN 0
#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define BROTLI_LITTLE_ENDIAN 1
#define BROTLI_BIG_ENDIAN 0
#elif defined(_WIN32)
/* Win32 can currently always be assumed to be little endian */
#define BROTLI_LITTLE_ENDIAN 1
#define BROTLI_BIG_ENDIAN 0
#else
#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#define BROTLI_BIG_ENDIAN 1
#else
#define BROTLI_BIG_ENDIAN 0
#endif
#define BROTLI_LITTLE_ENDIAN 0
#endif
#if (BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN)
#define BROTLI_64_BITS_LITTLE_ENDIAN 1
#else
#define BROTLI_64_BITS_LITTLE_ENDIAN 0
#endif
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || \
(defined(__llvm__) && __has_attribute(noinline))
#if BROTLI_MODERN_COMPILER || __has_attribute(noinline)
#define BROTLI_NOINLINE __attribute__ ((noinline))
#else
#define BROTLI_NOINLINE
#endif
#if BROTLI_ASAN_BUILD && !defined(BROTLI_BUILD_PORTABLE)
#define BROTLI_NO_ASAN __attribute__((no_sanitize("address"))) BROTLI_NOINLINE
#else
#define BROTLI_NO_ASAN
#endif
#define BROTLI_REPEAT(N, X) { \
if ((N & 1) != 0) {X;} \
if ((N & 2) != 0) {X; X;} \
if ((N & 4) != 0) {X; X; X; X;} \
}
#if (__GNUC__ > 2) || defined(__llvm__)
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
#if BROTLI_MODERN_COMPILER || defined(__llvm__)
#if defined(BROTLI_TARGET_ARMV7)
static BROTLI_INLINE unsigned BrotliRBit(unsigned input) {
unsigned output;
__asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
@ -161,4 +212,19 @@ static BROTLI_INLINE unsigned BrotliRBit(unsigned input) {
#endif /* armv7 */
#endif /* gcc || clang */
#if defined(BROTLI_TARGET_ARM)
#define BROTLI_HAS_UBFX 1
#else
#define BROTLI_HAS_UBFX 0
#endif
#define BROTLI_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
#define BROTLI_FREE(S, X) { \
S->free_func(S->memory_manager_opaque, X); \
X = NULL; \
}
#define BROTLI_UNUSED(X) (void)(X)
#endif /* BROTLI_DEC_PORT_H_ */

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Lookup tables to map prefix codes to value ranges. This is used during
@ -20,11 +11,13 @@
#ifndef BROTLI_DEC_PREFIX_H_
#define BROTLI_DEC_PREFIX_H_
#include "./types.h"
/* Represents the range of values belonging to a prefix code: */
/* [offset, offset + 2^nbits) */
struct PrefixCodeRange {
int16_t offset;
int8_t nbits;
uint16_t offset;
uint8_t nbits;
};
static const struct PrefixCodeRange kBlockLengthPrefixCode[] = {

Просмотреть файл

@ -1,29 +1,47 @@
/* Copyright 2015 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
#include "./huffman.h"
#include "./state.h"
#include <stdlib.h>
#include <string.h>
#include <stdlib.h> /* free, malloc */
#include "./huffman.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static void* DefaultAllocFunc(void* opaque, size_t size) {
BROTLI_UNUSED(opaque);
return malloc(size);
}
static void DefaultFreeFunc(void* opaque, void* address) {
BROTLI_UNUSED(opaque);
free(address);
}
void BrotliStateInit(BrotliState* s) {
BrotliStateInitWithCustomAllocators(s, 0, 0, 0);
}
void BrotliStateInitWithCustomAllocators(BrotliState* s,
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
if (!alloc_func) {
s->alloc_func = DefaultAllocFunc;
s->free_func = DefaultFreeFunc;
s->memory_manager_opaque = 0;
} else {
s->alloc_func = alloc_func;
s->free_func = free_func;
s->memory_manager_opaque = opaque;
}
BrotliInitBitReader(&s->br);
s->state = BROTLI_STATE_UNINITED;
s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
@ -31,6 +49,13 @@ void BrotliStateInit(BrotliState* s) {
s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
s->buffer_length = 0;
s->loop_counter = 0;
s->pos = 0;
s->rb_roundtrips = 0;
s->partial_pos_out = 0;
s->block_type_trees = NULL;
s->block_len_trees = NULL;
@ -42,6 +67,8 @@ void BrotliStateInit(BrotliState* s) {
s->context_map_slice = NULL;
s->dist_context_map_slice = NULL;
s->sub_loop_counter = 0;
s->literal_hgroup.codes = NULL;
s->literal_hgroup.htrees = NULL;
s->insert_copy_hgroup.codes = NULL;
@ -72,9 +99,9 @@ void BrotliStateInit(BrotliState* s) {
void BrotliStateMetablockBegin(BrotliState* s) {
s->meta_block_remaining_len = 0;
s->block_length[0] = 1 << 28;
s->block_length[1] = 1 << 28;
s->block_length[2] = 1 << 28;
s->block_length[0] = 1U << 28;
s->block_length[1] = 1U << 28;
s->block_length[2] = 1U << 28;
s->num_block_types[0] = 1;
s->num_block_types[1] = 1;
s->num_block_types[2] = 1;
@ -103,50 +130,47 @@ void BrotliStateMetablockBegin(BrotliState* s) {
}
void BrotliStateCleanupAfterMetablock(BrotliState* s) {
if (s->context_modes != 0) {
free(s->context_modes);
s->context_modes = NULL;
}
if (s->context_map != 0) {
free(s->context_map);
s->context_map = NULL;
}
if (s->dist_context_map != 0) {
free(s->dist_context_map);
s->dist_context_map = NULL;
}
BROTLI_FREE(s, s->context_modes);
BROTLI_FREE(s, s->context_map);
BROTLI_FREE(s, s->dist_context_map);
BrotliHuffmanTreeGroupRelease(&s->literal_hgroup);
BrotliHuffmanTreeGroupRelease(&s->insert_copy_hgroup);
BrotliHuffmanTreeGroupRelease(&s->distance_hgroup);
s->literal_hgroup.codes = NULL;
s->literal_hgroup.htrees = NULL;
s->insert_copy_hgroup.codes = NULL;
s->insert_copy_hgroup.htrees = NULL;
s->distance_hgroup.codes = NULL;
s->distance_hgroup.htrees = NULL;
BrotliHuffmanTreeGroupRelease(s, &s->literal_hgroup);
BrotliHuffmanTreeGroupRelease(s, &s->insert_copy_hgroup);
BrotliHuffmanTreeGroupRelease(s, &s->distance_hgroup);
}
void BrotliStateCleanup(BrotliState* s) {
if (s->context_modes != 0) {
free(s->context_modes);
}
if (s->context_map != 0) {
free(s->context_map);
}
if (s->dist_context_map != 0) {
free(s->dist_context_map);
}
BrotliHuffmanTreeGroupRelease(&s->literal_hgroup);
BrotliHuffmanTreeGroupRelease(&s->insert_copy_hgroup);
BrotliHuffmanTreeGroupRelease(&s->distance_hgroup);
BrotliStateCleanupAfterMetablock(s);
if (s->ringbuffer != 0) {
free(s->ringbuffer);
}
if (s->block_type_trees != 0) {
free(s->block_type_trees);
}
BROTLI_FREE(s, s->ringbuffer);
BROTLI_FREE(s, s->block_type_trees);
}
int BrotliStateIsStreamStart(const BrotliState* s) {
return (s->state == BROTLI_STATE_UNINITED &&
BrotliGetAvailableBits(&s->br) == 0);
}
int BrotliStateIsStreamEnd(const BrotliState* s) {
return s->state == BROTLI_STATE_DONE;
}
void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group,
uint32_t alphabet_size, uint32_t ntrees) {
/* Pack two allocations into one */
const size_t max_table_size = kMaxHuffmanTableSize[(alphabet_size + 31) >> 5];
const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
char *p = (char*)BROTLI_ALLOC(s, code_size + htree_size);
group->alphabet_size = (uint16_t)alphabet_size;
group->num_htrees = (uint16_t)ntrees;
group->codes = (HuffmanCode*)p;
group->htrees = (HuffmanCode**)(p + code_size);
}
void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group) {
BROTLI_FREE(s, group->codes);
group->htrees = NULL;
}
#if defined(__cplusplus) || defined(c_plusplus)

Просмотреть файл

@ -1,16 +1,7 @@
/* Copyright 2015 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Brotli state for partial streaming decoding. */
@ -18,10 +9,8 @@
#ifndef BROTLI_DEC_STATE_H_
#define BROTLI_DEC_STATE_H_
#include <stdio.h>
#include "./bit_reader.h"
#include "./huffman.h"
#include "./streams.h"
#include "./types.h"
#if defined(__cplusplus) || defined(c_plusplus)
@ -30,19 +19,20 @@ extern "C" {
typedef enum {
BROTLI_STATE_UNINITED,
BROTLI_STATE_BITREADER_WARMUP,
BROTLI_STATE_METABLOCK_BEGIN,
BROTLI_STATE_METABLOCK_HEADER,
BROTLI_STATE_METABLOCK_HEADER_2,
BROTLI_STATE_CONTEXT_MODES,
BROTLI_STATE_COMMAND_BEGIN,
BROTLI_STATE_COMMAND_INNER,
BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
BROTLI_STATE_COMMAND_POST_WRAP_COPY,
BROTLI_STATE_UNCOMPRESSED,
BROTLI_STATE_METADATA,
BROTLI_STATE_COMMAND_INNER_WRITE,
BROTLI_STATE_METABLOCK_DONE,
BROTLI_STATE_COMMAND_POST_WRITE_1,
BROTLI_STATE_COMMAND_POST_WRITE_2,
BROTLI_STATE_COMMAND_POST_WRAP_COPY,
BROTLI_STATE_HUFFMAN_CODE_0,
BROTLI_STATE_HUFFMAN_CODE_1,
BROTLI_STATE_HUFFMAN_CODE_2,
@ -66,8 +56,6 @@ typedef enum {
typedef enum {
BROTLI_STATE_UNCOMPRESSED_NONE,
BROTLI_STATE_UNCOMPRESSED_SHORT,
BROTLI_STATE_UNCOMPRESSED_COPY,
BROTLI_STATE_UNCOMPRESSED_WRITE
} BrotliRunningUncompressedState;
@ -80,11 +68,16 @@ typedef enum {
BROTLI_STATE_CONTEXT_MAP_NONE,
BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
BROTLI_STATE_CONTEXT_MAP_DECODE
BROTLI_STATE_CONTEXT_MAP_DECODE,
BROTLI_STATE_CONTEXT_MAP_TRANSFORM
} BrotliRunningContextMapState;
typedef enum {
BROTLI_STATE_HUFFMAN_NONE,
BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
BROTLI_STATE_HUFFMAN_SIMPLE_READ,
BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
BROTLI_STATE_HUFFMAN_COMPLEX,
BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS
} BrotliRunningHuffmanState;
@ -94,11 +87,30 @@ typedef enum {
BROTLI_STATE_DECODE_UINT8_LONG
} BrotliRunningDecodeUint8State;
typedef struct {
typedef enum {
BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
} BrotliRunningReadBlockLengthState;
struct BrotliStateStruct {
BrotliRunningState state;
/* This counter is reused for several disjoint loops. */
BrotliBitReader br;
int loop_counter;
BrotliBitReader br;
brotli_alloc_func alloc_func;
brotli_free_func free_func;
void* memory_manager_opaque;
/* Temporary storage for remaining input. */
union {
uint64_t u64;
uint8_t u8[8];
} buffer;
uint32_t buffer_length;
int pos;
int max_backward_distance;
int max_backward_distance_minus_custom_dict_size;
@ -115,6 +127,8 @@ typedef struct {
uint8_t* context_map_slice;
uint8_t* dist_context_map_slice;
uint32_t sub_loop_counter;
/* This ring buffer holds a few past copy distances that will be used by */
/* some special distance codes. */
HuffmanTreeGroup literal_hgroup;
@ -127,27 +141,28 @@ typedef struct {
int trivial_literal_context;
int distance_context;
int meta_block_remaining_len;
int block_length[3];
int num_block_types[3];
int block_type_rb[6];
int distance_postfix_bits;
int num_direct_distance_codes;
uint32_t block_length_index;
uint32_t block_length[3];
uint32_t num_block_types[3];
uint32_t block_type_rb[6];
uint32_t distance_postfix_bits;
uint32_t num_direct_distance_codes;
int distance_postfix_mask;
int num_dist_htrees;
uint32_t num_dist_htrees;
uint8_t* dist_context_map;
HuffmanCode *literal_htree;
uint8_t literal_htree_index;
uint8_t dist_htree_index;
uint8_t repeat_code_len;
uint8_t prev_code_len;
uint32_t repeat_code_len;
uint32_t prev_code_len;
int copy_length;
int distance_code;
/* For partial write operations */
int to_write;
int partially_written;
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) */
/* For ReadHuffmanCode */
uint32_t symbol;
@ -171,12 +186,13 @@ typedef struct {
HuffmanCode* next;
/* For DecodeContextMap */
int context_index;
int max_run_length_prefix;
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_TABLE_SIZE];
uint32_t context_index;
uint32_t max_run_length_prefix;
uint32_t code;
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
/* For InverseMoveToFrontTransform */
int mtf_upper_bound;
uint32_t mtf_upper_bound;
uint8_t mtf[256];
/* For custom dictionaries */
@ -191,6 +207,7 @@ typedef struct {
BrotliRunningUncompressedState substate_uncompressed;
BrotliRunningHuffmanState substate_huffman;
BrotliRunningDecodeUint8State substate_decode_uint8;
BrotliRunningReadBlockLengthState substate_read_block_length;
uint8_t is_last_metablock;
uint8_t is_uncompressed;
@ -198,15 +215,33 @@ typedef struct {
uint8_t size_nibbles;
uint32_t window_bits;
int num_literal_htrees;
uint32_t num_literal_htrees;
uint8_t* context_map;
uint8_t* context_modes;
} BrotliState;
};
typedef struct BrotliStateStruct BrotliState;
void BrotliStateInit(BrotliState* s);
void BrotliStateInitWithCustomAllocators(BrotliState* s,
brotli_alloc_func alloc_func,
brotli_free_func free_func,
void* opaque);
void BrotliStateCleanup(BrotliState* s);
void BrotliStateMetablockBegin(BrotliState* s);
void BrotliStateCleanupAfterMetablock(BrotliState* s);
void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group,
uint32_t alphabet_size, uint32_t ntrees);
void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group);
/* Returns 1, if s is in a state where we have not read any input bytes yet,
and 0 otherwise */
int BrotliStateIsStreamStart(const BrotliState* s);
/* Returns 1, if s is in a state where we reached the end of the input and
produced all of the output, and 0 otherwise. */
int BrotliStateIsStreamEnd(const BrotliState* s);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Functions for streaming input and output. */
@ -93,11 +84,13 @@ BrotliOutput BrotliFileOutput(FILE* f) {
return out;
}
int BrotliNullOutputFunction(void* data, const uint8_t* buf, size_t count) {
int BrotliNullOutputFunction(void* data , const uint8_t* buf, size_t count) {
BROTLI_UNUSED(data);
BROTLI_UNUSED(buf);
return (int)count;
}
BrotliOutput BrotliNullOutput() {
BrotliOutput BrotliNullOutput(void) {
BrotliOutput out;
out.cb_ = BrotliNullOutputFunction;
out.data_ = NULL;

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Functions for streaming input and output. */
@ -95,7 +86,7 @@ BrotliOutput BrotliFileOutput(FILE* f);
/* Output callback that does nothing, always consumes the whole input. */
int BrotliNullOutputFunction(void* data, const uint8_t* buf, size_t count);
BrotliOutput BrotliNullOutput();
BrotliOutput BrotliNullOutput(void);
#if defined(__cplusplus) || defined(c_plusplus)
} /* extern "C" */

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Transformations on dictionary words. */
@ -18,8 +9,6 @@
#ifndef BROTLI_DEC_TRANSFORM_H_
#define BROTLI_DEC_TRANSFORM_H_
#include <stdio.h>
#include <ctype.h>
#include "./port.h"
#include "./types.h"
@ -278,22 +267,19 @@ static BROTLI_NOINLINE int TransformDictionaryWord(
}
{
const int t = kTransforms[transform].transform;
int skip = t < kOmitFirst1 ? 0 : t - (kOmitFirst1 - 1);
int i = 0;
uint8_t* uppercase;
if (skip > len) {
skip = len;
}
word += skip;
len -= skip;
if (t <= kOmitLast9) {
int skip = t - (kOmitFirst1 - 1);
if (skip > 0) {
word += skip;
len -= skip;
} else if (t <= kOmitLast9) {
len -= t;
}
while (i < len) { dst[idx++] = word[i++]; }
uppercase = &dst[idx - len];
if (t == kUppercaseFirst) {
ToUpperCase(uppercase);
ToUpperCase(&dst[idx - len]);
} else if (t == kUppercaseAll) {
uint8_t* uppercase = &dst[idx - len];
while (len > 0) {
int step = ToUpperCase(uppercase);
uppercase += step;

Просмотреть файл

@ -1,16 +1,7 @@
/* 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.
Distributed under MIT license.
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
/* Common types */
@ -21,16 +12,27 @@
#include <stddef.h> /* for size_t */
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
typedef long long int int64_t;
typedef __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int64 int64_t;
#else
#include <stdint.h>
#endif /* defined(_MSC_VER) && (_MSC_VER < 1600) */
/* Allocating function pointer. Function MUST return 0 in the case of failure.
Otherwise it MUST return a valid pointer to a memory region of at least
size length. Neither items nor size are allowed to be 0.
opaque argument is a pointer provided by client and could be used to bind
function to specific object (memory pool). */
typedef void* (*brotli_alloc_func) (void* opaque, size_t size);
/* Deallocating function pointer. Function SHOULD be no-op in the case the
address is 0. */
typedef void (*brotli_free_func) (void* opaque, void* address);
#endif /* BROTLI_DEC_TYPES_H_ */

Просмотреть файл

@ -10,7 +10,6 @@ EXPORTS += [
'dec/huffman.h',
'dec/port.h',
'dec/state.h',
'dec/streams.h',
'dec/types.h',
]
@ -20,7 +19,6 @@ UNIFIED_SOURCES += [
'dec/dictionary.c',
'dec/huffman.c',
'dec/state.c',
'dec/streams.c',
]
# We allow warnings for third-party code that can be updated from upstream.

Просмотреть файл

@ -3,7 +3,7 @@
# Script to update the mozilla in-tree copy of the Brotli decompressor.
# Run this within the /modules/brotli directory of the source tree.
MY_TEMP_DIR=`mktemp -d -t brotli_update` || exit 1
MY_TEMP_DIR=`mktemp -d -t brotli_update.XXXXXX` || exit 1
git clone https://github.com/google/brotli ${MY_TEMP_DIR}/brotli

Просмотреть файл

@ -136,7 +136,6 @@ nsHTTPCompressConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
LOG(("nsHttpCompresssConv %p onstop partial gzip\n", this));
}
if (NS_SUCCEEDED(status) && mMode == HTTP_COMPRESS_BROTLI) {
uint32_t waste;
nsCOMPtr<nsIForcePendingChannel> fpChannel = do_QueryInterface(request);
bool isPending = false;
if (request) {
@ -145,7 +144,9 @@ nsHTTPCompressConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
if (fpChannel && !isPending) {
fpChannel->ForcePending(true);
}
status = BrotliHandler(nullptr, this, nullptr, 0, 0, &waste);
if (mBrotli->mTotalOut == 0 && !BrotliStateIsStreamEnd(&mBrotli->mState)) {
status = NS_ERROR_INVALID_CONTENT_ENCODING;
}
LOG(("nsHttpCompresssConv %p onstop brotlihandler rv %x\n", this, status));
if (fpChannel && !isPending) {
fpChannel->ForcePending(false);
@ -160,6 +161,7 @@ NS_METHOD
nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const char *dataIn,
uint32_t, uint32_t aAvail, uint32_t *countRead)
{
MOZ_ASSERT(stream);
nsHTTPCompressConv *self = static_cast<nsHTTPCompressConv *>(closure);
*countRead = 0;
@ -179,11 +181,10 @@ nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const c
outSize = kOutSize;
outPtr = outBuffer;
// brotli api is documented in brotli/dec/decode.h
LOG(("nsHttpCompresssConv %p brotlihandler decompress %d finish %d\n",
self, avail, !stream));
res = ::BrotliDecompressBufferStreaming(
&avail, reinterpret_cast<const unsigned char **>(&dataIn), stream ? 0 : 1,
// brotli api is documented in brotli/dec/decode.h and brotli/dec/decode.c
LOG(("nsHttpCompresssConv %p brotlihandler decompress %d\n", self, avail));
res = ::BrotliDecompressStream(
&avail, reinterpret_cast<const unsigned char **>(&dataIn),
&outSize, &outPtr, &self->mBrotli->mTotalOut, &self->mBrotli->mState);
outSize = kOutSize - outSize;
LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%x out=%d\n",
@ -195,12 +196,15 @@ nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const c
return self->mBrotli->mStatus;
}
// in 'the current implementation' brotli consumes all input on success
MOZ_ASSERT(!avail);
if (avail) {
LOG(("nsHttpCompressConv %p did not consume all input", self));
self->mBrotli->mStatus = NS_ERROR_UNEXPECTED;
return self->mBrotli->mStatus;
// in 'the current implementation' brotli must consume everything before
// asking for more input
if (res == BROTLI_RESULT_NEEDS_MORE_INPUT) {
MOZ_ASSERT(!avail);
if (avail) {
LOG(("nsHttpCompressConv %p did not consume all input", self));
self->mBrotli->mStatus = NS_ERROR_UNEXPECTED;
return self->mBrotli->mStatus;
}
}
if (outSize > 0) {
nsresult rv = self->do_OnDataAvailable(self->mBrotli->mRequest,