зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1242904 - Update Brotli to latest upstream revision ; now at 33aa40220b96cf95ad2b9ba61dc8d7fd2f964f2c. r=mcmanus
This commit is contained in:
Родитель
c32fd629f0
Коммит
a4aeb26856
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче