mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1850991 - Update brotli to version 1.1.0. r=jfkthame
Differential Revision: https://phabricator.services.mozilla.com/D187212
This commit is contained in:
parent
63bd6acc44
commit
35c6bce5ac
@ -4,7 +4,7 @@
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "./constants.h"
|
||||
#include "constants.h"
|
||||
|
||||
const BrotliPrefixCodeRange
|
||||
_kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
|
||||
|
@ -12,10 +12,11 @@
|
||||
#ifndef BROTLI_COMMON_CONSTANTS_H_
|
||||
#define BROTLI_COMMON_CONSTANTS_H_
|
||||
|
||||
#include "./platform.h"
|
||||
#include <brotli/port.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/* Specification: 7.3. Encoding of the context map */
|
||||
#define BROTLI_CONTEXT_MAP_MAX_RLE 16
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "./context.h"
|
||||
#include "context.h"
|
||||
|
||||
#include <brotli/types.h>
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "./dictionary.h"
|
||||
#include "./platform.h"
|
||||
#include "dictionary.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
@ -13,6 +13,7 @@ extern "C" {
|
||||
|
||||
#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA)
|
||||
static const uint8_t kBrotliDictionaryData[] =
|
||||
/* GENERATED CODE START */
|
||||
{
|
||||
116,105,109,101,100,111,119,110,108,105,102,101,108,101,102,116,98,97,99,107,99,
|
||||
111,100,101,100,97,116,97,115,104,111,119,111,110,108,121,115,105,116,101,99,105
|
||||
@ -5860,6 +5861,7 @@ static const uint8_t kBrotliDictionaryData[] =
|
||||
,164,181,224,164,190,224,164,136,224,164,184,224,164,149,224,165,141,224,164,176
|
||||
,224,164,191,224,164,175,224,164,164,224,164,190
|
||||
}
|
||||
/* GENERATED CODE END */
|
||||
;
|
||||
#endif /* !BROTLI_EXTERNAL_DICTIONARY_DATA */
|
||||
|
||||
@ -5895,7 +5897,7 @@ static BrotliDictionary kBrotliDictionary = {
|
||||
#endif
|
||||
};
|
||||
|
||||
const BrotliDictionary* BrotliGetDictionary() {
|
||||
const BrotliDictionary* BrotliGetDictionary(void) {
|
||||
return &kBrotliDictionary;
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./platform.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/* Default brotli_alloc_func */
|
||||
void* BrotliDefaultAllocFunc(void* opaque, size_t size) {
|
||||
BROTLI_UNUSED(opaque);
|
||||
|
@ -12,12 +12,13 @@
|
||||
* 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_PORTABLE disables dangerous optimizations, like unaligned
|
||||
read and overlapping memcpy; this reduces decompression speed by 5%
|
||||
* BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
|
||||
* BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read
|
||||
optimizations (mainly for testing purposes)
|
||||
* BROTLI_DEBUG dumps file name and line number when decoder detects stream
|
||||
or memory error
|
||||
* BROTLI_ENABLE_LOG enables asserts and dumps various state information
|
||||
* BROTLI_ENABLE_DUMP overrides default "dump" behaviour
|
||||
*/
|
||||
|
||||
#ifndef BROTLI_COMMON_PLATFORM_H_
|
||||
@ -40,7 +41,7 @@
|
||||
#define BROTLI_X_BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#if BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
|
||||
#if BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
@ -156,24 +157,6 @@ OR:
|
||||
#define BROTLI_NOINLINE
|
||||
#endif
|
||||
|
||||
/* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */
|
||||
#if !defined(BROTLI_INTERNAL)
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define BROTLI_INTERNAL
|
||||
#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \
|
||||
BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
|
||||
BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
|
||||
BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
|
||||
BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \
|
||||
BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \
|
||||
(BROTLI_TI_VERSION_CHECK(7, 3, 0) && \
|
||||
defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))
|
||||
#define BROTLI_INTERNAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define BROTLI_INTERNAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* <<< <<< <<< end of hedley macros. */
|
||||
|
||||
#if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \
|
||||
@ -226,15 +209,24 @@ OR:
|
||||
#define BROTLI_TARGET_RISCV64
|
||||
#endif
|
||||
|
||||
#if defined(__loongarch_lp64)
|
||||
#define BROTLI_TARGET_LOONGARCH64
|
||||
#endif
|
||||
|
||||
#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
|
||||
defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \
|
||||
defined(BROTLI_TARGET_LOONGARCH64)
|
||||
#define BROTLI_TARGET_64_BITS 1
|
||||
#else
|
||||
#define BROTLI_TARGET_64_BITS 0
|
||||
#endif
|
||||
|
||||
#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_64) || \
|
||||
defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
|
||||
#define BROTLI_64_BITS 1
|
||||
#else
|
||||
#define BROTLI_64_BITS 0
|
||||
#define BROTLI_64_BITS BROTLI_TARGET_64_BITS
|
||||
#endif
|
||||
|
||||
#if (BROTLI_64_BITS)
|
||||
@ -278,18 +270,19 @@ OR:
|
||||
#undef BROTLI_X_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#if defined(BROTLI_BUILD_PORTABLE)
|
||||
#define BROTLI_ALIGNED_READ (!!1)
|
||||
#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
|
||||
#if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST)
|
||||
#define BROTLI_UNALIGNED_READ_FAST (!!0)
|
||||
#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
|
||||
defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \
|
||||
defined(BROTLI_TARGET_RISCV64)
|
||||
/* Allow unaligned read only for white-listed CPUs. */
|
||||
#define BROTLI_ALIGNED_READ (!!0)
|
||||
defined(BROTLI_TARGET_RISCV64) || defined(BROTLI_TARGET_LOONGARCH64)
|
||||
/* These targets are known to generate efficient code for unaligned reads
|
||||
* (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd
|
||||
* together). */
|
||||
#define BROTLI_UNALIGNED_READ_FAST (!!1)
|
||||
#else
|
||||
#define BROTLI_ALIGNED_READ (!!1)
|
||||
#define BROTLI_UNALIGNED_READ_FAST (!!0)
|
||||
#endif
|
||||
|
||||
#if BROTLI_ALIGNED_READ
|
||||
/* Portable unaligned memory access: read / write values via memcpy. */
|
||||
static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
|
||||
uint16_t t;
|
||||
@ -309,75 +302,6 @@ static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
|
||||
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
|
||||
memcpy(p, &v, sizeof v);
|
||||
}
|
||||
#else /* BROTLI_ALIGNED_READ */
|
||||
/* Unaligned memory access is allowed: just cast pointer to requested type. */
|
||||
#if BROTLI_SANITIZED
|
||||
/* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
|
||||
AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
|
||||
will miss a bug if 08 is the first unaddressable byte.
|
||||
ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
|
||||
miss a race between this access and some other accesses to 08.
|
||||
MemorySanitizer will correctly propagate the shadow on unaligned stores
|
||||
and correctly report bugs on unaligned loads, but it may not properly
|
||||
update and report the origin of the uninitialized memory.
|
||||
For all three tools, replacing an unaligned access with a tool-specific
|
||||
callback solves the problem. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
uint16_t __sanitizer_unaligned_load16(const void* p);
|
||||
uint32_t __sanitizer_unaligned_load32(const void* p);
|
||||
uint64_t __sanitizer_unaligned_load64(const void* p);
|
||||
void __sanitizer_unaligned_store64(void* p, uint64_t v);
|
||||
#if defined(__cplusplus)
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
#define BrotliUnalignedRead16 __sanitizer_unaligned_load16
|
||||
#define BrotliUnalignedRead32 __sanitizer_unaligned_load32
|
||||
#define BrotliUnalignedRead64 __sanitizer_unaligned_load64
|
||||
#define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
|
||||
#else /* BROTLI_SANITIZED */
|
||||
static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
|
||||
return *(const uint16_t*)p;
|
||||
}
|
||||
static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {
|
||||
return *(const uint32_t*)p;
|
||||
}
|
||||
#if (BROTLI_64_BITS)
|
||||
static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
|
||||
return *(const uint64_t*)p;
|
||||
}
|
||||
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
|
||||
*(uint64_t*)p = v;
|
||||
}
|
||||
#else /* BROTLI_64_BITS */
|
||||
/* Avoid emitting LDRD / STRD, which require properly aligned address. */
|
||||
/* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */
|
||||
|
||||
#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
|
||||
typedef BROTLI_ALIGNED(1) uint64_t brotli_unaligned_uint64_t;
|
||||
|
||||
static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
|
||||
return (uint64_t) ((const brotli_unaligned_uint64_t*) p)[0];
|
||||
}
|
||||
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
|
||||
brotli_unaligned_uint64_t* dwords = (brotli_unaligned_uint64_t*) p;
|
||||
dwords[0] = (brotli_unaligned_uint64_t) v;
|
||||
}
|
||||
#else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
|
||||
static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
|
||||
uint64_t v;
|
||||
memcpy(&v, p, sizeof(uint64_t));
|
||||
return v;
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
|
||||
memcpy(p, &v, sizeof(uint64_t));
|
||||
}
|
||||
#endif /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
|
||||
#endif /* BROTLI_64_BITS */
|
||||
#endif /* BROTLI_SANITIZED */
|
||||
#endif /* BROTLI_ALIGNED_READ */
|
||||
|
||||
#if BROTLI_LITTLE_ENDIAN
|
||||
/* Straight endianness. Just read / write values. */
|
||||
@ -453,6 +377,16 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
|
||||
}
|
||||
#endif /* BROTLI_LITTLE_ENDIAN */
|
||||
|
||||
static BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) {
|
||||
void* v;
|
||||
memcpy(&v, p, sizeof(void*));
|
||||
return v;
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) {
|
||||
memcpy(p, &v, sizeof(void*));
|
||||
}
|
||||
|
||||
/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */
|
||||
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \
|
||||
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
|
||||
@ -474,22 +408,34 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
|
||||
#endif
|
||||
|
||||
#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
|
||||
#define BROTLI_ENABLE_DUMP_DEFAULT 1
|
||||
#define BROTLI_DCHECK(x) assert(x)
|
||||
#else
|
||||
#define BROTLI_ENABLE_DUMP_DEFAULT 0
|
||||
#define BROTLI_DCHECK(x)
|
||||
#endif
|
||||
|
||||
#if !defined(BROTLI_ENABLE_DUMP)
|
||||
#define BROTLI_ENABLE_DUMP BROTLI_ENABLE_DUMP_DEFAULT
|
||||
#endif
|
||||
|
||||
#if BROTLI_ENABLE_DUMP
|
||||
static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
|
||||
fprintf(stderr, "%s:%d (%s)\n", f, l, fn);
|
||||
fflush(stderr);
|
||||
}
|
||||
#define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__)
|
||||
#else
|
||||
#define BROTLI_DCHECK(x)
|
||||
#define BROTLI_DUMP() (void)(0)
|
||||
#endif
|
||||
|
||||
/* TODO: add appropriate icc/sunpro/arm/ibm/ti checks. */
|
||||
/* BrotliRBit assumes brotli_reg_t fits native CPU register type. */
|
||||
#if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS)
|
||||
/* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */
|
||||
#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \
|
||||
!defined(BROTLI_BUILD_NO_RBIT)
|
||||
#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)
|
||||
/* TODO: detect ARMv6T2 and enable this code for it. */
|
||||
/* TODO(eustas): detect ARMv6T2 and enable this code for it. */
|
||||
static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
|
||||
brotli_reg_t output;
|
||||
__asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
|
||||
@ -498,15 +444,14 @@ static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
|
||||
#define BROTLI_RBIT(x) BrotliRBit(x)
|
||||
#endif /* armv7 / armv8 */
|
||||
#endif /* gcc || clang */
|
||||
#endif /* brotli_reg_t is native */
|
||||
#if !defined(BROTLI_RBIT)
|
||||
static BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ }
|
||||
#endif /* BROTLI_RBIT */
|
||||
|
||||
#define BROTLI_REPEAT(N, X) { \
|
||||
if ((N & 1) != 0) {X;} \
|
||||
if ((N & 2) != 0) {X; X;} \
|
||||
if ((N & 4) != 0) {X; X; X; X;} \
|
||||
}
|
||||
#define BROTLI_REPEAT_4(X) {X; X; X; X;}
|
||||
#define BROTLI_REPEAT_5(X) {X; X; X; X; X;}
|
||||
#define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;}
|
||||
|
||||
#define BROTLI_UNUSED(X) (void)(X)
|
||||
|
||||
@ -529,7 +474,7 @@ BROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t)
|
||||
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \
|
||||
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
|
||||
#define BROTLI_TZCNT64 __builtin_ctzll
|
||||
#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
|
||||
#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
|
||||
#if defined(BROTLI_TARGET_X64)
|
||||
#define BROTLI_TZCNT64 _tzcnt_u64
|
||||
#else /* BROTLI_TARGET_X64 */
|
||||
@ -546,7 +491,7 @@ static BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) {
|
||||
#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \
|
||||
BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
|
||||
#define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x))
|
||||
#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
|
||||
#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
|
||||
static BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) {
|
||||
unsigned long msb;
|
||||
_BitScanReverse(&msb, x);
|
||||
@ -571,6 +516,8 @@ BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
|
||||
BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE);
|
||||
BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE);
|
||||
BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE);
|
||||
BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR);
|
||||
BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR);
|
||||
BROTLI_UNUSED(&BrotliRBit);
|
||||
BROTLI_UNUSED(&brotli_min_double);
|
||||
BROTLI_UNUSED(&brotli_max_double);
|
||||
@ -586,7 +533,7 @@ BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
|
||||
BROTLI_UNUSED(&brotli_max_uint8_t);
|
||||
BROTLI_UNUSED(&BrotliDefaultAllocFunc);
|
||||
BROTLI_UNUSED(&BrotliDefaultFreeFunc);
|
||||
#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
|
||||
#if BROTLI_ENABLE_DUMP
|
||||
BROTLI_UNUSED(&BrotliDump);
|
||||
#endif
|
||||
}
|
||||
|
521
modules/brotli/common/shared_dictionary.c
Normal file
521
modules/brotli/common/shared_dictionary.c
Normal file
@ -0,0 +1,521 @@
|
||||
/* Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* Shared Dictionary definition and utilities. */
|
||||
|
||||
#include <brotli/shared_dictionary.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dictionary.h"
|
||||
#include "platform.h"
|
||||
#include "shared_dictionary_internal.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(BROTLI_EXPERIMENTAL)
|
||||
|
||||
#define BROTLI_NUM_ENCODED_LENGTHS (SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH \
|
||||
- SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH + 1)
|
||||
|
||||
/* Max allowed by spec */
|
||||
#define BROTLI_MAX_SIZE_BITS 15u
|
||||
|
||||
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
|
||||
static BROTLI_BOOL ReadBool(const uint8_t* encoded, size_t size, size_t* pos,
|
||||
BROTLI_BOOL* result) {
|
||||
uint8_t value;
|
||||
size_t position = *pos;
|
||||
if (position >= size) return BROTLI_FALSE; /* past file end */
|
||||
value = encoded[position++];
|
||||
if (value > 1) return BROTLI_FALSE; /* invalid bool */
|
||||
*result = TO_BROTLI_BOOL(value);
|
||||
*pos = position;
|
||||
return BROTLI_TRUE; /* success */
|
||||
}
|
||||
|
||||
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
|
||||
static BROTLI_BOOL ReadUint8(const uint8_t* encoded, size_t size, size_t* pos,
|
||||
uint8_t* result) {
|
||||
size_t position = *pos;
|
||||
if (position + sizeof(uint8_t) > size) return BROTLI_FALSE;
|
||||
*result = encoded[position++];
|
||||
*pos = position;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
|
||||
static BROTLI_BOOL ReadUint16(const uint8_t* encoded, size_t size, size_t* pos,
|
||||
uint16_t* result) {
|
||||
size_t position = *pos;
|
||||
if (position + sizeof(uint16_t) > size) return BROTLI_FALSE;
|
||||
*result = BROTLI_UNALIGNED_LOAD16LE(&encoded[position]);
|
||||
position += 2;
|
||||
*pos = position;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
/* Reads a varint into a uint32_t, and returns error if it's too large */
|
||||
/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
|
||||
static BROTLI_BOOL ReadVarint32(const uint8_t* encoded, size_t size,
|
||||
size_t* pos, uint32_t* result) {
|
||||
int num = 0;
|
||||
uint8_t byte;
|
||||
*result = 0;
|
||||
for (;;) {
|
||||
if (*pos >= size) return BROTLI_FALSE;
|
||||
byte = encoded[(*pos)++];
|
||||
if (num == 4 && byte > 15) return BROTLI_FALSE;
|
||||
*result |= (uint32_t)(byte & 127) << (num * 7);
|
||||
if (byte < 128) return BROTLI_TRUE;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the total length of word list. */
|
||||
static size_t BrotliSizeBitsToOffsets(const uint8_t* size_bits_by_length,
|
||||
uint32_t* offsets_by_length) {
|
||||
uint32_t pos = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {
|
||||
offsets_by_length[i] = pos;
|
||||
if (size_bits_by_length[i] != 0) {
|
||||
pos += i << size_bits_by_length[i];
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
static BROTLI_BOOL ParseWordList(size_t size, const uint8_t* encoded,
|
||||
size_t* pos, BrotliDictionary* out) {
|
||||
size_t offset;
|
||||
size_t i;
|
||||
size_t position = *pos;
|
||||
if (position + BROTLI_NUM_ENCODED_LENGTHS > size) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
memset(out->size_bits_by_length, 0, SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH);
|
||||
memcpy(out->size_bits_by_length + SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH,
|
||||
&encoded[position], BROTLI_NUM_ENCODED_LENGTHS);
|
||||
for (i = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;
|
||||
i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {
|
||||
if (out->size_bits_by_length[i] > BROTLI_MAX_SIZE_BITS) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
position += BROTLI_NUM_ENCODED_LENGTHS;
|
||||
offset = BrotliSizeBitsToOffsets(
|
||||
out->size_bits_by_length, out->offsets_by_length);
|
||||
|
||||
out->data = &encoded[position];
|
||||
out->data_size = offset;
|
||||
position += offset;
|
||||
if (position > size) return BROTLI_FALSE;
|
||||
*pos = position;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
/* Computes the cutOffTransforms of a BrotliTransforms which already has the
|
||||
transforms data correctly filled in. */
|
||||
static void ComputeCutoffTransforms(BrotliTransforms* transforms) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {
|
||||
transforms->cutOffTransforms[i] = -1;
|
||||
}
|
||||
for (i = 0; i < transforms->num_transforms; i++) {
|
||||
const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, i);
|
||||
uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, i);
|
||||
const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, i);
|
||||
if (type <= BROTLI_TRANSFORM_OMIT_LAST_9 && *prefix == 0 && *suffix == 0 &&
|
||||
transforms->cutOffTransforms[type] == -1) {
|
||||
transforms->cutOffTransforms[type] = (int16_t)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BROTLI_BOOL ParsePrefixSuffixTable(size_t size, const uint8_t* encoded,
|
||||
size_t* pos, BrotliTransforms* out, uint16_t* out_table,
|
||||
size_t* out_table_size) {
|
||||
size_t position = *pos;
|
||||
size_t offset = 0;
|
||||
size_t stringlet_count = 0; /* NUM_PREFIX_SUFFIX */
|
||||
size_t data_length = 0;
|
||||
|
||||
/* PREFIX_SUFFIX_LENGTH */
|
||||
if (!ReadUint16(encoded, size, &position, &out->prefix_suffix_size)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
data_length = out->prefix_suffix_size;
|
||||
|
||||
/* Must at least have space for null terminator. */
|
||||
if (data_length < 1) return BROTLI_FALSE;
|
||||
out->prefix_suffix = &encoded[position];
|
||||
if (position + data_length >= size) return BROTLI_FALSE;
|
||||
while (BROTLI_TRUE) {
|
||||
/* STRING_LENGTH */
|
||||
size_t stringlet_len = encoded[position + offset];
|
||||
out_table[stringlet_count] = (uint16_t)offset;
|
||||
stringlet_count++;
|
||||
offset++;
|
||||
if (stringlet_len == 0) {
|
||||
if (offset == data_length) {
|
||||
break;
|
||||
} else {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
if (stringlet_count > 255) return BROTLI_FALSE;
|
||||
offset += stringlet_len;
|
||||
if (offset >= data_length) return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
position += data_length;
|
||||
*pos = position;
|
||||
*out_table_size = (uint16_t)stringlet_count;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
static BROTLI_BOOL ParseTransformsList(size_t size, const uint8_t* encoded,
|
||||
size_t* pos, BrotliTransforms* out, uint16_t* prefix_suffix_table,
|
||||
size_t* prefix_suffix_count) {
|
||||
uint32_t i;
|
||||
BROTLI_BOOL has_params = BROTLI_FALSE;
|
||||
BROTLI_BOOL prefix_suffix_ok = BROTLI_FALSE;
|
||||
size_t position = *pos;
|
||||
size_t stringlet_cnt = 0;
|
||||
if (position >= size) return BROTLI_FALSE;
|
||||
|
||||
prefix_suffix_ok = ParsePrefixSuffixTable(
|
||||
size, encoded, &position, out, prefix_suffix_table, &stringlet_cnt);
|
||||
if (!prefix_suffix_ok) return BROTLI_FALSE;
|
||||
out->prefix_suffix_map = prefix_suffix_table;
|
||||
*prefix_suffix_count = stringlet_cnt;
|
||||
|
||||
out->num_transforms = encoded[position++];
|
||||
out->transforms = &encoded[position];
|
||||
position += (size_t)out->num_transforms * 3;
|
||||
if (position > size) return BROTLI_FALSE;
|
||||
/* Check for errors and read extra parameters. */
|
||||
for (i = 0; i < out->num_transforms; i++) {
|
||||
uint8_t prefix_id = BROTLI_TRANSFORM_PREFIX_ID(out, i);
|
||||
uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);
|
||||
uint8_t suffix_id = BROTLI_TRANSFORM_SUFFIX_ID(out, i);
|
||||
if (prefix_id >= stringlet_cnt) return BROTLI_FALSE;
|
||||
if (type >= BROTLI_NUM_TRANSFORM_TYPES) return BROTLI_FALSE;
|
||||
if (suffix_id >= stringlet_cnt) return BROTLI_FALSE;
|
||||
if (type == BROTLI_TRANSFORM_SHIFT_FIRST ||
|
||||
type == BROTLI_TRANSFORM_SHIFT_ALL) {
|
||||
has_params = BROTLI_TRUE;
|
||||
}
|
||||
}
|
||||
if (has_params) {
|
||||
out->params = &encoded[position];
|
||||
position += (size_t)out->num_transforms * 2;
|
||||
if (position > size) return BROTLI_FALSE;
|
||||
for (i = 0; i < out->num_transforms; i++) {
|
||||
uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);
|
||||
if (type != BROTLI_TRANSFORM_SHIFT_FIRST &&
|
||||
type != BROTLI_TRANSFORM_SHIFT_ALL) {
|
||||
if (out->params[i * 2] != 0 || out->params[i * 2 + 1] != 0) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out->params = NULL;
|
||||
}
|
||||
ComputeCutoffTransforms(out);
|
||||
*pos = position;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
static BROTLI_BOOL DryParseDictionary(const uint8_t* encoded,
|
||||
size_t size, uint32_t* num_prefix, BROTLI_BOOL* is_custom_static_dict) {
|
||||
size_t pos = 0;
|
||||
uint32_t chunk_size = 0;
|
||||
uint8_t num_word_lists;
|
||||
uint8_t num_transform_lists;
|
||||
*is_custom_static_dict = BROTLI_FALSE;
|
||||
*num_prefix = 0;
|
||||
|
||||
/* Skip magic header bytes. */
|
||||
pos += 2;
|
||||
|
||||
/* LZ77_DICTIONARY_LENGTH */
|
||||
if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;
|
||||
if (chunk_size != 0) {
|
||||
/* This limitation is not specified but the 32-bit Brotli decoder for now */
|
||||
if (chunk_size > 1073741823) return BROTLI_FALSE;
|
||||
*num_prefix = 1;
|
||||
if (pos + chunk_size > size) return BROTLI_FALSE;
|
||||
pos += chunk_size;
|
||||
}
|
||||
|
||||
if (!ReadUint8(encoded, size, &pos, &num_word_lists)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (!ReadUint8(encoded, size, &pos, &num_transform_lists)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
if (num_word_lists > 0 || num_transform_lists > 0) {
|
||||
*is_custom_static_dict = BROTLI_TRUE;
|
||||
}
|
||||
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
static BROTLI_BOOL ParseDictionary(const uint8_t* encoded, size_t size,
|
||||
BrotliSharedDictionary* dict) {
|
||||
uint32_t i;
|
||||
size_t pos = 0;
|
||||
uint32_t chunk_size = 0;
|
||||
size_t total_prefix_suffix_count = 0;
|
||||
size_t trasform_list_start[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
|
||||
uint16_t temporary_prefix_suffix_table[256];
|
||||
|
||||
/* Skip magic header bytes. */
|
||||
pos += 2;
|
||||
|
||||
/* LZ77_DICTIONARY_LENGTH */
|
||||
if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;
|
||||
if (chunk_size != 0) {
|
||||
if (pos + chunk_size > size) return BROTLI_FALSE;
|
||||
dict->prefix_size[dict->num_prefix] = chunk_size;
|
||||
dict->prefix[dict->num_prefix] = &encoded[pos];
|
||||
dict->num_prefix++;
|
||||
/* LZ77_DICTIONARY_LENGTH bytes. */
|
||||
pos += chunk_size;
|
||||
}
|
||||
|
||||
/* NUM_WORD_LISTS */
|
||||
if (!ReadUint8(encoded, size, &pos, &dict->num_word_lists)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (dict->num_word_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
if (dict->num_word_lists != 0) {
|
||||
dict->words_instances = (BrotliDictionary*)dict->alloc_func(
|
||||
dict->memory_manager_opaque,
|
||||
dict->num_word_lists * sizeof(*dict->words_instances));
|
||||
if (!dict->words_instances) return BROTLI_FALSE; /* OOM */
|
||||
}
|
||||
for (i = 0; i < dict->num_word_lists; i++) {
|
||||
if (!ParseWordList(size, encoded, &pos, &dict->words_instances[i])) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* NUM_TRANSFORM_LISTS */
|
||||
if (!ReadUint8(encoded, size, &pos, &dict->num_transform_lists)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (dict->num_transform_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
if (dict->num_transform_lists != 0) {
|
||||
dict->transforms_instances = (BrotliTransforms*)dict->alloc_func(
|
||||
dict->memory_manager_opaque,
|
||||
dict->num_transform_lists * sizeof(*dict->transforms_instances));
|
||||
if (!dict->transforms_instances) return BROTLI_FALSE; /* OOM */
|
||||
}
|
||||
for (i = 0; i < dict->num_transform_lists; i++) {
|
||||
BROTLI_BOOL ok = BROTLI_FALSE;
|
||||
size_t prefix_suffix_count = 0;
|
||||
trasform_list_start[i] = pos;
|
||||
dict->transforms_instances[i].prefix_suffix_map =
|
||||
temporary_prefix_suffix_table;
|
||||
ok = ParseTransformsList(
|
||||
size, encoded, &pos, &dict->transforms_instances[i],
|
||||
temporary_prefix_suffix_table, &prefix_suffix_count);
|
||||
if (!ok) return BROTLI_FALSE;
|
||||
total_prefix_suffix_count += prefix_suffix_count;
|
||||
}
|
||||
if (total_prefix_suffix_count != 0) {
|
||||
dict->prefix_suffix_maps = (uint16_t*)dict->alloc_func(
|
||||
dict->memory_manager_opaque,
|
||||
total_prefix_suffix_count * sizeof(*dict->prefix_suffix_maps));
|
||||
if (!dict->prefix_suffix_maps) return BROTLI_FALSE; /* OOM */
|
||||
}
|
||||
total_prefix_suffix_count = 0;
|
||||
for (i = 0; i < dict->num_transform_lists; i++) {
|
||||
size_t prefix_suffix_count = 0;
|
||||
size_t position = trasform_list_start[i];
|
||||
uint16_t* prefix_suffix_map =
|
||||
&dict->prefix_suffix_maps[total_prefix_suffix_count];
|
||||
BROTLI_BOOL ok = ParsePrefixSuffixTable(
|
||||
size, encoded, &position, &dict->transforms_instances[i],
|
||||
prefix_suffix_map, &prefix_suffix_count);
|
||||
if (!ok) return BROTLI_FALSE;
|
||||
dict->transforms_instances[i].prefix_suffix_map = prefix_suffix_map;
|
||||
total_prefix_suffix_count += prefix_suffix_count;
|
||||
}
|
||||
|
||||
if (dict->num_word_lists != 0 || dict->num_transform_lists != 0) {
|
||||
if (!ReadUint8(encoded, size, &pos, &dict->num_dictionaries)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (dict->num_dictionaries == 0 ||
|
||||
dict->num_dictionaries > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
for (i = 0; i < dict->num_dictionaries; i++) {
|
||||
uint8_t words_index;
|
||||
uint8_t transforms_index;
|
||||
if (!ReadUint8(encoded, size, &pos, &words_index)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (words_index > dict->num_word_lists) return BROTLI_FALSE;
|
||||
if (!ReadUint8(encoded, size, &pos, &transforms_index)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (transforms_index > dict->num_transform_lists) return BROTLI_FALSE;
|
||||
dict->words[i] = words_index == dict->num_word_lists ?
|
||||
BrotliGetDictionary() : &dict->words_instances[words_index];
|
||||
dict->transforms[i] = transforms_index == dict->num_transform_lists ?
|
||||
BrotliGetTransforms(): &dict->transforms_instances[transforms_index];
|
||||
}
|
||||
/* CONTEXT_ENABLED */
|
||||
if (!ReadBool(encoded, size, &pos, &dict->context_based)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
/* CONTEXT_MAP */
|
||||
if (dict->context_based) {
|
||||
for (i = 0; i < SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS; i++) {
|
||||
if (!ReadUint8(encoded, size, &pos, &dict->context_map[i])) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
if (dict->context_map[i] >= dict->num_dictionaries) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dict->context_based = BROTLI_FALSE;
|
||||
dict->num_dictionaries = 1;
|
||||
dict->words[0] = BrotliGetDictionary();
|
||||
dict->transforms[0] = BrotliGetTransforms();
|
||||
}
|
||||
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
/* Decodes shared dictionary and verifies correctness.
|
||||
Returns BROTLI_TRUE if dictionary is valid, BROTLI_FALSE otherwise.
|
||||
The BrotliSharedDictionary must already have been initialized. If the
|
||||
BrotliSharedDictionary already contains data, compound dictionaries
|
||||
will be appended, but an error will be returned if it already has
|
||||
custom words or transforms.
|
||||
TODO(lode): link to RFC for shared brotli once published. */
|
||||
static BROTLI_BOOL DecodeSharedDictionary(
|
||||
const uint8_t* encoded, size_t size, BrotliSharedDictionary* dict) {
|
||||
uint32_t num_prefix = 0;
|
||||
BROTLI_BOOL is_custom_static_dict = BROTLI_FALSE;
|
||||
BROTLI_BOOL has_custom_static_dict =
|
||||
dict->num_word_lists > 0 || dict->num_transform_lists > 0;
|
||||
|
||||
/* Check magic header bytes. */
|
||||
if (size < 2) return BROTLI_FALSE;
|
||||
if (encoded[0] != 0x91 || encoded[1] != 0) return BROTLI_FALSE;
|
||||
|
||||
if (!DryParseDictionary(encoded, size, &num_prefix, &is_custom_static_dict)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
if (num_prefix + dict->num_prefix > SHARED_BROTLI_MAX_COMPOUND_DICTS) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
/* Cannot combine different static dictionaries, only prefix dictionaries */
|
||||
if (has_custom_static_dict && is_custom_static_dict) return BROTLI_FALSE;
|
||||
|
||||
return ParseDictionary(encoded, size, dict);
|
||||
}
|
||||
|
||||
#endif /* BROTLI_EXPERIMENTAL */
|
||||
|
||||
void BrotliSharedDictionaryDestroyInstance(
|
||||
BrotliSharedDictionary* dict) {
|
||||
if (!dict) {
|
||||
return;
|
||||
} else {
|
||||
brotli_free_func free_func = dict->free_func;
|
||||
void* opaque = dict->memory_manager_opaque;
|
||||
/* Cleanup. */
|
||||
free_func(opaque, dict->words_instances);
|
||||
free_func(opaque, dict->transforms_instances);
|
||||
free_func(opaque, dict->prefix_suffix_maps);
|
||||
/* Self-destruction. */
|
||||
free_func(opaque, dict);
|
||||
}
|
||||
}
|
||||
|
||||
BROTLI_BOOL BrotliSharedDictionaryAttach(
|
||||
BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,
|
||||
size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {
|
||||
if (!dict) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
#if defined(BROTLI_EXPERIMENTAL)
|
||||
if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {
|
||||
return DecodeSharedDictionary(data, data_size, dict);
|
||||
}
|
||||
#endif /* BROTLI_EXPERIMENTAL */
|
||||
if (type == BROTLI_SHARED_DICTIONARY_RAW) {
|
||||
if (dict->num_prefix >= SHARED_BROTLI_MAX_COMPOUND_DICTS) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
dict->prefix_size[dict->num_prefix] = data_size;
|
||||
dict->prefix[dict->num_prefix] = data;
|
||||
dict->num_prefix++;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
|
||||
BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(
|
||||
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
|
||||
BrotliSharedDictionary* dict = 0;
|
||||
if (!alloc_func && !free_func) {
|
||||
dict = (BrotliSharedDictionary*)malloc(sizeof(BrotliSharedDictionary));
|
||||
} else if (alloc_func && free_func) {
|
||||
dict = (BrotliSharedDictionary*)alloc_func(
|
||||
opaque, sizeof(BrotliSharedDictionary));
|
||||
}
|
||||
if (dict == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(eustas): explicitly initialize all the fields? */
|
||||
memset(dict, 0, sizeof(BrotliSharedDictionary));
|
||||
|
||||
dict->context_based = BROTLI_FALSE;
|
||||
dict->num_dictionaries = 1;
|
||||
dict->num_word_lists = 0;
|
||||
dict->num_transform_lists = 0;
|
||||
|
||||
dict->words[0] = BrotliGetDictionary();
|
||||
dict->transforms[0] = BrotliGetTransforms();
|
||||
|
||||
dict->alloc_func = alloc_func ? alloc_func : BrotliDefaultAllocFunc;
|
||||
dict->free_func = free_func ? free_func : BrotliDefaultFreeFunc;
|
||||
dict->memory_manager_opaque = opaque;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
75
modules/brotli/common/shared_dictionary_internal.h
Normal file
75
modules/brotli/common/shared_dictionary_internal.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* (Transparent) Shared Dictionary definition. */
|
||||
|
||||
#ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
|
||||
#define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
|
||||
|
||||
#include <brotli/shared_dictionary.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "dictionary.h"
|
||||
#include "transform.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct BrotliSharedDictionaryStruct {
|
||||
/* LZ77 prefixes (compound dictionary). */
|
||||
uint32_t num_prefix; /* max SHARED_BROTLI_MAX_COMPOUND_DICTS */
|
||||
size_t prefix_size[SHARED_BROTLI_MAX_COMPOUND_DICTS];
|
||||
const uint8_t* prefix[SHARED_BROTLI_MAX_COMPOUND_DICTS];
|
||||
|
||||
/* If set, the context map is used to select word and transform list from 64
|
||||
contexts, if not set, the context map is not used and only words[0] and
|
||||
transforms[0] are to be used. */
|
||||
BROTLI_BOOL context_based;
|
||||
|
||||
uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
|
||||
|
||||
/* Amount of word_list+transform_list combinations. */
|
||||
uint8_t num_dictionaries;
|
||||
|
||||
/* Must use num_dictionaries values. */
|
||||
const BrotliDictionary* words[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
|
||||
|
||||
/* Must use num_dictionaries values. */
|
||||
const BrotliTransforms* transforms[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
|
||||
|
||||
/* Amount of custom word lists. May be 0 if only Brotli's built-in is used */
|
||||
uint8_t num_word_lists;
|
||||
|
||||
/* Contents of the custom words lists. Must be NULL if num_word_lists is 0. */
|
||||
BrotliDictionary* words_instances;
|
||||
|
||||
/* Amount of custom transform lists. May be 0 if only Brotli's built-in is
|
||||
used */
|
||||
uint8_t num_transform_lists;
|
||||
|
||||
/* Contents of the custom transform lists. Must be NULL if num_transform_lists
|
||||
is 0. */
|
||||
BrotliTransforms* transforms_instances;
|
||||
|
||||
/* Concatenated prefix_suffix_maps of the custom transform lists. Must be NULL
|
||||
if num_transform_lists is 0. */
|
||||
uint16_t* prefix_suffix_maps;
|
||||
|
||||
/* Memory management */
|
||||
brotli_alloc_func alloc_func;
|
||||
brotli_free_func free_func;
|
||||
void* memory_manager_opaque;
|
||||
};
|
||||
|
||||
typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionaryInternal;
|
||||
#define BrotliSharedDictionary BrotliSharedDictionaryInternal
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ */
|
@ -4,7 +4,7 @@
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "./transform.h"
|
||||
#include "transform.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
|
@ -9,18 +9,43 @@
|
||||
#ifndef BROTLI_COMMON_VERSION_H_
|
||||
#define BROTLI_COMMON_VERSION_H_
|
||||
|
||||
/* This macro should only be used when library is compiled together with client.
|
||||
If library is dynamically linked, use BrotliDecoderVersion and
|
||||
/* Compose 3 components into a single number. In a hexadecimal representation
|
||||
B and C components occupy exactly 3 digits. */
|
||||
#define BROTLI_MAKE_HEX_VERSION(A, B, C) ((A << 24) | (B << 12) | C)
|
||||
|
||||
/* Those macros should only be used when library is compiled together with
|
||||
the client. If library is dynamically linked, use BrotliDecoderVersion and
|
||||
BrotliEncoderVersion methods. */
|
||||
|
||||
/* Semantic version, calculated as (MAJOR << 24) | (MINOR << 12) | PATCH */
|
||||
#define BROTLI_VERSION 0x1000009
|
||||
#define BROTLI_VERSION_MAJOR 1
|
||||
#define BROTLI_VERSION_MINOR 1
|
||||
#define BROTLI_VERSION_PATCH 0
|
||||
|
||||
#define BROTLI_VERSION BROTLI_MAKE_HEX_VERSION( \
|
||||
BROTLI_VERSION_MAJOR, BROTLI_VERSION_MINOR, BROTLI_VERSION_PATCH)
|
||||
|
||||
/* This macro is used by build system to produce Libtool-friendly soname. See
|
||||
https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||
Version evolution rules:
|
||||
- interfaces added (or change is compatible) -> current+1:0:age+1
|
||||
- interfaces removed (or changed is incompatible) -> current+1:0:0
|
||||
- interfaces not changed -> current:revision+1:age
|
||||
*/
|
||||
|
||||
/* ABI version, calculated as (CURRENT << 24) | (REVISION << 12) | AGE */
|
||||
#define BROTLI_ABI_VERSION 0x1009000
|
||||
#define BROTLI_ABI_CURRENT 2
|
||||
#define BROTLI_ABI_REVISION 0
|
||||
#define BROTLI_ABI_AGE 1
|
||||
|
||||
#if BROTLI_VERSION_MAJOR != (BROTLI_ABI_CURRENT - BROTLI_ABI_AGE)
|
||||
#error ABI/API version inconsistency
|
||||
#endif
|
||||
|
||||
#if BROTLI_VERSION_MINOR != BROTLI_ABI_AGE
|
||||
#error ABI/API version inconsistency
|
||||
#endif
|
||||
|
||||
#if BROTLI_VERSION_PATCH != BROTLI_ABI_REVISION
|
||||
#error ABI/API version inconsistency
|
||||
#endif
|
||||
|
||||
#endif /* BROTLI_COMMON_VERSION_H_ */
|
||||
|
@ -6,16 +6,17 @@
|
||||
|
||||
/* Bit reading helpers */
|
||||
|
||||
#include "./bit_reader.h"
|
||||
#include "bit_reader.h"
|
||||
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "../common/platform.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const uint32_t kBrotliBitMask[33] = { 0x00000000,
|
||||
const brotli_reg_t kBrotliBitMask[33] = { 0x00000000,
|
||||
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
|
||||
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
|
||||
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
|
||||
@ -28,7 +29,7 @@ const uint32_t kBrotliBitMask[33] = { 0x00000000,
|
||||
|
||||
void BrotliInitBitReader(BrotliBitReader* const br) {
|
||||
br->val_ = 0;
|
||||
br->bit_pos_ = sizeof(br->val_) << 3;
|
||||
br->bit_pos_ = 0;
|
||||
}
|
||||
|
||||
BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
|
||||
@ -36,10 +37,11 @@ BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
|
||||
/* Fixing alignment after unaligned BrotliFillWindow would result accumulator
|
||||
overflow. If unalignment is caused by BrotliSafeReadBits, then there is
|
||||
enough space in accumulator to fix alignment. */
|
||||
if (!BROTLI_ALIGNED_READ) {
|
||||
if (BROTLI_UNALIGNED_READ_FAST) {
|
||||
aligned_read_mask = 0;
|
||||
}
|
||||
if (BrotliGetAvailableBits(br) == 0) {
|
||||
br->val_ = 0;
|
||||
if (!BrotliPullByte(br)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
@ -55,9 +57,9 @@ BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
|
||||
}
|
||||
|
||||
BROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,
|
||||
uint32_t n_bits, uint32_t* val) {
|
||||
uint32_t low_val;
|
||||
uint32_t high_val;
|
||||
brotli_reg_t n_bits, brotli_reg_t* val) {
|
||||
brotli_reg_t low_val;
|
||||
brotli_reg_t high_val;
|
||||
BrotliBitReaderState memento;
|
||||
BROTLI_DCHECK(n_bits <= 32);
|
||||
BROTLI_DCHECK(n_bits > 24);
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "../common/constants.h"
|
||||
#include "../common/platform.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
@ -21,13 +22,16 @@ extern "C" {
|
||||
|
||||
#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)
|
||||
|
||||
BROTLI_INTERNAL extern const uint32_t kBrotliBitMask[33];
|
||||
/* 162 bits + 7 bytes */
|
||||
#define BROTLI_FAST_INPUT_SLACK 28
|
||||
|
||||
static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
|
||||
BROTLI_INTERNAL extern const brotli_reg_t kBrotliBitMask[33];
|
||||
|
||||
static BROTLI_INLINE brotli_reg_t BitMask(brotli_reg_t n) {
|
||||
if (BROTLI_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);
|
||||
return ~(~((brotli_reg_t)0) << n);
|
||||
} else {
|
||||
return kBrotliBitMask[n];
|
||||
}
|
||||
@ -35,40 +39,57 @@ static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
|
||||
|
||||
typedef struct {
|
||||
brotli_reg_t val_; /* pre-fetched bits */
|
||||
uint32_t bit_pos_; /* current bit-reading position in val_ */
|
||||
brotli_reg_t bit_pos_; /* current bit-reading position in val_ */
|
||||
const uint8_t* next_in; /* the byte we're reading from */
|
||||
size_t avail_in;
|
||||
const uint8_t* guard_in; /* position from which "fast-path" is prohibited */
|
||||
const uint8_t* last_in; /* == next_in + avail_in */
|
||||
} BrotliBitReader;
|
||||
|
||||
typedef struct {
|
||||
brotli_reg_t val_;
|
||||
uint32_t bit_pos_;
|
||||
brotli_reg_t bit_pos_;
|
||||
const uint8_t* next_in;
|
||||
size_t avail_in;
|
||||
} BrotliBitReaderState;
|
||||
|
||||
/* Initializes the BrotliBitReader fields. */
|
||||
BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
|
||||
BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* br);
|
||||
|
||||
/* Ensures that accumulator is not empty.
|
||||
May consume up to sizeof(brotli_reg_t) - 1 bytes of input.
|
||||
Returns BROTLI_FALSE if data is required but there is no input available.
|
||||
For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned
|
||||
reading. */
|
||||
BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);
|
||||
For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for
|
||||
aligned reading. */
|
||||
BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* br);
|
||||
|
||||
/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
|
||||
the main code-path. Never called for RFC brotli streams, required only for
|
||||
"large-window" mode and other extensions. */
|
||||
BROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val);
|
||||
BrotliBitReader* br, brotli_reg_t n_bits, brotli_reg_t* val);
|
||||
|
||||
static BROTLI_INLINE size_t
|
||||
BrotliBitReaderGetAvailIn(BrotliBitReader* const br) {
|
||||
return (size_t)(br->last_in - br->next_in);
|
||||
}
|
||||
|
||||
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;
|
||||
to->avail_in = BrotliBitReaderGetAvailIn(from);
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void BrotliBitReaderSetInput(
|
||||
BrotliBitReader* const br, const uint8_t* next_in, size_t avail_in) {
|
||||
br->next_in = next_in;
|
||||
br->last_in = (avail_in == 0) ? next_in : (next_in + avail_in);
|
||||
if (avail_in + 1 > BROTLI_FAST_INPUT_SLACK) {
|
||||
br->guard_in = next_in + (avail_in + 1 - BROTLI_FAST_INPUT_SLACK);
|
||||
} else {
|
||||
br->guard_in = next_in;
|
||||
}
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void BrotliBitReaderRestoreState(
|
||||
@ -76,12 +97,12 @@ static BROTLI_INLINE void BrotliBitReaderRestoreState(
|
||||
to->val_ = from->val_;
|
||||
to->bit_pos_ = from->bit_pos_;
|
||||
to->next_in = from->next_in;
|
||||
to->avail_in = from->avail_in;
|
||||
BrotliBitReaderSetInput(to, from->next_in, from->avail_in);
|
||||
}
|
||||
|
||||
static BROTLI_INLINE uint32_t BrotliGetAvailableBits(
|
||||
static BROTLI_INLINE brotli_reg_t BrotliGetAvailableBits(
|
||||
const BrotliBitReader* br) {
|
||||
return (BROTLI_64_BITS ? 64 : 32) - br->bit_pos_;
|
||||
return br->bit_pos_;
|
||||
}
|
||||
|
||||
/* Returns amount of unread bytes the bit reader still has buffered from the
|
||||
@ -89,15 +110,27 @@ static BROTLI_INLINE uint32_t BrotliGetAvailableBits(
|
||||
maximal ring-buffer size (larger number won't be utilized anyway). */
|
||||
static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
|
||||
static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;
|
||||
if (br->avail_in > kCap) return kCap;
|
||||
return br->avail_in + (BrotliGetAvailableBits(br) >> 3);
|
||||
size_t avail_in = BrotliBitReaderGetAvailIn(br);
|
||||
if (avail_in > kCap) return kCap;
|
||||
return avail_in + (BrotliGetAvailableBits(br) >> 3);
|
||||
}
|
||||
|
||||
/* Checks if there is at least |num| bytes left in the input ring-buffer
|
||||
(excluding the bits remaining in br->val_). */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(
|
||||
BrotliBitReader* const br, size_t num) {
|
||||
return TO_BROTLI_BOOL(br->avail_in >= num);
|
||||
BrotliBitReader* const br) {
|
||||
return TO_BROTLI_BOOL(br->next_in < br->guard_in);
|
||||
}
|
||||
|
||||
/* Load more bits into accumulator. */
|
||||
static BROTLI_INLINE brotli_reg_t BrotliBitReaderLoadBits(brotli_reg_t val,
|
||||
brotli_reg_t new_bits,
|
||||
brotli_reg_t count,
|
||||
brotli_reg_t offset) {
|
||||
BROTLI_DCHECK(
|
||||
!((val >> offset) & ~new_bits & ~(~((brotli_reg_t)0) << count)));
|
||||
(void)count;
|
||||
return val | (new_bits << offset);
|
||||
}
|
||||
|
||||
/* Guarantees that there are at least |n_bits| + 1 bits in accumulator.
|
||||
@ -105,49 +138,51 @@ static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(
|
||||
|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, uint32_t n_bits) {
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits) {
|
||||
#if (BROTLI_64_BITS)
|
||||
if (!BROTLI_ALIGNED_READ && BROTLI_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_ |= BROTLI_UNALIGNED_LOAD64LE(br->next_in) << 8;
|
||||
br->avail_in -= 7;
|
||||
if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
|
||||
(n_bits <= 8)) {
|
||||
brotli_reg_t bit_pos = br->bit_pos_;
|
||||
if (bit_pos <= 8) {
|
||||
br->val_ = BrotliBitReaderLoadBits(br->val_,
|
||||
BROTLI_UNALIGNED_LOAD64LE(br->next_in), 56, bit_pos);
|
||||
br->bit_pos_ = bit_pos + 56;
|
||||
br->next_in += 7;
|
||||
}
|
||||
} else if (
|
||||
!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 16)) {
|
||||
if (br->bit_pos_ >= 48) {
|
||||
br->val_ >>= 48;
|
||||
br->bit_pos_ ^= 48; /* here same as -= 48 because of the if condition */
|
||||
br->val_ |= BROTLI_UNALIGNED_LOAD64LE(br->next_in) << 16;
|
||||
br->avail_in -= 6;
|
||||
} else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
|
||||
(n_bits <= 16)) {
|
||||
brotli_reg_t bit_pos = br->bit_pos_;
|
||||
if (bit_pos <= 16) {
|
||||
br->val_ = BrotliBitReaderLoadBits(br->val_,
|
||||
BROTLI_UNALIGNED_LOAD64LE(br->next_in), 48, bit_pos);
|
||||
br->bit_pos_ = bit_pos + 48;
|
||||
br->next_in += 6;
|
||||
}
|
||||
} else {
|
||||
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)BROTLI_UNALIGNED_LOAD32LE(br->next_in)) << 32;
|
||||
br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
|
||||
brotli_reg_t bit_pos = br->bit_pos_;
|
||||
if (bit_pos <= 32) {
|
||||
br->val_ = BrotliBitReaderLoadBits(br->val_,
|
||||
(uint64_t)BROTLI_UNALIGNED_LOAD32LE(br->next_in), 32, bit_pos);
|
||||
br->bit_pos_ = bit_pos + 32;
|
||||
br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!BROTLI_ALIGNED_READ && BROTLI_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_ |= BROTLI_UNALIGNED_LOAD32LE(br->next_in) << 8;
|
||||
br->avail_in -= 3;
|
||||
if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
|
||||
(n_bits <= 8)) {
|
||||
brotli_reg_t bit_pos = br->bit_pos_;
|
||||
if (bit_pos <= 8) {
|
||||
br->val_ = BrotliBitReaderLoadBits(br->val_,
|
||||
BROTLI_UNALIGNED_LOAD32LE(br->next_in), 24, bit_pos);
|
||||
br->bit_pos_ = bit_pos + 24;
|
||||
br->next_in += 3;
|
||||
}
|
||||
} else {
|
||||
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)BROTLI_UNALIGNED_LOAD16LE(br->next_in)) << 16;
|
||||
br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
|
||||
brotli_reg_t bit_pos = br->bit_pos_;
|
||||
if (bit_pos <= 16) {
|
||||
br->val_ = BrotliBitReaderLoadBits(br->val_,
|
||||
(uint32_t)BROTLI_UNALIGNED_LOAD16LE(br->next_in), 16, bit_pos);
|
||||
br->bit_pos_ = bit_pos + 16;
|
||||
br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
|
||||
}
|
||||
}
|
||||
@ -163,17 +198,12 @@ static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {
|
||||
/* Tries to pull one byte of input to accumulator.
|
||||
Returns BROTLI_FALSE if there is no input available. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {
|
||||
if (br->avail_in == 0) {
|
||||
if (br->next_in == br->last_in) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
br->val_ >>= 8;
|
||||
#if (BROTLI_64_BITS)
|
||||
br->val_ |= ((uint64_t)*br->next_in) << 56;
|
||||
#else
|
||||
br->val_ |= ((uint32_t)*br->next_in) << 24;
|
||||
#endif
|
||||
br->bit_pos_ -= 8;
|
||||
--br->avail_in;
|
||||
br->val_ = BrotliBitReaderLoadBits(br->val_,
|
||||
(brotli_reg_t)*br->next_in, 8, br->bit_pos_);
|
||||
br->bit_pos_ += 8;
|
||||
++br->next_in;
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
@ -182,81 +212,90 @@ static BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {
|
||||
The number of valid bits could be calculated by BrotliGetAvailableBits. */
|
||||
static BROTLI_INLINE brotli_reg_t BrotliGetBitsUnmasked(
|
||||
BrotliBitReader* const br) {
|
||||
return br->val_ >> br->bit_pos_;
|
||||
return br->val_;
|
||||
}
|
||||
|
||||
/* Like BrotliGetBits, but does not mask the result.
|
||||
The result contains at least 16 valid bits. */
|
||||
static BROTLI_INLINE uint32_t BrotliGet16BitsUnmasked(
|
||||
static BROTLI_INLINE brotli_reg_t BrotliGet16BitsUnmasked(
|
||||
BrotliBitReader* const br) {
|
||||
BrotliFillBitWindow(br, 16);
|
||||
return (uint32_t)BrotliGetBitsUnmasked(br);
|
||||
return (brotli_reg_t)BrotliGetBitsUnmasked(br);
|
||||
}
|
||||
|
||||
/* Returns the specified number of bits from |br| without advancing bit
|
||||
position. */
|
||||
static BROTLI_INLINE uint32_t BrotliGetBits(
|
||||
BrotliBitReader* const br, uint32_t n_bits) {
|
||||
static BROTLI_INLINE brotli_reg_t BrotliGetBits(
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits) {
|
||||
BrotliFillBitWindow(br, n_bits);
|
||||
return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
return BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
}
|
||||
|
||||
/* Tries to peek the specified amount of bits. Returns BROTLI_FALSE, if there
|
||||
is not enough input. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
|
||||
while (BrotliGetAvailableBits(br) < n_bits) {
|
||||
if (!BrotliPullByte(br)) {
|
||||
return BROTLI_FALSE;
|
||||
}
|
||||
}
|
||||
*val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
*val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
/* Advances the bit pos by |n_bits|. */
|
||||
static BROTLI_INLINE void BrotliDropBits(
|
||||
BrotliBitReader* const br, uint32_t n_bits) {
|
||||
br->bit_pos_ += n_bits;
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits) {
|
||||
br->bit_pos_ -= n_bits;
|
||||
br->val_ >>= n_bits;
|
||||
}
|
||||
|
||||
/* Make sure that there are no spectre bits in accumulator.
|
||||
This is important for the cases when some bytes are skipped
|
||||
(i.e. never placed into accumulator). */
|
||||
static BROTLI_INLINE void BrotliBitReaderNormalize(BrotliBitReader* br) {
|
||||
/* Actually, it is enough to normalize when br->bit_pos_ == 0 */
|
||||
if (br->bit_pos_ < (sizeof(brotli_reg_t) << 3u)) {
|
||||
br->val_ &= (((brotli_reg_t)1) << br->bit_pos_) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
brotli_reg_t unused_bytes = BrotliGetAvailableBits(br) >> 3;
|
||||
brotli_reg_t unused_bits = unused_bytes << 3;
|
||||
br->next_in =
|
||||
(unused_bytes == 0) ? br->next_in : (br->next_in - unused_bytes);
|
||||
br->bit_pos_ -= unused_bits;
|
||||
BrotliBitReaderNormalize(br);
|
||||
}
|
||||
|
||||
/* 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, uint32_t n_bits, uint32_t* val) {
|
||||
*val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
static BROTLI_INLINE void BrotliTakeBits(BrotliBitReader* const br,
|
||||
brotli_reg_t n_bits,
|
||||
brotli_reg_t* val) {
|
||||
*val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);
|
||||
BROTLI_LOG(("[BrotliTakeBits] %d %d %d val: %6x\n",
|
||||
(int)br->avail_in, (int)br->bit_pos_, (int)n_bits, (int)*val));
|
||||
(int)BrotliBitReaderGetAvailIn(br), (int)br->bit_pos_,
|
||||
(int)n_bits, (int)*val));
|
||||
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.
|
||||
Up to 24 bits are allowed to be requested from this method. */
|
||||
static BROTLI_INLINE uint32_t BrotliReadBits24(
|
||||
BrotliBitReader* const br, uint32_t n_bits) {
|
||||
static BROTLI_INLINE brotli_reg_t BrotliReadBits24(
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits) {
|
||||
BROTLI_DCHECK(n_bits <= 24);
|
||||
if (BROTLI_64_BITS || (n_bits <= 16)) {
|
||||
uint32_t val;
|
||||
brotli_reg_t val;
|
||||
BrotliFillBitWindow(br, n_bits);
|
||||
BrotliTakeBits(br, n_bits, &val);
|
||||
return val;
|
||||
} else {
|
||||
uint32_t low_val;
|
||||
uint32_t high_val;
|
||||
brotli_reg_t low_val;
|
||||
brotli_reg_t high_val;
|
||||
BrotliFillBitWindow(br, 16);
|
||||
BrotliTakeBits(br, 16, &low_val);
|
||||
BrotliFillBitWindow(br, 8);
|
||||
@ -266,17 +305,17 @@ static BROTLI_INLINE uint32_t BrotliReadBits24(
|
||||
}
|
||||
|
||||
/* Same as BrotliReadBits24, but allows reading up to 32 bits. */
|
||||
static BROTLI_INLINE uint32_t BrotliReadBits32(
|
||||
BrotliBitReader* const br, uint32_t n_bits) {
|
||||
static BROTLI_INLINE brotli_reg_t BrotliReadBits32(
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits) {
|
||||
BROTLI_DCHECK(n_bits <= 32);
|
||||
if (BROTLI_64_BITS || (n_bits <= 16)) {
|
||||
uint32_t val;
|
||||
brotli_reg_t val;
|
||||
BrotliFillBitWindow(br, n_bits);
|
||||
BrotliTakeBits(br, n_bits, &val);
|
||||
return val;
|
||||
} else {
|
||||
uint32_t low_val;
|
||||
uint32_t high_val;
|
||||
brotli_reg_t low_val;
|
||||
brotli_reg_t high_val;
|
||||
BrotliFillBitWindow(br, 16);
|
||||
BrotliTakeBits(br, 16, &low_val);
|
||||
BrotliFillBitWindow(br, 16);
|
||||
@ -289,7 +328,7 @@ static BROTLI_INLINE uint32_t BrotliReadBits32(
|
||||
is not enough input. |n_bits| MUST be positive.
|
||||
Up to 24 bits are allowed to be requested from this method. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
|
||||
BROTLI_DCHECK(n_bits <= 24);
|
||||
while (BrotliGetAvailableBits(br) < n_bits) {
|
||||
if (!BrotliPullByte(br)) {
|
||||
@ -302,7 +341,7 @@ static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
|
||||
|
||||
/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(
|
||||
BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
|
||||
BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {
|
||||
BROTLI_DCHECK(n_bits <= 32);
|
||||
if (BROTLI_64_BITS || (n_bits <= 24)) {
|
||||
while (BrotliGetAvailableBits(br) < n_bits) {
|
||||
@ -320,14 +359,22 @@ static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(
|
||||
/* Advances the bit reader position to the next byte boundary and verifies
|
||||
that any skipped bits are set to zero. */
|
||||
static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
|
||||
uint32_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;
|
||||
uint32_t pad_bits = 0;
|
||||
brotli_reg_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;
|
||||
brotli_reg_t pad_bits = 0;
|
||||
if (pad_bits_count != 0) {
|
||||
BrotliTakeBits(br, pad_bits_count, &pad_bits);
|
||||
}
|
||||
BrotliBitReaderNormalize(br);
|
||||
return TO_BROTLI_BOOL(pad_bits == 0);
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {
|
||||
/* Check detour is legal: accumulator must to be empty. */
|
||||
BROTLI_DCHECK(br->bit_pos_ == 0);
|
||||
BROTLI_DCHECK(br->val_ == 0);
|
||||
br->next_in += num;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@ -339,9 +386,34 @@ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
|
||||
++dest;
|
||||
--num;
|
||||
}
|
||||
memcpy(dest, br->next_in, num);
|
||||
br->avail_in -= num;
|
||||
br->next_in += num;
|
||||
BrotliBitReaderNormalize(br);
|
||||
if (num > 0) {
|
||||
memcpy(dest, br->next_in, num);
|
||||
BrotliDropBytes(br, num);
|
||||
}
|
||||
}
|
||||
|
||||
BROTLI_UNUSED_FUNCTION void BrotliBitReaderSuppressUnusedFunctions(void) {
|
||||
BROTLI_UNUSED(&BrotliBitReaderSuppressUnusedFunctions);
|
||||
|
||||
BROTLI_UNUSED(&BrotliBitReaderGetAvailIn);
|
||||
BROTLI_UNUSED(&BrotliBitReaderLoadBits);
|
||||
BROTLI_UNUSED(&BrotliBitReaderRestoreState);
|
||||
BROTLI_UNUSED(&BrotliBitReaderSaveState);
|
||||
BROTLI_UNUSED(&BrotliBitReaderSetInput);
|
||||
BROTLI_UNUSED(&BrotliBitReaderUnload);
|
||||
BROTLI_UNUSED(&BrotliCheckInputAmount);
|
||||
BROTLI_UNUSED(&BrotliCopyBytes);
|
||||
BROTLI_UNUSED(&BrotliFillBitWindow16);
|
||||
BROTLI_UNUSED(&BrotliGet16BitsUnmasked);
|
||||
BROTLI_UNUSED(&BrotliGetBits);
|
||||
BROTLI_UNUSED(&BrotliGetRemainingBytes);
|
||||
BROTLI_UNUSED(&BrotliJumpToByteBoundary);
|
||||
BROTLI_UNUSED(&BrotliReadBits24);
|
||||
BROTLI_UNUSED(&BrotliReadBits32);
|
||||
BROTLI_UNUSED(&BrotliSafeGetBits);
|
||||
BROTLI_UNUSED(&BrotliSafeReadBits);
|
||||
BROTLI_UNUSED(&BrotliSafeReadBits32);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,13 +6,14 @@
|
||||
|
||||
/* Utilities for building Huffman decoding tables. */
|
||||
|
||||
#include "./huffman.h"
|
||||
#include "huffman.h"
|
||||
|
||||
#include <string.h> /* memcpy, memset */
|
||||
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "../common/constants.h"
|
||||
#include "../common/platform.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
@ -117,11 +118,13 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
|
||||
int bits_count;
|
||||
BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <=
|
||||
BROTLI_REVERSE_BITS_MAX);
|
||||
BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5);
|
||||
|
||||
/* Generate offsets into sorted symbol table by code length. */
|
||||
symbol = -1;
|
||||
bits = 1;
|
||||
BROTLI_REPEAT(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH, {
|
||||
/* BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5 */
|
||||
BROTLI_REPEAT_5({
|
||||
symbol += count[bits];
|
||||
offset[bits] = symbol;
|
||||
bits++;
|
||||
@ -132,7 +135,7 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
|
||||
/* Sort symbols by length, by symbol order within each length. */
|
||||
symbol = BROTLI_CODE_LENGTH_CODES;
|
||||
do {
|
||||
BROTLI_REPEAT(6, {
|
||||
BROTLI_REPEAT_6({
|
||||
symbol--;
|
||||
sorted[offset[code_lengths[symbol]]--] = symbol;
|
||||
});
|
||||
|
@ -9,9 +9,10 @@
|
||||
#ifndef BROTLI_DEC_HUFFMAN_H_
|
||||
#define BROTLI_DEC_HUFFMAN_H_
|
||||
|
||||
#include "../common/platform.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "../common/platform.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -10,9 +10,10 @@
|
||||
#ifndef BROTLI_DEC_PREFIX_H_
|
||||
#define BROTLI_DEC_PREFIX_H_
|
||||
|
||||
#include "../common/constants.h"
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "../common/constants.h"
|
||||
|
||||
typedef struct CmdLutElement {
|
||||
uint8_t insert_len_extra_bits;
|
||||
uint8_t copy_len_extra_bits;
|
||||
|
@ -4,12 +4,14 @@
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "./state.h"
|
||||
#include "state.h"
|
||||
|
||||
#include <stdlib.h> /* free, malloc */
|
||||
|
||||
#include <brotli/types.h>
|
||||
#include "./huffman.h"
|
||||
|
||||
#include "../common/dictionary.h"
|
||||
#include "huffman.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
@ -42,6 +44,7 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
|
||||
s->pos = 0;
|
||||
s->rb_roundtrips = 0;
|
||||
s->partial_pos_out = 0;
|
||||
s->used_input = 0;
|
||||
|
||||
s->block_type_trees = NULL;
|
||||
s->block_len_trees = NULL;
|
||||
@ -81,17 +84,23 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
|
||||
|
||||
s->mtf_upper_bound = 63;
|
||||
|
||||
s->dictionary = BrotliGetDictionary();
|
||||
s->transforms = BrotliGetTransforms();
|
||||
s->compound_dictionary = NULL;
|
||||
s->dictionary =
|
||||
BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);
|
||||
if (!s->dictionary) return BROTLI_FALSE;
|
||||
|
||||
s->metadata_start_func = NULL;
|
||||
s->metadata_chunk_func = NULL;
|
||||
s->metadata_callback_opaque = 0;
|
||||
|
||||
return BROTLI_TRUE;
|
||||
}
|
||||
|
||||
void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s) {
|
||||
s->meta_block_remaining_len = 0;
|
||||
s->block_length[0] = 1U << 24;
|
||||
s->block_length[1] = 1U << 24;
|
||||
s->block_length[2] = 1U << 24;
|
||||
s->block_length[0] = BROTLI_BLOCK_SIZE_CAP;
|
||||
s->block_length[1] = BROTLI_BLOCK_SIZE_CAP;
|
||||
s->block_length[2] = BROTLI_BLOCK_SIZE_CAP;
|
||||
s->num_block_types[0] = 1;
|
||||
s->num_block_types[1] = 1;
|
||||
s->num_block_types[2] = 1;
|
||||
@ -126,16 +135,31 @@ void BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) {
|
||||
BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees);
|
||||
}
|
||||
|
||||
#ifdef BROTLI_REPORTING
|
||||
/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */
|
||||
void BrotliDecoderOnFinish(const BrotliDecoderState* s);
|
||||
#define BROTLI_DECODER_ON_FINISH(s) BrotliDecoderOnFinish(s);
|
||||
#else
|
||||
#if !defined(BROTLI_DECODER_ON_FINISH)
|
||||
#define BROTLI_DECODER_ON_FINISH(s) (void)(s);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
|
||||
BrotliDecoderStateCleanupAfterMetablock(s);
|
||||
|
||||
BROTLI_DECODER_ON_FINISH(s);
|
||||
|
||||
BROTLI_DECODER_FREE(s, s->compound_dictionary);
|
||||
BrotliSharedDictionaryDestroyInstance(s->dictionary);
|
||||
s->dictionary = NULL;
|
||||
BROTLI_DECODER_FREE(s, s->ringbuffer);
|
||||
BROTLI_DECODER_FREE(s, s->block_type_trees);
|
||||
}
|
||||
|
||||
BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,
|
||||
HuffmanTreeGroup* group, uint32_t alphabet_size_max,
|
||||
uint32_t alphabet_size_limit, uint32_t ntrees) {
|
||||
HuffmanTreeGroup* group, brotli_reg_t alphabet_size_max,
|
||||
brotli_reg_t alphabet_size_limit, brotli_reg_t ntrees) {
|
||||
/* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)
|
||||
This number is discovered "unlimited" "enough" calculator; it is actually
|
||||
a wee bigger than required in several cases (especially for alphabets with
|
||||
|
@ -9,13 +9,16 @@
|
||||
#ifndef BROTLI_DEC_STATE_H_
|
||||
#define BROTLI_DEC_STATE_H_
|
||||
|
||||
#include <brotli/decode.h>
|
||||
#include <brotli/shared_dictionary.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
#include "../common/constants.h"
|
||||
#include "../common/dictionary.h"
|
||||
#include "../common/platform.h"
|
||||
#include "../common/transform.h"
|
||||
#include <brotli/types.h>
|
||||
#include "./bit_reader.h"
|
||||
#include "./huffman.h"
|
||||
#include "bit_reader.h"
|
||||
#include "huffman.h"
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
@ -189,20 +192,34 @@ typedef enum {
|
||||
BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
|
||||
} BrotliRunningReadBlockLengthState;
|
||||
|
||||
/* BrotliDecoderState addon, used for Compound Dictionary functionality. */
|
||||
typedef struct BrotliDecoderCompoundDictionary {
|
||||
int num_chunks;
|
||||
int total_size;
|
||||
int br_index;
|
||||
int br_offset;
|
||||
int br_length;
|
||||
int br_copied;
|
||||
const uint8_t* chunks[16];
|
||||
int chunk_offsets[16];
|
||||
int block_bits;
|
||||
uint8_t block_map[256];
|
||||
} BrotliDecoderCompoundDictionary;
|
||||
|
||||
typedef struct BrotliMetablockHeaderArena {
|
||||
BrotliRunningTreeGroupState substate_tree_group;
|
||||
BrotliRunningContextMapState substate_context_map;
|
||||
BrotliRunningHuffmanState substate_huffman;
|
||||
|
||||
uint32_t sub_loop_counter;
|
||||
brotli_reg_t sub_loop_counter;
|
||||
|
||||
uint32_t repeat_code_len;
|
||||
uint32_t prev_code_len;
|
||||
brotli_reg_t repeat_code_len;
|
||||
brotli_reg_t prev_code_len;
|
||||
|
||||
/* For ReadHuffmanCode. */
|
||||
uint32_t symbol;
|
||||
uint32_t repeat;
|
||||
uint32_t space;
|
||||
brotli_reg_t symbol;
|
||||
brotli_reg_t repeat;
|
||||
brotli_reg_t space;
|
||||
|
||||
/* Huffman table for "histograms". */
|
||||
HuffmanCode table[32];
|
||||
@ -216,21 +233,22 @@ typedef struct BrotliMetablockHeaderArena {
|
||||
uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
|
||||
/* Population counts for the code lengths. */
|
||||
uint16_t code_length_histo[16];
|
||||
/* TODO(eustas): +2 bytes padding */
|
||||
|
||||
/* For HuffmanTreeGroupDecode. */
|
||||
int htree_index;
|
||||
HuffmanCode* next;
|
||||
|
||||
/* For DecodeContextMap. */
|
||||
uint32_t context_index;
|
||||
uint32_t max_run_length_prefix;
|
||||
uint32_t code;
|
||||
brotli_reg_t context_index;
|
||||
brotli_reg_t max_run_length_prefix;
|
||||
brotli_reg_t code;
|
||||
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
|
||||
} BrotliMetablockHeaderArena;
|
||||
|
||||
typedef struct BrotliMetablockBodyArena {
|
||||
uint8_t dist_extra_bits[544];
|
||||
uint32_t dist_offset[544];
|
||||
brotli_reg_t dist_offset[544];
|
||||
} BrotliMetablockBodyArena;
|
||||
|
||||
struct BrotliDecoderStateStruct {
|
||||
@ -251,7 +269,7 @@ struct BrotliDecoderStateStruct {
|
||||
uint64_t u64;
|
||||
uint8_t u8[8];
|
||||
} buffer;
|
||||
uint32_t buffer_length;
|
||||
brotli_reg_t buffer_length;
|
||||
|
||||
int pos;
|
||||
int max_backward_distance;
|
||||
@ -261,6 +279,8 @@ struct BrotliDecoderStateStruct {
|
||||
int dist_rb_idx;
|
||||
int dist_rb[4];
|
||||
int error_code;
|
||||
int meta_block_remaining_len;
|
||||
|
||||
uint8_t* ringbuffer;
|
||||
uint8_t* ringbuffer_end;
|
||||
HuffmanCode* htree_command;
|
||||
@ -281,54 +301,64 @@ struct BrotliDecoderStateStruct {
|
||||
/* Distance context is actual after command is decoded and before distance is
|
||||
computed. After distance computation it is used as a temporary variable. */
|
||||
int distance_context;
|
||||
int meta_block_remaining_len;
|
||||
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;
|
||||
uint32_t num_dist_htrees;
|
||||
brotli_reg_t block_length[3];
|
||||
brotli_reg_t block_length_index;
|
||||
brotli_reg_t num_block_types[3];
|
||||
brotli_reg_t block_type_rb[6];
|
||||
brotli_reg_t distance_postfix_bits;
|
||||
brotli_reg_t num_direct_distance_codes;
|
||||
brotli_reg_t num_dist_htrees;
|
||||
uint8_t* dist_context_map;
|
||||
HuffmanCode* literal_htree;
|
||||
uint8_t dist_htree_index;
|
||||
|
||||
int copy_length;
|
||||
int distance_code;
|
||||
|
||||
/* For partial write operations. */
|
||||
size_t rb_roundtrips; /* how many times we went around the ring-buffer */
|
||||
size_t partial_pos_out; /* how much output to the user in total */
|
||||
|
||||
/* For InverseMoveToFrontTransform. */
|
||||
uint32_t mtf_upper_bound;
|
||||
brotli_reg_t mtf_upper_bound;
|
||||
uint32_t mtf[64 + 1];
|
||||
|
||||
int copy_length;
|
||||
int distance_code;
|
||||
|
||||
uint8_t dist_htree_index;
|
||||
/* TODO(eustas): +3 bytes padding */
|
||||
|
||||
/* Less used attributes are at the end of this struct. */
|
||||
|
||||
brotli_decoder_metadata_start_func metadata_start_func;
|
||||
brotli_decoder_metadata_chunk_func metadata_chunk_func;
|
||||
void* metadata_callback_opaque;
|
||||
|
||||
/* For reporting. */
|
||||
uint64_t used_input; /* how many bytes of input are consumed */
|
||||
|
||||
/* States inside function calls. */
|
||||
BrotliRunningMetablockHeaderState substate_metablock_header;
|
||||
BrotliRunningUncompressedState substate_uncompressed;
|
||||
BrotliRunningDecodeUint8State substate_decode_uint8;
|
||||
BrotliRunningReadBlockLengthState substate_read_block_length;
|
||||
|
||||
int new_ringbuffer_size;
|
||||
/* TODO(eustas): +4 bytes padding */
|
||||
|
||||
unsigned int is_last_metablock : 1;
|
||||
unsigned int is_uncompressed : 1;
|
||||
unsigned int is_metadata : 1;
|
||||
unsigned int should_wrap_ringbuffer : 1;
|
||||
unsigned int canny_ringbuffer_allocation : 1;
|
||||
unsigned int large_window : 1;
|
||||
unsigned int window_bits : 6;
|
||||
unsigned int size_nibbles : 8;
|
||||
uint32_t window_bits;
|
||||
/* TODO(eustas): +12 bits padding */
|
||||
|
||||
int new_ringbuffer_size;
|
||||
|
||||
uint32_t num_literal_htrees;
|
||||
brotli_reg_t num_literal_htrees;
|
||||
uint8_t* context_map;
|
||||
uint8_t* context_modes;
|
||||
|
||||
const BrotliDictionary* dictionary;
|
||||
const BrotliTransforms* transforms;
|
||||
BrotliSharedDictionary* dictionary;
|
||||
BrotliDecoderCompoundDictionary* compound_dictionary;
|
||||
|
||||
uint32_t trivial_literal_contexts[8]; /* 256 bits */
|
||||
|
||||
@ -348,8 +378,9 @@ BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);
|
||||
BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(
|
||||
BrotliDecoderState* s);
|
||||
BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
|
||||
BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size_max,
|
||||
uint32_t alphabet_size_limit, uint32_t ntrees);
|
||||
BrotliDecoderState* s, HuffmanTreeGroup* group,
|
||||
brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,
|
||||
brotli_reg_t ntrees);
|
||||
|
||||
#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
|
||||
|
||||
@ -358,6 +389,10 @@ BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
|
||||
X = NULL; \
|
||||
}
|
||||
|
||||
/* Literal/Command/Distance block size maximum; same as maximum metablock size;
|
||||
used as block size when there is no block switching. */
|
||||
#define BROTLI_BLOCK_SIZE_CAP (1U << 24)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define BROTLI_DEC_DECODE_H_
|
||||
|
||||
#include <brotli/port.h>
|
||||
#include <brotli/shared_dictionary.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
@ -85,8 +86,9 @@ typedef enum {
|
||||
BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \
|
||||
\
|
||||
/* -17..-18 codes are reserved */ \
|
||||
/* -17 code is reserved */ \
|
||||
\
|
||||
BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \
|
||||
\
|
||||
@ -154,6 +156,28 @@ typedef enum BrotliDecoderParameter {
|
||||
BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter(
|
||||
BrotliDecoderState* state, BrotliDecoderParameter param, uint32_t value);
|
||||
|
||||
/**
|
||||
* Adds LZ77 prefix dictionary, adds or replaces built-in static dictionary and
|
||||
* transforms.
|
||||
*
|
||||
* Attached dictionary ownership is not transferred.
|
||||
* Data provided to this method should be kept accessible until
|
||||
* decoding is finished and decoder instance is destroyed.
|
||||
*
|
||||
* @note Dictionaries can NOT be attached after actual decoding is started.
|
||||
*
|
||||
* @param state decoder instance
|
||||
* @param type dictionary data format
|
||||
* @param data_size length of memory region pointed by @p data
|
||||
* @param data dictionary data in format corresponding to @p type
|
||||
* @returns ::BROTLI_FALSE if dictionary is corrupted,
|
||||
* or dictionary count limit is reached
|
||||
* @returns ::BROTLI_TRUE if dictionary is accepted / attached
|
||||
*/
|
||||
BROTLI_DEC_API BROTLI_BOOL BrotliDecoderAttachDictionary(
|
||||
BrotliDecoderState* state, BrotliSharedDictionaryType type,
|
||||
size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);
|
||||
|
||||
/**
|
||||
* Creates an instance of ::BrotliDecoderState and initializes it.
|
||||
*
|
||||
@ -333,10 +357,51 @@ BROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);
|
||||
/**
|
||||
* Gets a decoder library version.
|
||||
*
|
||||
* Look at BROTLI_VERSION for more information.
|
||||
* Look at BROTLI_MAKE_HEX_VERSION for more information.
|
||||
*/
|
||||
BROTLI_DEC_API uint32_t BrotliDecoderVersion(void);
|
||||
|
||||
/**
|
||||
* Callback to fire on metadata block start.
|
||||
*
|
||||
* After this callback is fired, if @p size is not @c 0, it is followed by
|
||||
* ::brotli_decoder_metadata_chunk_func as more metadata block contents become
|
||||
* accessible.
|
||||
*
|
||||
* @param opaque callback handle
|
||||
* @param size size of metadata block
|
||||
*/
|
||||
typedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size);
|
||||
|
||||
/**
|
||||
* Callback to fire on metadata block chunk becomes available.
|
||||
*
|
||||
* This function can be invoked multiple times per metadata block; block should
|
||||
* be considered finished when sum of @p size matches the announced metadata
|
||||
* block size. Chunks contents pointed by @p data are transient and shouln not
|
||||
* be accessed after leaving the callback.
|
||||
*
|
||||
* @param opaque callback handle
|
||||
* @param data pointer to metadata contents
|
||||
* @param size size of metadata block chunk, at least @c 1
|
||||
*/
|
||||
typedef void (*brotli_decoder_metadata_chunk_func)(void* opaque,
|
||||
const uint8_t* data,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* Sets callback for receiving metadata blocks.
|
||||
*
|
||||
* @param state decoder instance
|
||||
* @param start_func callback on metadata block start
|
||||
* @param chunk_func callback on metadata block chunk
|
||||
* @param opaque callback handle
|
||||
*/
|
||||
BROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks(
|
||||
BrotliDecoderState* state,
|
||||
brotli_decoder_metadata_start_func start_func,
|
||||
brotli_decoder_metadata_chunk_func chunk_func, void* opaque);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define BROTLI_ENC_ENCODE_H_
|
||||
|
||||
#include <brotli/port.h>
|
||||
#include <brotli/shared_dictionary.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
@ -269,6 +270,51 @@ BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance(
|
||||
*/
|
||||
BROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state);
|
||||
|
||||
/* Opaque type for pointer to different possible internal structures containing
|
||||
dictionary prepared for the encoder */
|
||||
typedef struct BrotliEncoderPreparedDictionaryStruct
|
||||
BrotliEncoderPreparedDictionary;
|
||||
|
||||
/**
|
||||
* Prepares a shared dictionary from the given file format for the encoder.
|
||||
*
|
||||
* @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
|
||||
* case they are both zero, default memory allocators are used. @p opaque is
|
||||
* passed to @p alloc_func and @p free_func when they are called. @p free_func
|
||||
* has to return without doing anything when asked to free a NULL pointer.
|
||||
*
|
||||
* @param type type of dictionary stored in data
|
||||
* @param data_size size of @p data buffer
|
||||
* @param data pointer to the dictionary data
|
||||
* @param quality the maximum Brotli quality to prepare the dictionary for,
|
||||
* use BROTLI_MAX_QUALITY by default
|
||||
* @param alloc_func custom memory allocation function
|
||||
* @param free_func custom memory free function
|
||||
* @param opaque custom memory manager handle
|
||||
*/
|
||||
BROTLI_ENC_API BrotliEncoderPreparedDictionary*
|
||||
BrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type,
|
||||
size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)],
|
||||
int quality,
|
||||
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
|
||||
|
||||
BROTLI_ENC_API void BrotliEncoderDestroyPreparedDictionary(
|
||||
BrotliEncoderPreparedDictionary* dictionary);
|
||||
|
||||
/**
|
||||
* Attaches a prepared dictionary of any type to the encoder. Can be used
|
||||
* multiple times to attach multiple dictionaries. The dictionary type was
|
||||
* determined by BrotliEncoderPrepareDictionary. Multiple raw prefix
|
||||
* dictionaries and/or max 1 serialized dictionary with custom words can be
|
||||
* attached.
|
||||
*
|
||||
* @returns ::BROTLI_FALSE in case of error
|
||||
* @returns ::BROTLI_TRUE otherwise
|
||||
*/
|
||||
BROTLI_ENC_API BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(
|
||||
BrotliEncoderState* state,
|
||||
const BrotliEncoderPreparedDictionary* dictionary);
|
||||
|
||||
/**
|
||||
* Calculates the output size bound for the given @p input_size.
|
||||
*
|
||||
@ -407,7 +453,7 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(
|
||||
*
|
||||
* This method is used to make language bindings easier and more efficient:
|
||||
* -# push data to ::BrotliEncoderCompressStream,
|
||||
* until ::BrotliEncoderHasMoreOutput returns BROTL_TRUE
|
||||
* until ::BrotliEncoderHasMoreOutput returns BROTLI_TRUE
|
||||
* -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific
|
||||
* entity
|
||||
*
|
||||
@ -433,11 +479,18 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(
|
||||
BROTLI_ENC_API const uint8_t* BrotliEncoderTakeOutput(
|
||||
BrotliEncoderState* state, size_t* size);
|
||||
|
||||
/* Returns the estimated peak memory usage (in bytes) of the BrotliCompress()
|
||||
function, not counting the memory needed for the input and output. */
|
||||
BROTLI_ENC_EXTRA_API size_t BrotliEncoderEstimatePeakMemoryUsage(
|
||||
int quality, int lgwin, size_t input_size);
|
||||
/* Returns 0 if dictionary is not valid; otherwise returns allocation size. */
|
||||
BROTLI_ENC_EXTRA_API size_t BrotliEncoderGetPreparedDictionarySize(
|
||||
const BrotliEncoderPreparedDictionary* dictionary);
|
||||
|
||||
/**
|
||||
* Gets an encoder library version.
|
||||
*
|
||||
* Look at BROTLI_VERSION for more information.
|
||||
* Look at BROTLI_MAKE_HEX_VERSION for more information.
|
||||
*/
|
||||
BROTLI_ENC_API uint32_t BrotliEncoderVersion(void);
|
||||
|
||||
|
@ -224,14 +224,6 @@
|
||||
#define BROTLI_HAS_FEATURE(feature) (0)
|
||||
#endif
|
||||
|
||||
#if defined(ADDRESS_SANITIZER) || BROTLI_HAS_FEATURE(address_sanitizer) || \
|
||||
defined(THREAD_SANITIZER) || BROTLI_HAS_FEATURE(thread_sanitizer) || \
|
||||
defined(MEMORY_SANITIZER) || BROTLI_HAS_FEATURE(memory_sanitizer)
|
||||
#define BROTLI_SANITIZED 1
|
||||
#else
|
||||
#define BROTLI_SANITIZED 0
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define BROTLI_PUBLIC
|
||||
#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \
|
||||
@ -247,9 +239,28 @@
|
||||
#define BROTLI_PUBLIC
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__STDC_NO_VLA__) && !defined(__cplusplus) && \
|
||||
!defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__)
|
||||
/* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */
|
||||
#if !defined(BROTLI_INTERNAL)
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define BROTLI_INTERNAL
|
||||
#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \
|
||||
BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
|
||||
BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
|
||||
BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
|
||||
BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \
|
||||
BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \
|
||||
(BROTLI_TI_VERSION_CHECK(7, 3, 0) && \
|
||||
defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))
|
||||
#define BROTLI_INTERNAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define BROTLI_INTERNAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__STDC_NO_VLA__) && !defined(__cplusplus) && \
|
||||
!defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__) && \
|
||||
!defined(__clang__)
|
||||
#define BROTLI_ARRAY_PARAM(name) (name)
|
||||
#else
|
||||
#define BROTLI_ARRAY_PARAM(name)
|
||||
@ -285,4 +296,10 @@
|
||||
#define BROTLI_ENC_API
|
||||
#endif
|
||||
|
||||
#if defined(BROTLI_BUILD_ENC_EXTRA_API)
|
||||
#define BROTLI_ENC_EXTRA_API BROTLI_ENC_API
|
||||
#else
|
||||
#define BROTLI_ENC_EXTRA_API BROTLI_INTERNAL
|
||||
#endif
|
||||
|
||||
#endif /* BROTLI_COMMON_PORT_H_ */
|
||||
|
100
modules/brotli/include/brotli/shared_dictionary.h
Normal file
100
modules/brotli/include/brotli/shared_dictionary.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* Copyright 2017 Google Inc. All Rights Reserved.
|
||||
|
||||
Distributed under MIT license.
|
||||
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/* (Opaque) Shared Dictionary definition and utilities. */
|
||||
|
||||
#ifndef BROTLI_COMMON_SHARED_DICTIONARY_H_
|
||||
#define BROTLI_COMMON_SHARED_DICTIONARY_H_
|
||||
|
||||
#include <brotli/port.h>
|
||||
#include <brotli/types.h>
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH 4
|
||||
#define SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH 31
|
||||
#define SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS 64
|
||||
#define SHARED_BROTLI_MAX_COMPOUND_DICTS 15
|
||||
|
||||
/**
|
||||
* Opaque structure that holds shared dictionary data.
|
||||
*
|
||||
* Allocated and initialized with ::BrotliSharedDictionaryCreateInstance.
|
||||
* Cleaned up and deallocated with ::BrotliSharedDictionaryDestroyInstance.
|
||||
*/
|
||||
typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionary;
|
||||
|
||||
/**
|
||||
* Input data type for ::BrotliSharedDictionaryAttach.
|
||||
*/
|
||||
typedef enum BrotliSharedDictionaryType {
|
||||
/** Raw LZ77 prefix dictionary. */
|
||||
BROTLI_SHARED_DICTIONARY_RAW = 0,
|
||||
/** Serialized shared dictionary.
|
||||
*
|
||||
* DO NOT USE: methods accepting this value will fail.
|
||||
*/
|
||||
BROTLI_SHARED_DICTIONARY_SERIALIZED = 1
|
||||
} BrotliSharedDictionaryType;
|
||||
|
||||
/**
|
||||
* Creates an instance of ::BrotliSharedDictionary.
|
||||
*
|
||||
* Fresh instance has default word dictionary and transforms
|
||||
* and no LZ77 prefix dictionary.
|
||||
*
|
||||
* @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
|
||||
* case they are both zero, default memory allocators are used. @p opaque is
|
||||
* passed to @p alloc_func and @p free_func when they are called. @p free_func
|
||||
* has to return without doing anything when asked to free a NULL pointer.
|
||||
*
|
||||
* @param alloc_func custom memory allocation function
|
||||
* @param free_func custom memory free function
|
||||
* @param opaque custom memory manager handle
|
||||
* @returns @c 0 if instance can not be allocated or initialized
|
||||
* @returns pointer to initialized ::BrotliSharedDictionary otherwise
|
||||
*/
|
||||
BROTLI_COMMON_API BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(
|
||||
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
|
||||
|
||||
/**
|
||||
* Deinitializes and frees ::BrotliSharedDictionary instance.
|
||||
*
|
||||
* @param dict shared dictionary instance to be cleaned up and deallocated
|
||||
*/
|
||||
BROTLI_COMMON_API void BrotliSharedDictionaryDestroyInstance(
|
||||
BrotliSharedDictionary* dict);
|
||||
|
||||
/**
|
||||
* Attaches dictionary to a given instance of ::BrotliSharedDictionary.
|
||||
*
|
||||
* Dictionary to be attached is represented in a serialized format as a region
|
||||
* of memory.
|
||||
*
|
||||
* Provided data it partially referenced by a resulting (compound) dictionary,
|
||||
* and should be kept untouched, while at least one compound dictionary uses it.
|
||||
* This way memory overhead is kept minimal by the cost of additional resource
|
||||
* management.
|
||||
*
|
||||
* @param dict dictionary to extend
|
||||
* @param type type of dictionary to attach
|
||||
* @param data_size size of @p data
|
||||
* @param data serialized dictionary of type @p type, with at least @p data_size
|
||||
* addressable bytes
|
||||
* @returns ::BROTLI_TRUE if provided dictionary is successfully attached
|
||||
* @returns ::BROTLI_FALSE otherwise
|
||||
*/
|
||||
BROTLI_COMMON_API BROTLI_BOOL BrotliSharedDictionaryAttach(
|
||||
BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,
|
||||
size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* BROTLI_COMMON_SHARED_DICTIONARY_H_ */
|
@ -11,6 +11,7 @@ EXPORTS.brotli += [
|
||||
'include/brotli/decode.h',
|
||||
'include/brotli/encode.h',
|
||||
'include/brotli/port.h',
|
||||
'include/brotli/shared_dictionary.h',
|
||||
'include/brotli/types.h',
|
||||
]
|
||||
|
||||
@ -19,6 +20,7 @@ UNIFIED_SOURCES += [
|
||||
'common/context.c',
|
||||
'common/dictionary.c',
|
||||
'common/platform.c',
|
||||
'common/shared_dictionary.c',
|
||||
'common/transform.c',
|
||||
'dec/bit_reader.c',
|
||||
'dec/decode.c',
|
||||
|
@ -10,8 +10,8 @@ origin:
|
||||
|
||||
url: https://github.com/google/brotli
|
||||
|
||||
release: e61745a6b7add50d380cfd7d3883dd6c62fc2c71 (2020-08-27T14:12:55Z).
|
||||
revision: e61745a6b7add50d380cfd7d3883dd6c62fc2c71
|
||||
release: ed738e842d2fbdf2d6459e39267a633c4a9b2f5d (2023-08-29T11:00:29Z).
|
||||
revision: ed738e842d2fbdf2d6459e39267a633c4a9b2f5d
|
||||
|
||||
license: MIT
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user