Blame SOURCES/rhbz1881156.patch

234b78
From ce3b0936620b9abb2d6d21d3e608f37f3c7302d9 Mon Sep 17 00:00:00 2001
234b78
From: rpm-build <rpm-build>
234b78
Date: Thu, 1 Oct 2020 10:34:27 +0200
234b78
Subject: [PATCH] rhbz1881156.patch
234b78
234b78
---
234b78
 c/common/constants.c      |  15 +
234b78
 c/common/constants.h      | 136 ++++++++
234b78
 c/common/platform.h       |   8 +-
234b78
 c/dec/bit_reader.c        |  28 ++
234b78
 c/dec/bit_reader.h        |  74 +++-
234b78
 c/dec/decode.c            | 695 ++++++++++++++++++++++----------------
234b78
 c/dec/huffman.h           |  71 +++-
234b78
 c/dec/prefix.h            |  18 -
234b78
 c/dec/state.c             |  23 +-
234b78
 c/dec/state.h             | 181 ++++++++--
234b78
 c/enc/brotli_bit_stream.c |  21 +-
234b78
 research/brotli_decoder.c |   1 +
234b78
 scripts/sources.lst       |   1 +
234b78
 setup.py                  |   1 +
234b78
 14 files changed, 865 insertions(+), 408 deletions(-)
234b78
 create mode 100644 c/common/constants.c
234b78
234b78
diff --git a/c/common/constants.c b/c/common/constants.c
234b78
new file mode 100644
234b78
index 0000000..6bad9f6
234b78
--- /dev/null
234b78
+++ b/c/common/constants.c
234b78
@@ -0,0 +1,15 @@
234b78
+/* Copyright 2013 Google Inc. All Rights Reserved.
234b78
+
234b78
+   Distributed under MIT license.
234b78
+   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
234b78
+*/
234b78
+
234b78
+#include "./constants.h"
234b78
+
234b78
+const BrotliPrefixCodeRange
234b78
+    _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
234b78
+        {1, 2},     {5, 2},     {9, 2},   {13, 2},    {17, 3},    {25, 3},
234b78
+        {33, 3},    {41, 3},    {49, 4},  {65, 4},    {81, 4},    {97, 4},
234b78
+        {113, 5},   {145, 5},   {177, 5}, {209, 5},   {241, 6},   {305, 6},
234b78
+        {369, 7},   {497, 8},   {753, 9}, {1265, 10}, {2289, 11}, {4337, 12},
234b78
+        {8433, 13}, {16625, 24}};
234b78
diff --git a/c/common/constants.h b/c/common/constants.h
234b78
index d1b88d1..e848195 100644
234b78
--- a/c/common/constants.h
234b78
+++ b/c/common/constants.h
234b78
@@ -4,9 +4,18 @@
234b78
    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
234b78
 */
234b78
 
234b78
+/**
234b78
+ * @file
234b78
+ * Common constants used in decoder and encoder API.
234b78
+ */
234b78
+
234b78
 #ifndef BROTLI_COMMON_CONSTANTS_H_
234b78
 #define BROTLI_COMMON_CONSTANTS_H_
234b78
 
234b78
+#include "./platform.h"
234b78
+#include <brotli/port.h>
234b78
+#include <brotli/types.h>
234b78
+
234b78
 /* Specification: 7.3. Encoding of the context map */
234b78
 #define BROTLI_CONTEXT_MAP_MAX_RLE 16
234b78
 
234b78
@@ -29,12 +38,31 @@
234b78
 #define BROTLI_INITIAL_REPEATED_CODE_LENGTH 8
234b78
 
234b78
 /* "Large Window Brotli" */
234b78
+
234b78
+/**
234b78
+ * The theoretical maximum number of distance bits specified for large window
234b78
+ * brotli, for 64-bit encoders and decoders. Even when in practice 32-bit
234b78
+ * encoders and decoders only support up to 30 max distance bits, the value is
234b78
+ * set to 62 because it affects the large window brotli file format.
234b78
+ * Specifically, it affects the encoding of simple huffman tree for distances,
234b78
+ * see Specification RFC 7932 chapter 3.4.
234b78
+ */
234b78
 #define BROTLI_LARGE_MAX_DISTANCE_BITS 62U
234b78
 #define BROTLI_LARGE_MIN_WBITS 10
234b78
+/**
234b78
+ * The maximum supported large brotli window bits by the encoder and decoder.
234b78
+ * Large window brotli allows up to 62 bits, however the current encoder and
234b78
+ * decoder, designed for 32-bit integers, only support up to 30 bits maximum.
234b78
+ */
234b78
 #define BROTLI_LARGE_MAX_WBITS 30
234b78
 
234b78
 /* Specification: 4. Encoding of distances */
234b78
 #define BROTLI_NUM_DISTANCE_SHORT_CODES 16
234b78
+/**
234b78
+ * Maximal number of "postfix" bits.
234b78
+ *
234b78
+ * Number of "postfix" bits is stored as 2 bits in meta-block header.
234b78
+ */
234b78
 #define BROTLI_MAX_NPOSTFIX 3
234b78
 #define BROTLI_MAX_NDIRECT 120
234b78
 #define BROTLI_MAX_DISTANCE_BITS 24U
234b78
@@ -45,9 +73,22 @@
234b78
 #define BROTLI_NUM_DISTANCE_SYMBOLS \
234b78
     BROTLI_DISTANCE_ALPHABET_SIZE(  \
234b78
         BROTLI_MAX_NDIRECT, BROTLI_MAX_NPOSTFIX, BROTLI_LARGE_MAX_DISTANCE_BITS)
234b78
+
234b78
+/* ((1 << 26) - 4) is the maximal distance that can be expressed in RFC 7932
234b78
+   brotli stream using NPOSTFIX = 0 and NDIRECT = 0. With other NPOSTFIX and
234b78
+   NDIRECT values distances up to ((1 << 29) + 88) could be expressed. */
234b78
 #define BROTLI_MAX_DISTANCE 0x3FFFFFC
234b78
+
234b78
+/* ((1 << 31) - 4) is the safe distance limit. Using this number as a limit
234b78
+   allows safe distance calculation without overflows, given the distance
234b78
+   alphabet size is limited to corresponding size
234b78
+   (see kLargeWindowDistanceCodeLimits). */
234b78
 #define BROTLI_MAX_ALLOWED_DISTANCE 0x7FFFFFFC
234b78
 
234b78
+
234b78
+/* Specification: 4. Encoding of Literal Insertion Lengths and Copy Lengths */
234b78
+#define BROTLI_NUM_INS_COPY_CODES 24
234b78
+
234b78
 /* 7.1. Context modes and context ID lookup for literals */
234b78
 /* "context IDs for literals are in the range of 0..63" */
234b78
 #define BROTLI_LITERAL_CONTEXT_BITS 6
234b78
@@ -61,4 +102,99 @@
234b78
 #define BROTLI_WINDOW_GAP 16
234b78
 #define BROTLI_MAX_BACKWARD_LIMIT(W) (((size_t)1 << (W)) - BROTLI_WINDOW_GAP)
234b78
 
234b78
+typedef struct BrotliDistanceCodeLimit {
234b78
+  uint32_t max_alphabet_size;
234b78
+  uint32_t max_distance;
234b78
+} BrotliDistanceCodeLimit;
234b78
+
234b78
+/* This function calculates maximal size of distance alphabet, such that the
234b78
+   distances greater than the given values can not be represented.
234b78
+
234b78
+   This limits are designed to support fast and safe 32-bit decoders.
234b78
+   "32-bit" means that signed integer values up to ((1 << 31) - 1) could be
234b78
+   safely expressed.
234b78
+
234b78
+   Brotli distance alphabet symbols do not represent consecutive distance
234b78
+   ranges. Each distance alphabet symbol (excluding direct distances and short
234b78
+   codes), represent interleaved (for NPOSTFIX > 0) range of distances.
234b78
+   A "group" of consecutive (1 << NPOSTFIX) symbols represent non-interleaved
234b78
+   range. Two consecutive groups require the same amount of "extra bits".
234b78
+
234b78
+   It is important that distance alphabet represents complete "groups".
234b78
+   To avoid complex logic on encoder side about interleaved ranges
234b78
+   it was decided to restrict both sides to complete distance code "groups".
234b78
+ */
234b78
+BROTLI_UNUSED_FUNCTION BrotliDistanceCodeLimit BrotliCalculateDistanceCodeLimit(
234b78
+    uint32_t max_distance, uint32_t npostfix, uint32_t ndirect) {
234b78
+  BrotliDistanceCodeLimit result;
234b78
+  /* Marking this function as unused, because not all files
234b78
+     including "constants.h" use it -> compiler warns about that. */
234b78
+  BROTLI_UNUSED(&BrotliCalculateDistanceCodeLimit);
234b78
+  if (max_distance <= ndirect) {
234b78
+    /* This case never happens / exists only for the sake of completeness. */
234b78
+    result.max_alphabet_size = max_distance + BROTLI_NUM_DISTANCE_SHORT_CODES;
234b78
+    result.max_distance = max_distance;
234b78
+    return result;
234b78
+  } else {
234b78
+    /* The first prohibited value. */
234b78
+    uint32_t forbidden_distance = max_distance + 1;
234b78
+    /* Subtract "directly" encoded region. */
234b78
+    uint32_t offset = forbidden_distance - ndirect - 1;
234b78
+    uint32_t ndistbits = 0;
234b78
+    uint32_t tmp;
234b78
+    uint32_t half;
234b78
+    uint32_t group;
234b78
+    /* Postfix for the last dcode in the group. */
234b78
+    uint32_t postfix = (1u << npostfix) - 1;
234b78
+    uint32_t extra;
234b78
+    uint32_t start;
234b78
+    /* Remove postfix and "head-start". */
234b78
+    offset = (offset >> npostfix) + 4;
234b78
+    /* Calculate the number of distance bits. */
234b78
+    tmp = offset / 2;
234b78
+    /* Poor-man's log2floor, to avoid extra dependencies. */
234b78
+    while (tmp != 0) {ndistbits++; tmp = tmp >> 1;}
234b78
+    /* One bit is covered with subrange addressing ("half"). */
234b78
+    ndistbits--;
234b78
+    /* Find subrange. */
234b78
+    half = (offset >> ndistbits) & 1;
234b78
+    /* Calculate the "group" part of dcode. */
234b78
+    group = ((ndistbits - 1) << 1) | half;
234b78
+    /* Calculated "group" covers the prohibited distance value. */
234b78
+    if (group == 0) {
234b78
+      /* This case is added for correctness; does not occur for limit > 128. */
234b78
+      result.max_alphabet_size = ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES;
234b78
+      result.max_distance = ndirect;
234b78
+      return result;
234b78
+    }
234b78
+    /* Decrement "group", so it is the last permitted "group". */
234b78
+    group--;
234b78
+    /* After group was decremented, ndistbits and half must be recalculated. */
234b78
+    ndistbits = (group >> 1) + 1;
234b78
+    /* The last available distance in the subrange has all extra bits set. */
234b78
+    extra = (1u << ndistbits) - 1;
234b78
+    /* Calculate region start. NB: ndistbits >= 1. */
234b78
+    start = (1u << (ndistbits + 1)) - 4;
234b78
+    /* Move to subregion. */
234b78
+    start += (group & 1) << ndistbits;
234b78
+    /* Calculate the alphabet size. */
234b78
+    result.max_alphabet_size = ((group << npostfix) | postfix) + ndirect +
234b78
+        BROTLI_NUM_DISTANCE_SHORT_CODES + 1;
234b78
+    /* Calculate the maximal distance representable by alphabet. */
234b78
+    result.max_distance = ((start + extra) << npostfix) + postfix + ndirect + 1;
234b78
+    return result;
234b78
+  }
234b78
+}
234b78
+
234b78
+/* Represents the range of values belonging to a prefix code:
234b78
+   [offset, offset + 2^nbits) */
234b78
+typedef struct {
234b78
+  uint16_t offset;
234b78
+  uint8_t nbits;
234b78
+} BrotliPrefixCodeRange;
234b78
+
234b78
+/* "Soft-private", it is exported, but not "advertised" as API. */
234b78
+BROTLI_COMMON_API extern const BrotliPrefixCodeRange
234b78
+    _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
234b78
+
234b78
 #endif  /* BROTLI_COMMON_CONSTANTS_H_ */
234b78
diff --git a/c/common/platform.h b/c/common/platform.h
234b78
index 0d84b19..94bf773 100755
234b78
--- a/c/common/platform.h
234b78
+++ b/c/common/platform.h
234b78
@@ -197,6 +197,10 @@ OR:
234b78
 
234b78
 #endif  /* ARMv8 */
234b78
 
234b78
+#if defined(__ARM_NEON__) || defined(__ARM_NEON)
234b78
+#define BROTLI_TARGET_NEON
234b78
+#endif
234b78
+
234b78
 #if defined(__i386) || defined(_M_IX86)
234b78
 #define BROTLI_TARGET_X86
234b78
 #endif
234b78
@@ -456,20 +460,20 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
234b78
 #endif
234b78
 
234b78
 #if defined(BROTLI_ENABLE_LOG)
234b78
-#define BROTLI_DCHECK(x) assert(x)
234b78
 #define BROTLI_LOG(x) printf x
234b78
 #else
234b78
-#define BROTLI_DCHECK(x)
234b78
 #define BROTLI_LOG(x)
234b78
 #endif
234b78
 
234b78
 #if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
234b78
+#define BROTLI_DCHECK(x) assert(x)
234b78
 static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
234b78
   fprintf(stderr, "%s:%d (%s)\n", f, l, fn);
234b78
   fflush(stderr);
234b78
 }
234b78
 #define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__)
234b78
 #else
234b78
+#define BROTLI_DCHECK(x)
234b78
 #define BROTLI_DUMP() (void)(0)
234b78
 #endif
234b78
 
234b78
diff --git a/c/dec/bit_reader.c b/c/dec/bit_reader.c
234b78
index 722fd90..7f7b256 100644
234b78
--- a/c/dec/bit_reader.c
234b78
+++ b/c/dec/bit_reader.c
234b78
@@ -15,6 +15,17 @@
234b78
 extern "C" {
234b78
 #endif
234b78
 
234b78
+const uint32_t kBrotliBitMask[33] = {   0x00000000,
234b78
+    0x00000001, 0x00000003, 0x00000007, 0x0000000F,
234b78
+    0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
234b78
+    0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
234b78
+    0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
234b78
+    0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
234b78
+    0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
234b78
+    0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
234b78
+    0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
234b78
+};
234b78
+
234b78
 void BrotliInitBitReader(BrotliBitReader* const br) {
234b78
   br->val_ = 0;
234b78
   br->bit_pos_ = sizeof(br->val_) << 3;
234b78
@@ -43,6 +54,23 @@ BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
234b78
   return BROTLI_TRUE;
234b78
 }
234b78
 
234b78
+BROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,
234b78
+    uint32_t n_bits, uint32_t* val) {
234b78
+  uint32_t low_val;
234b78
+  uint32_t high_val;
234b78
+  BrotliBitReaderState memento;
234b78
+  BROTLI_DCHECK(n_bits <= 32);
234b78
+  BROTLI_DCHECK(n_bits > 24);
234b78
+  BrotliBitReaderSaveState(br, &memento);
234b78
+  if (!BrotliSafeReadBits(br, 16, &low_val) ||
234b78
+      !BrotliSafeReadBits(br, n_bits - 16, &high_val)) {
234b78
+    BrotliBitReaderRestoreState(br, &memento);
234b78
+    return BROTLI_FALSE;
234b78
+  }
234b78
+  *val = low_val | (high_val << 16);
234b78
+  return BROTLI_TRUE;
234b78
+}
234b78
+
234b78
 #if defined(__cplusplus) || defined(c_plusplus)
234b78
 }  /* extern "C" */
234b78
 #endif
234b78
diff --git a/c/dec/bit_reader.h b/c/dec/bit_reader.h
234b78
index c06e914..22bc060 100644
234b78
--- a/c/dec/bit_reader.h
234b78
+++ b/c/dec/bit_reader.h
234b78
@@ -11,6 +11,7 @@
234b78
 
234b78
 #include <string.h>  /* memcpy */
234b78
 
234b78
+#include "../common/constants.h"
234b78
 #include "../common/platform.h"
234b78
 #include <brotli/types.h>
234b78
 
234b78
@@ -20,16 +21,7 @@ extern "C" {
234b78
 
234b78
 #define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)
234b78
 
234b78
-static const uint32_t kBitMask[33] = {  0x00000000,
234b78
-    0x00000001, 0x00000003, 0x00000007, 0x0000000F,
234b78
-    0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
234b78
-    0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
234b78
-    0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
234b78
-    0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
234b78
-    0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
234b78
-    0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
234b78
-    0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
234b78
-};
234b78
+BROTLI_INTERNAL extern const uint32_t kBrotliBitMask[33];
234b78
 
234b78
 static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
234b78
   if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) {
234b78
@@ -37,7 +29,7 @@ static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
234b78
        "Unsigned Bit Field Extract" UBFX instruction on ARM. */
234b78
     return ~((0xFFFFFFFFu) << n);
234b78
   } else {
234b78
-    return kBitMask[n];
234b78
+    return kBrotliBitMask[n];
234b78
   }
234b78
 }
234b78
 
234b78
@@ -65,6 +57,12 @@ BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
234b78
    reading. */
234b78
 BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);
234b78
 
234b78
+/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
234b78
+   the main code-path. Never called for RFC brotli streams, required only for
234b78
+   "large-window" mode and other extensions. */
234b78
+BROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(
234b78
+    BrotliBitReader* const br, uint32_t n_bits, uint32_t* val);
234b78
+
234b78
 static BROTLI_INLINE void BrotliBitReaderSaveState(
234b78
     BrotliBitReader* const from, BrotliBitReaderState* to) {
234b78
   to->val_ = from->val_;
234b78
@@ -87,8 +85,11 @@ static BROTLI_INLINE uint32_t BrotliGetAvailableBits(
234b78
 }
234b78
 
234b78
 /* Returns amount of unread bytes the bit reader still has buffered from the
234b78
-   BrotliInput, including whole bytes in br->val_. */
234b78
+   BrotliInput, including whole bytes in br->val_. Result is capped with
234b78
+   maximal ring-buffer size (larger number won't be utilized anyway). */
234b78
 static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
234b78
+  static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;
234b78
+  if (br->avail_in > kCap) return kCap;
234b78
   return br->avail_in + (BrotliGetAvailableBits(br) >> 3);
234b78
 }
234b78
 
234b78
@@ -237,15 +238,17 @@ static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {
234b78
 static BROTLI_INLINE void BrotliTakeBits(
234b78
   BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
234b78
   *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
234b78
-  BROTLI_LOG(("[BrotliReadBits]  %d %d %d val: %6x\n",
234b78
+  BROTLI_LOG(("[BrotliTakeBits]  %d %d %d val: %6x\n",
234b78
       (int)br->avail_in, (int)br->bit_pos_, (int)n_bits, (int)*val));
234b78
   BrotliDropBits(br, n_bits);
234b78
 }
234b78
 
234b78
 /* Reads the specified number of bits from |br| and advances the bit pos.
234b78
-   Assumes that there is enough input to perform BrotliFillBitWindow. */
234b78
-static BROTLI_INLINE uint32_t BrotliReadBits(
234b78
+   Assumes that there is enough input to perform BrotliFillBitWindow.
234b78
+   Up to 24 bits are allowed to be requested from this method. */
234b78
+static BROTLI_INLINE uint32_t BrotliReadBits24(
234b78
     BrotliBitReader* const br, uint32_t n_bits) {
234b78
+  BROTLI_DCHECK(n_bits <= 24);
234b78
   if (BROTLI_64_BITS || (n_bits <= 16)) {
234b78
     uint32_t val;
234b78
     BrotliFillBitWindow(br, n_bits);
234b78
@@ -262,10 +265,32 @@ static BROTLI_INLINE uint32_t BrotliReadBits(
234b78
   }
234b78
 }
234b78
 
234b78
+/* Same as BrotliReadBits24, but allows reading up to 32 bits. */
234b78
+static BROTLI_INLINE uint32_t BrotliReadBits32(
234b78
+    BrotliBitReader* const br, uint32_t n_bits) {
234b78
+  BROTLI_DCHECK(n_bits <= 32);
234b78
+  if (BROTLI_64_BITS || (n_bits <= 16)) {
234b78
+    uint32_t val;
234b78
+    BrotliFillBitWindow(br, n_bits);
234b78
+    BrotliTakeBits(br, n_bits, &val;;
234b78
+    return val;
234b78
+  } else {
234b78
+    uint32_t low_val;
234b78
+    uint32_t high_val;
234b78
+    BrotliFillBitWindow(br, 16);
234b78
+    BrotliTakeBits(br, 16, &low_val);
234b78
+    BrotliFillBitWindow(br, 16);
234b78
+    BrotliTakeBits(br, n_bits - 16, &high_val);
234b78
+    return low_val | (high_val << 16);
234b78
+  }
234b78
+}
234b78
+
234b78
 /* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there
234b78
-   is not enough input. |n_bits| MUST be positive. */
234b78
+   is not enough input. |n_bits| MUST be positive.
234b78
+   Up to 24 bits are allowed to be requested from this method. */
234b78
 static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
234b78
     BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
234b78
+  BROTLI_DCHECK(n_bits <= 24);
234b78
   while (BrotliGetAvailableBits(br) < n_bits) {
234b78
     if (!BrotliPullByte(br)) {
234b78
       return BROTLI_FALSE;
234b78
@@ -275,6 +300,23 @@ static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
234b78
   return BROTLI_TRUE;
234b78
 }
234b78
 
234b78
+/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */
234b78
+static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(
234b78
+    BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
234b78
+  BROTLI_DCHECK(n_bits <= 32);
234b78
+  if (BROTLI_64_BITS || (n_bits <= 24)) {
234b78
+    while (BrotliGetAvailableBits(br) < n_bits) {
234b78
+      if (!BrotliPullByte(br)) {
234b78
+        return BROTLI_FALSE;
234b78
+      }
234b78
+    }
234b78
+    BrotliTakeBits(br, n_bits, val);
234b78
+    return BROTLI_TRUE;
234b78
+  } else {
234b78
+    return BrotliSafeReadBits32Slow(br, n_bits, val);
234b78
+  }
234b78
+}
234b78
+
234b78
 /* Advances the bit reader position to the next byte boundary and verifies
234b78
    that any skipped bits are set to zero. */
234b78
 static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
234b78
diff --git a/c/dec/decode.c b/c/dec/decode.c
234b78
index 674b829..ae5a3d3 100644
234b78
--- a/c/dec/decode.c
234b78
+++ b/c/dec/decode.c
234b78
@@ -6,10 +6,6 @@
234b78
 
234b78
 #include <brotli/decode.h>
234b78
 
234b78
-#if defined(__ARM_NEON__)
234b78
-#include <arm_neon.h>
234b78
-#endif
234b78
-
234b78
 #include <stdlib.h>  /* free, malloc */
234b78
 #include <string.h>  /* memcpy, memset */
234b78
 
234b78
@@ -24,6 +20,10 @@
234b78
 #include "./prefix.h"
234b78
 #include "./state.h"
234b78
 
234b78
+#if defined(BROTLI_TARGET_NEON)
234b78
+#include <arm_neon.h>
234b78
+#endif
234b78
+
234b78
 #if defined(__cplusplus) || defined(c_plusplus)
234b78
 extern "C" {
234b78
 #endif
234b78
@@ -41,7 +41,8 @@ extern "C" {
234b78
 
234b78
 /* We need the slack region for the following reasons:
234b78
     - doing up to two 16-byte copies for fast backward copying
234b78
-    - inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */
234b78
+    - inserting transformed dictionary word:
234b78
+        5 prefix + 24 base + 8 suffix */
234b78
 static const uint32_t kRingBufferWriteAheadSlack = 42;
234b78
 
234b78
 static const uint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = {
234b78
@@ -167,7 +168,7 @@ static BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,
234b78
 }
234b78
 
234b78
 static BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {
234b78
-#if defined(__ARM_NEON__)
234b78
+#if defined(BROTLI_TARGET_NEON)
234b78
   vst1q_u8(dst, vld1q_u8(src));
234b78
 #else
234b78
   uint32_t buffer[4];
234b78
@@ -274,7 +275,8 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
234b78
             s->loop_counter = i;
234b78
             return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
           }
234b78
-          if (i + 1 == s->size_nibbles && s->size_nibbles > 4 && bits == 0) {
234b78
+          if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 &&
234b78
+              bits == 0) {
234b78
             return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);
234b78
           }
234b78
           s->meta_block_remaining_len |= (int)(bits << (i * 4));
234b78
@@ -323,7 +325,8 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
234b78
             s->loop_counter = i;
234b78
             return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
           }
234b78
-          if (i + 1 == s->size_nibbles && s->size_nibbles > 1 && bits == 0) {
234b78
+          if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 &&
234b78
+              bits == 0) {
234b78
             return BROTLI_FAILURE(
234b78
                 BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
234b78
           }
234b78
@@ -347,15 +350,17 @@ static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
234b78
 static BROTLI_INLINE uint32_t DecodeSymbol(uint32_t bits,
234b78
                                            const HuffmanCode* table,
234b78
                                            BrotliBitReader* br) {
234b78
-  table += bits & HUFFMAN_TABLE_MASK;
234b78
-  if (table->bits > HUFFMAN_TABLE_BITS) {
234b78
-    uint32_t nbits = table->bits - HUFFMAN_TABLE_BITS;
234b78
+  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
234b78
+  BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK);
234b78
+  if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) {
234b78
+    uint32_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS;
234b78
     BrotliDropBits(br, HUFFMAN_TABLE_BITS);
234b78
-    table += table->value;
234b78
-    table += (bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits);
234b78
+    BROTLI_HC_ADJUST_TABLE_INDEX(table,
234b78
+        BROTLI_HC_FAST_LOAD_VALUE(table) +
234b78
+        ((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits)));
234b78
   }
234b78
-  BrotliDropBits(br, table->bits);
234b78
-  return table->value;
234b78
+  BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
234b78
+  return BROTLI_HC_FAST_LOAD_VALUE(table);
234b78
 }
234b78
 
234b78
 /* Reads and decodes the next Huffman code from bit-stream.
234b78
@@ -371,19 +376,20 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
234b78
     const HuffmanCode* table, BrotliBitReader* br, uint32_t* result) {
234b78
   uint32_t val;
234b78
   uint32_t available_bits = BrotliGetAvailableBits(br);
234b78
+  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
234b78
   if (available_bits == 0) {
234b78
-    if (table->bits == 0) {
234b78
-      *result = table->value;
234b78
+    if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) {
234b78
+      *result = BROTLI_HC_FAST_LOAD_VALUE(table);
234b78
       return BROTLI_TRUE;
234b78
     }
234b78
     return BROTLI_FALSE;  /* No valid bits at all. */
234b78
   }
234b78
   val = (uint32_t)BrotliGetBitsUnmasked(br);
234b78
-  table += val & HUFFMAN_TABLE_MASK;
234b78
-  if (table->bits <= HUFFMAN_TABLE_BITS) {
234b78
-    if (table->bits <= available_bits) {
234b78
-      BrotliDropBits(br, table->bits);
234b78
-      *result = table->value;
234b78
+  BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK);
234b78
+  if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) {
234b78
+    if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) {
234b78
+      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
234b78
+      *result = BROTLI_HC_FAST_LOAD_VALUE(table);
234b78
       return BROTLI_TRUE;
234b78
     } else {
234b78
       return BROTLI_FALSE;  /* Not enough bits for the first level. */
234b78
@@ -394,15 +400,15 @@ static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
234b78
   }
234b78
 
234b78
   /* Speculatively drop HUFFMAN_TABLE_BITS. */
234b78
-  val = (val & BitMask(table->bits)) >> HUFFMAN_TABLE_BITS;
234b78
+  val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS;
234b78
   available_bits -= HUFFMAN_TABLE_BITS;
234b78
-  table += table->value + val;
234b78
-  if (available_bits < table->bits) {
234b78
+  BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val);
234b78
+  if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) {
234b78
     return BROTLI_FALSE;  /* Not enough bits for the second level. */
234b78
   }
234b78
 
234b78
-  BrotliDropBits(br, HUFFMAN_TABLE_BITS + table->bits);
234b78
-  *result = table->value;
234b78
+  BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table));
234b78
+  *result = BROTLI_HC_FAST_LOAD_VALUE(table);
234b78
   return BROTLI_TRUE;
234b78
 }
234b78
 
234b78
@@ -425,9 +431,10 @@ static BROTLI_INLINE void PreloadSymbol(int safe,
234b78
   if (safe) {
234b78
     return;
234b78
   }
234b78
-  table += BrotliGetBits(br, HUFFMAN_TABLE_BITS);
234b78
-  *bits = table->bits;
234b78
-  *value = table->value;
234b78
+  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
234b78
+  BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS));
234b78
+  *bits = BROTLI_HC_FAST_LOAD_BITS(table);
234b78
+  *value = BROTLI_HC_FAST_LOAD_VALUE(table);
234b78
 }
234b78
 
234b78
 /* Decodes the next Huffman code using data prepared by PreloadSymbol.
234b78
@@ -441,10 +448,11 @@ static BROTLI_INLINE uint32_t ReadPreloadedSymbol(const HuffmanCode* table,
234b78
     uint32_t val = BrotliGet16BitsUnmasked(br);
234b78
     const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value;
234b78
     uint32_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS));
234b78
+    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext);
234b78
     BrotliDropBits(br, HUFFMAN_TABLE_BITS);
234b78
-    ext += (val >> HUFFMAN_TABLE_BITS) & mask;
234b78
-    BrotliDropBits(br, ext->bits);
234b78
-    result = ext->value;
234b78
+    BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask);
234b78
+    BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext));
234b78
+    result = BROTLI_HC_FAST_LOAD_VALUE(ext);
234b78
   } else {
234b78
     BrotliDropBits(br, *bits);
234b78
   }
234b78
@@ -465,32 +473,34 @@ static BROTLI_INLINE uint32_t Log2Floor(uint32_t x) {
234b78
    Totally 1..4 symbols are read, 1..11 bits each.
234b78
    The list of symbols MUST NOT contain duplicates. */
234b78
 static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
234b78
-    uint32_t alphabet_size, uint32_t max_symbol, BrotliDecoderState* s) {
234b78
+    uint32_t alphabet_size_max, uint32_t alphabet_size_limit,
234b78
+    BrotliDecoderState* s) {
234b78
   /* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */
234b78
   BrotliBitReader* br = &s->br;
234b78
-  uint32_t max_bits = Log2Floor(alphabet_size - 1);
234b78
-  uint32_t i = s->sub_loop_counter;
234b78
-  uint32_t num_symbols = s->symbol;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
+  uint32_t max_bits = Log2Floor(alphabet_size_max - 1);
234b78
+  uint32_t i = h->sub_loop_counter;
234b78
+  uint32_t num_symbols = h->symbol;
234b78
   while (i <= num_symbols) {
234b78
     uint32_t v;
234b78
     if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {
234b78
-      s->sub_loop_counter = i;
234b78
-      s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
234b78
+      h->sub_loop_counter = i;
234b78
+      h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
234b78
       return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
     }
234b78
-    if (v >= max_symbol) {
234b78
+    if (v >= alphabet_size_limit) {
234b78
       return
234b78
           BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
234b78
     }
234b78
-    s->symbols_lists_array[i] = (uint16_t)v;
234b78
-    BROTLI_LOG_UINT(s->symbols_lists_array[i]);
234b78
+    h->symbols_lists_array[i] = (uint16_t)v;
234b78
+    BROTLI_LOG_UINT(h->symbols_lists_array[i]);
234b78
     ++i;
234b78
   }
234b78
 
234b78
   for (i = 0; i < num_symbols; ++i) {
234b78
     uint32_t k = i + 1;
234b78
     for (; k <= num_symbols; ++k) {
234b78
-      if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) {
234b78
+      if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) {
234b78
         return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
234b78
       }
234b78
     }
234b78
@@ -583,33 +593,35 @@ static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len,
234b78
 static BrotliDecoderErrorCode ReadSymbolCodeLengths(
234b78
     uint32_t alphabet_size, BrotliDecoderState* s) {
234b78
   BrotliBitReader* br = &s->br;
234b78
-  uint32_t symbol = s->symbol;
234b78
-  uint32_t repeat = s->repeat;
234b78
-  uint32_t space = s->space;
234b78
-  uint32_t prev_code_len = s->prev_code_len;
234b78
-  uint32_t repeat_code_len = s->repeat_code_len;
234b78
-  uint16_t* symbol_lists = s->symbol_lists;
234b78
-  uint16_t* code_length_histo = s->code_length_histo;
234b78
-  int* next_symbol = s->next_symbol;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
+  uint32_t symbol = h->symbol;
234b78
+  uint32_t repeat = h->repeat;
234b78
+  uint32_t space = h->space;
234b78
+  uint32_t prev_code_len = h->prev_code_len;
234b78
+  uint32_t repeat_code_len = h->repeat_code_len;
234b78
+  uint16_t* symbol_lists = h->symbol_lists;
234b78
+  uint16_t* code_length_histo = h->code_length_histo;
234b78
+  int* next_symbol = h->next_symbol;
234b78
   if (!BrotliWarmupBitReader(br)) {
234b78
     return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
   }
234b78
   while (symbol < alphabet_size && space > 0) {
234b78
-    const HuffmanCode* p = s->table;
234b78
+    const HuffmanCode* p = h->table;
234b78
     uint32_t code_len;
234b78
+    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
234b78
     if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) {
234b78
-      s->symbol = symbol;
234b78
-      s->repeat = repeat;
234b78
-      s->prev_code_len = prev_code_len;
234b78
-      s->repeat_code_len = repeat_code_len;
234b78
-      s->space = space;
234b78
+      h->symbol = symbol;
234b78
+      h->repeat = repeat;
234b78
+      h->prev_code_len = prev_code_len;
234b78
+      h->repeat_code_len = repeat_code_len;
234b78
+      h->space = space;
234b78
       return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
     }
234b78
     BrotliFillBitWindow16(br);
234b78
-    p += BrotliGetBitsUnmasked(br) &
234b78
-        BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
234b78
-    BrotliDropBits(br, p->bits);  /* Use 1..5 bits. */
234b78
-    code_len = p->value;  /* code_len == 0..17 */
234b78
+    BROTLI_HC_ADJUST_TABLE_INDEX(p, BrotliGetBitsUnmasked(br) &
234b78
+        BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
234b78
+    BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));  /* Use 1..5 bits. */
234b78
+    code_len = BROTLI_HC_FAST_LOAD_VALUE(p);  /* code_len == 0..17 */
234b78
     if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
234b78
       ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,
234b78
           &prev_code_len, symbol_lists, code_length_histo, next_symbol);
234b78
@@ -624,48 +636,52 @@ static BrotliDecoderErrorCode ReadSymbolCodeLengths(
234b78
           symbol_lists, code_length_histo, next_symbol);
234b78
     }
234b78
   }
234b78
-  s->space = space;
234b78
+  h->space = space;
234b78
   return BROTLI_DECODER_SUCCESS;
234b78
 }
234b78
 
234b78
 static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
234b78
     uint32_t alphabet_size, BrotliDecoderState* s) {
234b78
   BrotliBitReader* br = &s->br;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
   BROTLI_BOOL get_byte = BROTLI_FALSE;
234b78
-  while (s->symbol < alphabet_size && s->space > 0) {
234b78
-    const HuffmanCode* p = s->table;
234b78
+  while (h->symbol < alphabet_size && h->space > 0) {
234b78
+    const HuffmanCode* p = h->table;
234b78
     uint32_t code_len;
234b78
     uint32_t available_bits;
234b78
     uint32_t bits = 0;
234b78
+    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
234b78
     if (get_byte && !BrotliPullByte(br)) return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
     get_byte = BROTLI_FALSE;
234b78
     available_bits = BrotliGetAvailableBits(br);
234b78
     if (available_bits != 0) {
234b78
       bits = (uint32_t)BrotliGetBitsUnmasked(br);
234b78
     }
234b78
-    p += bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
234b78
-    if (p->bits > available_bits) {
234b78
+    BROTLI_HC_ADJUST_TABLE_INDEX(p,
234b78
+        bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
234b78
+    if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) {
234b78
       get_byte = BROTLI_TRUE;
234b78
       continue;
234b78
     }
234b78
-    code_len = p->value;  /* code_len == 0..17 */
234b78
+    code_len = BROTLI_HC_FAST_LOAD_VALUE(p);  /* code_len == 0..17 */
234b78
     if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
234b78
-      BrotliDropBits(br, p->bits);
234b78
-      ProcessSingleCodeLength(code_len, &s->symbol, &s->repeat, &s->space,
234b78
-          &s->prev_code_len, s->symbol_lists, s->code_length_histo,
234b78
-          s->next_symbol);
234b78
+      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));
234b78
+      ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space,
234b78
+          &h->prev_code_len, h->symbol_lists, h->code_length_histo,
234b78
+          h->next_symbol);
234b78
     } else {  /* code_len == 16..17, extra_bits == 2..3 */
234b78
       uint32_t extra_bits = code_len - 14U;
234b78
-      uint32_t repeat_delta = (bits >> p->bits) & BitMask(extra_bits);
234b78
-      if (available_bits < p->bits + extra_bits) {
234b78
+      uint32_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &
234b78
+          BitMask(extra_bits);
234b78
+      if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) {
234b78
         get_byte = BROTLI_TRUE;
234b78
         continue;
234b78
       }
234b78
-      BrotliDropBits(br, p->bits + extra_bits);
234b78
+      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);
234b78
       ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
234b78
-          &s->symbol, &s->repeat, &s->space, &s->prev_code_len,
234b78
-          &s->repeat_code_len, s->symbol_lists, s->code_length_histo,
234b78
-          s->next_symbol);
234b78
+          &h->symbol, &h->repeat, &h->space, &h->prev_code_len,
234b78
+          &h->repeat_code_len, h->symbol_lists, h->code_length_histo,
234b78
+          h->next_symbol);
234b78
     }
234b78
   }
234b78
   return BROTLI_DECODER_SUCCESS;
234b78
@@ -675,9 +691,10 @@ static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
234b78
    Each code is 2..4 bits long. In total 30..72 bits are used. */
234b78
 static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
234b78
   BrotliBitReader* br = &s->br;
234b78
-  uint32_t num_codes = s->repeat;
234b78
-  unsigned space = s->space;
234b78
-  uint32_t i = s->sub_loop_counter;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
+  uint32_t num_codes = h->repeat;
234b78
+  unsigned space = h->space;
234b78
+  uint32_t i = h->sub_loop_counter;
234b78
   for (; i < BROTLI_CODE_LENGTH_CODES; ++i) {
234b78
     const uint8_t code_len_idx = kCodeLengthCodeOrder[i];
234b78
     uint32_t ix;
234b78
@@ -690,21 +707,21 @@ static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
234b78
         ix = 0;
234b78
       }
234b78
       if (kCodeLengthPrefixLength[ix] > available_bits) {
234b78
-        s->sub_loop_counter = i;
234b78
-        s->repeat = num_codes;
234b78
-        s->space = space;
234b78
-        s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
234b78
+        h->sub_loop_counter = i;
234b78
+        h->repeat = num_codes;
234b78
+        h->space = space;
234b78
+        h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
234b78
         return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
       }
234b78
     }
234b78
     v = kCodeLengthPrefixValue[ix];
234b78
     BrotliDropBits(br, kCodeLengthPrefixLength[ix]);
234b78
-    s->code_length_code_lengths[code_len_idx] = (uint8_t)v;
234b78
-    BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx);
234b78
+    h->code_length_code_lengths[code_len_idx] = (uint8_t)v;
234b78
+    BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx);
234b78
     if (v != 0) {
234b78
       space = space - (32U >> v);
234b78
       ++num_codes;
234b78
-      ++s->code_length_histo[v];
234b78
+      ++h->code_length_histo[v];
234b78
       if (space - 1U >= 32U) {
234b78
         /* space is 0 or wrapped around. */
234b78
         break;
234b78
@@ -728,49 +745,48 @@ static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
234b78
          encoded with predefined entropy code. 32 - 74 bits are used.
234b78
     B.2) Decoded table is used to decode code lengths of symbols in resulting
234b78
          Huffman table. In worst case 3520 bits are read. */
234b78
-static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
234b78
-                                              uint32_t max_symbol,
234b78
+static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size_max,
234b78
+                                              uint32_t alphabet_size_limit,
234b78
                                               HuffmanCode* table,
234b78
                                               uint32_t* opt_table_size,
234b78
                                               BrotliDecoderState* s) {
234b78
   BrotliBitReader* br = &s->br;
234b78
-  /* Unnecessary masking, but might be good for safety. */
234b78
-  alphabet_size &= 0x7FF;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
   /* State machine. */
234b78
   for (;;) {
234b78
-    switch (s->substate_huffman) {
234b78
+    switch (h->substate_huffman) {
234b78
       case BROTLI_STATE_HUFFMAN_NONE:
234b78
-        if (!BrotliSafeReadBits(br, 2, &s->sub_loop_counter)) {
234b78
+        if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) {
234b78
           return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
         }
234b78
-        BROTLI_LOG_UINT(s->sub_loop_counter);
234b78
+        BROTLI_LOG_UINT(h->sub_loop_counter);
234b78
         /* The value is used as follows:
234b78
            1 for simple code;
234b78
            0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
234b78
-        if (s->sub_loop_counter != 1) {
234b78
-          s->space = 32;
234b78
-          s->repeat = 0;  /* num_codes */
234b78
-          memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo[0]) *
234b78
+        if (h->sub_loop_counter != 1) {
234b78
+          h->space = 32;
234b78
+          h->repeat = 0;  /* num_codes */
234b78
+          memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo[0]) *
234b78
               (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));
234b78
-          memset(&s->code_length_code_lengths[0], 0,
234b78
-              sizeof(s->code_length_code_lengths));
234b78
-          s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
234b78
+          memset(&h->code_length_code_lengths[0], 0,
234b78
+              sizeof(h->code_length_code_lengths));
234b78
+          h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
234b78
           continue;
234b78
         }
234b78
       /* Fall through. */
234b78
 
234b78
       case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:
234b78
         /* Read symbols, codes & code lengths directly. */
234b78
-        if (!BrotliSafeReadBits(br, 2, &s->symbol)) {  /* num_symbols */
234b78
-          s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
234b78
+        if (!BrotliSafeReadBits(br, 2, &h->symbol)) {  /* num_symbols */
234b78
+          h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
234b78
           return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
         }
234b78
-        s->sub_loop_counter = 0;
234b78
+        h->sub_loop_counter = 0;
234b78
       /* Fall through. */
234b78
 
234b78
       case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
234b78
         BrotliDecoderErrorCode result =
234b78
-            ReadSimpleHuffmanSymbols(alphabet_size, max_symbol, s);
234b78
+            ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s);
234b78
         if (result != BROTLI_DECODER_SUCCESS) {
234b78
           return result;
234b78
         }
234b78
@@ -779,21 +795,21 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
234b78
 
234b78
       case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {
234b78
         uint32_t table_size;
234b78
-        if (s->symbol == 3) {
234b78
+        if (h->symbol == 3) {
234b78
           uint32_t bits;
234b78
           if (!BrotliSafeReadBits(br, 1, &bits)) {
234b78
-            s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
234b78
+            h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
234b78
             return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
           }
234b78
-          s->symbol += bits;
234b78
+          h->symbol += bits;
234b78
         }
234b78
-        BROTLI_LOG_UINT(s->symbol);
234b78
+        BROTLI_LOG_UINT(h->symbol);
234b78
         table_size = BrotliBuildSimpleHuffmanTable(
234b78
-            table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, s->symbol);
234b78
+            table, HUFFMAN_TABLE_BITS, h->symbols_lists_array, h->symbol);
234b78
         if (opt_table_size) {
234b78
           *opt_table_size = table_size;
234b78
         }
234b78
-        s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
234b78
+        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
234b78
         return BROTLI_DECODER_SUCCESS;
234b78
       }
234b78
 
234b78
@@ -804,44 +820,45 @@ static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size,
234b78
         if (result != BROTLI_DECODER_SUCCESS) {
234b78
           return result;
234b78
         }
234b78
-        BrotliBuildCodeLengthsHuffmanTable(s->table,
234b78
-                                           s->code_length_code_lengths,
234b78
-                                           s->code_length_histo);
234b78
-        memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo));
234b78
+        BrotliBuildCodeLengthsHuffmanTable(h->table,
234b78
+                                           h->code_length_code_lengths,
234b78
+                                           h->code_length_histo);
234b78
+        memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo));
234b78
         for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {
234b78
-          s->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
234b78
-          s->symbol_lists[s->next_symbol[i]] = 0xFFFF;
234b78
+          h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
234b78
+          h->symbol_lists[h->next_symbol[i]] = 0xFFFF;
234b78
         }
234b78
 
234b78
-        s->symbol = 0;
234b78
-        s->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
234b78
-        s->repeat = 0;
234b78
-        s->repeat_code_len = 0;
234b78
-        s->space = 32768;
234b78
-        s->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
234b78
+        h->symbol = 0;
234b78
+        h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
234b78
+        h->repeat = 0;
234b78
+        h->repeat_code_len = 0;
234b78
+        h->space = 32768;
234b78
+        h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
234b78
       }
234b78
       /* Fall through. */
234b78
 
234b78
       case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
234b78
         uint32_t table_size;
234b78
-        BrotliDecoderErrorCode result = ReadSymbolCodeLengths(max_symbol, s);
234b78
+        BrotliDecoderErrorCode result = ReadSymbolCodeLengths(
234b78
+            alphabet_size_limit, s);
234b78
         if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
234b78
-          result = SafeReadSymbolCodeLengths(max_symbol, s);
234b78
+          result = SafeReadSymbolCodeLengths(alphabet_size_limit, s);
234b78
         }
234b78
         if (result != BROTLI_DECODER_SUCCESS) {
234b78
           return result;
234b78
         }
234b78
 
234b78
-        if (s->space != 0) {
234b78
-          BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)s->space));
234b78
+        if (h->space != 0) {
234b78
+          BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)h->space));
234b78
           return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);
234b78
         }
234b78
         table_size = BrotliBuildHuffmanTable(
234b78
-            table, HUFFMAN_TABLE_BITS, s->symbol_lists, s->code_length_histo);
234b78
+            table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo);
234b78
         if (opt_table_size) {
234b78
           *opt_table_size = table_size;
234b78
         }
234b78
-        s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
234b78
+        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
234b78
         return BROTLI_DECODER_SUCCESS;
234b78
       }
234b78
 
234b78
@@ -858,8 +875,8 @@ static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table,
234b78
   uint32_t code;
234b78
   uint32_t nbits;
234b78
   code = ReadSymbol(table, br);
234b78
-  nbits = kBlockLengthPrefixCode[code].nbits;  /* nbits == 2..24 */
234b78
-  return kBlockLengthPrefixCode[code].offset + BrotliReadBits(br, nbits);
234b78
+  nbits = _kBrotliPrefixCodeRanges[code].nbits;  /* nbits == 2..24 */
234b78
+  return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits);
234b78
 }
234b78
 
234b78
 /* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then
234b78
@@ -877,13 +894,14 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(
234b78
   }
234b78
   {
234b78
     uint32_t bits;
234b78
-    uint32_t nbits = kBlockLengthPrefixCode[index].nbits;  /* nbits == 2..24 */
234b78
+    uint32_t nbits = _kBrotliPrefixCodeRanges[index].nbits;
234b78
+    uint32_t offset = _kBrotliPrefixCodeRanges[index].offset;
234b78
     if (!BrotliSafeReadBits(br, nbits, &bits)) {
234b78
       s->block_length_index = index;
234b78
       s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;
234b78
       return BROTLI_FALSE;
234b78
     }
234b78
-    *result = kBlockLengthPrefixCode[index].offset + bits;
234b78
+    *result = offset + bits;
234b78
     s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
234b78
     return BROTLI_TRUE;
234b78
   }
234b78
@@ -943,22 +961,22 @@ static BROTLI_NOINLINE void InverseMoveToFrontTransform(
234b78
 /* Decodes a series of Huffman table using ReadHuffmanCode function. */
234b78
 static BrotliDecoderErrorCode HuffmanTreeGroupDecode(
234b78
     HuffmanTreeGroup* group, BrotliDecoderState* s) {
234b78
-  if (s->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
234b78
-    s->next = group->codes;
234b78
-    s->htree_index = 0;
234b78
-    s->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
+  if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
234b78
+    h->next = group->codes;
234b78
+    h->htree_index = 0;
234b78
+    h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
234b78
   }
234b78
-  while (s->htree_index < group->num_htrees) {
234b78
+  while (h->htree_index < group->num_htrees) {
234b78
     uint32_t table_size;
234b78
-    BrotliDecoderErrorCode result =
234b78
-        ReadHuffmanCode(group->alphabet_size, group->max_symbol,
234b78
-                        s->next, &table_size, s);
234b78
+    BrotliDecoderErrorCode result = ReadHuffmanCode(group->alphabet_size_max,
234b78
+        group->alphabet_size_limit, h->next, &table_size, s);
234b78
     if (result != BROTLI_DECODER_SUCCESS) return result;
234b78
-    group->htrees[s->htree_index] = s->next;
234b78
-    s->next += table_size;
234b78
-    ++s->htree_index;
234b78
+    group->htrees[h->htree_index] = h->next;
234b78
+    h->next += table_size;
234b78
+    ++h->htree_index;
234b78
   }
234b78
-  s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
234b78
+  h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
234b78
   return BROTLI_DECODER_SUCCESS;
234b78
 }
234b78
 
234b78
@@ -976,15 +994,16 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
234b78
                                                BrotliDecoderState* s) {
234b78
   BrotliBitReader* br = &s->br;
234b78
   BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
234b78
+  BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
 
234b78
-  switch ((int)s->substate_context_map) {
234b78
+  switch ((int)h->substate_context_map) {
234b78
     case BROTLI_STATE_CONTEXT_MAP_NONE:
234b78
       result = DecodeVarLenUint8(s, br, num_htrees);
234b78
       if (result != BROTLI_DECODER_SUCCESS) {
234b78
         return result;
234b78
       }
234b78
       (*num_htrees)++;
234b78
-      s->context_index = 0;
234b78
+      h->context_index = 0;
234b78
       BROTLI_LOG_UINT(context_map_size);
234b78
       BROTLI_LOG_UINT(*num_htrees);
234b78
       *context_map_arg =
234b78
@@ -996,7 +1015,7 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
234b78
         memset(*context_map_arg, 0, (size_t)context_map_size);
234b78
         return BROTLI_DECODER_SUCCESS;
234b78
       }
234b78
-      s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
234b78
+      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
234b78
     /* Fall through. */
234b78
 
234b78
     case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {
234b78
@@ -1007,38 +1026,38 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
234b78
         return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
       }
234b78
       if ((bits & 1) != 0) { /* Use RLE for zeros. */
234b78
-        s->max_run_length_prefix = (bits >> 1) + 1;
234b78
+        h->max_run_length_prefix = (bits >> 1) + 1;
234b78
         BrotliDropBits(br, 5);
234b78
       } else {
234b78
-        s->max_run_length_prefix = 0;
234b78
+        h->max_run_length_prefix = 0;
234b78
         BrotliDropBits(br, 1);
234b78
       }
234b78
-      BROTLI_LOG_UINT(s->max_run_length_prefix);
234b78
-      s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
234b78
+      BROTLI_LOG_UINT(h->max_run_length_prefix);
234b78
+      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
234b78
     }
234b78
     /* Fall through. */
234b78
 
234b78
     case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {
234b78
-      uint32_t alphabet_size = *num_htrees + s->max_run_length_prefix;
234b78
+      uint32_t alphabet_size = *num_htrees + h->max_run_length_prefix;
234b78
       result = ReadHuffmanCode(alphabet_size, alphabet_size,
234b78
-                               s->context_map_table, NULL, s);
234b78
+                               h->context_map_table, NULL, s);
234b78
       if (result != BROTLI_DECODER_SUCCESS) return result;
234b78
-      s->code = 0xFFFF;
234b78
-      s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
234b78
+      h->code = 0xFFFF;
234b78
+      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
234b78
     }
234b78
     /* Fall through. */
234b78
 
234b78
     case BROTLI_STATE_CONTEXT_MAP_DECODE: {
234b78
-      uint32_t context_index = s->context_index;
234b78
-      uint32_t max_run_length_prefix = s->max_run_length_prefix;
234b78
+      uint32_t context_index = h->context_index;
234b78
+      uint32_t max_run_length_prefix = h->max_run_length_prefix;
234b78
       uint8_t* context_map = *context_map_arg;
234b78
-      uint32_t code = s->code;
234b78
+      uint32_t code = h->code;
234b78
       BROTLI_BOOL skip_preamble = (code != 0xFFFF);
234b78
       while (context_index < context_map_size || skip_preamble) {
234b78
         if (!skip_preamble) {
234b78
-          if (!SafeReadSymbol(s->context_map_table, br, &code)) {
234b78
-            s->code = 0xFFFF;
234b78
-            s->context_index = context_index;
234b78
+          if (!SafeReadSymbol(h->context_map_table, br, &code)) {
234b78
+            h->code = 0xFFFF;
234b78
+            h->context_index = context_index;
234b78
             return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
           }
234b78
           BROTLI_LOG_UINT(code);
234b78
@@ -1059,8 +1078,8 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
234b78
         {
234b78
           uint32_t reps;
234b78
           if (!BrotliSafeReadBits(br, code, &reps)) {
234b78
-            s->code = code;
234b78
-            s->context_index = context_index;
234b78
+            h->code = code;
234b78
+            h->context_index = context_index;
234b78
             return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
           }
234b78
           reps += 1U << code;
234b78
@@ -1080,13 +1099,13 @@ static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
234b78
     case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {
234b78
       uint32_t bits;
234b78
       if (!BrotliSafeReadBits(br, 1, &bits)) {
234b78
-        s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
234b78
+        h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
234b78
         return BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
       }
234b78
       if (bits != 0) {
234b78
         InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);
234b78
       }
234b78
-      s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
234b78
+      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
234b78
       return BROTLI_DECODER_SUCCESS;
234b78
     }
234b78
 
234b78
@@ -1448,32 +1467,28 @@ static BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {
234b78
 }
234b78
 
234b78
 static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {
234b78
-  if (s->distance_code == 0) {
234b78
-    --s->dist_rb_idx;
234b78
-    s->distance_code = s->dist_rb[s->dist_rb_idx & 3];
234b78
+  int offset = s->distance_code - 3;
234b78
+  if (s->distance_code <= 3) {
234b78
     /* Compensate double distance-ring-buffer roll for dictionary items. */
234b78
-    s->distance_context = 1;
234b78
+    s->distance_context = 1 >> s->distance_code;
234b78
+    s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3];
234b78
+    s->dist_rb_idx -= s->distance_context;
234b78
   } else {
234b78
-    int distance_code = s->distance_code << 1;
234b78
-    /* kDistanceShortCodeIndexOffset has 2-bit values from LSB:
234b78
-        3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */
234b78
-    const uint32_t kDistanceShortCodeIndexOffset = 0xAAAFFF1B;
234b78
-    /* kDistanceShortCodeValueOffset has 2-bit values from LSB:
234b78
-       -0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */
234b78
-    const uint32_t kDistanceShortCodeValueOffset = 0xFA5FA500;
234b78
-    int v = (s->dist_rb_idx +
234b78
-        (int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3;
234b78
-    s->distance_code = s->dist_rb[v];
234b78
-    v = (int)(kDistanceShortCodeValueOffset >> distance_code) & 0x3;
234b78
-    if ((distance_code & 0x3) != 0) {
234b78
-      s->distance_code += v;
234b78
+    int index_delta = 3;
234b78
+    int delta;
234b78
+    int base = s->distance_code - 10;
234b78
+    if (s->distance_code < 10) {
234b78
+      base = s->distance_code - 4;
234b78
     } else {
234b78
-      s->distance_code -= v;
234b78
-      if (s->distance_code <= 0) {
234b78
-        /* A huge distance will cause a BROTLI_FAILURE() soon.
234b78
-           This is a little faster than failing here. */
234b78
-        s->distance_code = 0x7FFFFFFF;
234b78
-      }
234b78
+      index_delta = 2;
234b78
+    }
234b78
+    /* Unpack one of six 4-bit values. */
234b78
+    delta = ((0x605142 >> (4 * base)) & 0xF) - 3;
234b78
+    s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta;
234b78
+    if (s->distance_code <= 0) {
234b78
+      /* A huge distance will cause a BROTLI_FAILURE() soon.
234b78
+         This is a little faster than failing here. */
234b78
+      s->distance_code = 0x7FFFFFFF;
234b78
     }
234b78
   }
234b78
 }
234b78
@@ -1488,62 +1503,153 @@ static BROTLI_INLINE BROTLI_BOOL SafeReadBits(
234b78
   }
234b78
 }
234b78
 
234b78
+static BROTLI_INLINE BROTLI_BOOL SafeReadBits32(
234b78
+    BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
234b78
+  if (n_bits != 0) {
234b78
+    return BrotliSafeReadBits32(br, n_bits, val);
234b78
+  } else {
234b78
+    *val = 0;
234b78
+    return BROTLI_TRUE;
234b78
+  }
234b78
+}
234b78
+
234b78
+/*
234b78
+   RFC 7932 Section 4 with "..." shortenings and "[]" emendations.
234b78
+
234b78
+   Each distance ... is represented with a pair <distance code, extra bits>...
234b78
+   The distance code is encoded using a prefix code... The number of extra bits
234b78
+   can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ...
234b78
+   NDIRECT (0..120) ... are encoded in the meta-block header...
234b78
+
234b78
+   The first 16 distance symbols ... reference past distances... ring buffer ...
234b78
+   Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT...
234b78
+   [For] distance symbols 16 + NDIRECT and greater ... the number of extra bits
234b78
+   ... is given by the following formula:
234b78
+
234b78
+   [ xcode = dcode - NDIRECT - 16 ]
234b78
+   ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1)
234b78
+
234b78
+   ...
234b78
+*/
234b78
+
234b78
+/*
234b78
+   RFC 7932 Section 9.2 with "..." shortenings and "[]" emendations.
234b78
+
234b78
+   ... to get the actual value of the parameter NDIRECT, left-shift this
234b78
+   four-bit number by NPOSTFIX bits ...
234b78
+*/
234b78
+
234b78
+/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following:
234b78
+
234b78
+     alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1))
234b78
+
234b78
+     half = ((xcode >> NPOSTFIX) & 1) << ndistbits
234b78
+     postfix = xcode & ((1 << NPOSTFIX) - 1)
234b78
+     range_start = 2 * (1 << ndistbits - 1 - 1)
234b78
+
234b78
+     distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1
234b78
+
234b78
+   NB: ndistbits >= 1 -> range_start >= 0
234b78
+   NB: range_start has factor 2, as the range is covered by 2 "halves"
234b78
+   NB: extra -1 offset in range_start formula covers the absence of
234b78
+       ndistbits = 0 case
234b78
+   NB: when NPOSTFIX = 0, NDIRECT is not greater than 15
234b78
+
234b78
+   In other words, xcode has the following binary structure - XXXHPPP:
234b78
+    - XXX represent the number of extra distance bits
234b78
+    - H selects upper / lower range of distances
234b78
+    - PPP represent "postfix"
234b78
+
234b78
+  "Regular" distance encoding has NPOSTFIX = 0; omitting the postfix part
234b78
+  simplifies distance calculation.
234b78
+
234b78
+  Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where
234b78
+  most of distances have the same reminder of division by 2/4/8. For example,
234b78
+  the table of int32_t values that come from different sources; if it is likely
234b78
+  that 3 highest bytes of values from the same source are the same, then
234b78
+  copy distance often looks like 4x + y.
234b78
+
234b78
+  Distance calculation could be rewritten to:
234b78
+
234b78
+    ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode]
234b78
+    distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX
234b78
+
234b78
+  NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could
234b78
+  change only once per meta-block.
234b78
+*/
234b78
+
234b78
+/* Calculates distance lookup table.
234b78
+   NB: it is possible to have all 64 tables precalculated. */
234b78
+static void CalculateDistanceLut(BrotliDecoderState* s) {
234b78
+  BrotliMetablockBodyArena* b = &s->arena.body;
234b78
+  uint32_t npostfix = s->distance_postfix_bits;
234b78
+  uint32_t ndirect = s->num_direct_distance_codes;
234b78
+  uint32_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit;
234b78
+  uint32_t postfix = 1u << npostfix;
234b78
+  uint32_t j;
234b78
+  uint32_t bits = 1;
234b78
+  uint32_t half = 0;
234b78
+
234b78
+  /* Skip short codes. */
234b78
+  uint32_t i = BROTLI_NUM_DISTANCE_SHORT_CODES;
234b78
+
234b78
+  /* Fill direct codes. */
234b78
+  for (j = 0; j < ndirect; ++j) {
234b78
+    b->dist_extra_bits[i] = 0;
234b78
+    b->dist_offset[i] = j + 1;
234b78
+    ++i;
234b78
+  }
234b78
+
234b78
+  /* Fill regular distance codes. */
234b78
+  while (i < alphabet_size_limit) {
234b78
+    uint32_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
234b78
+    /* Always fill the complete group. */
234b78
+    for (j = 0; j < postfix; ++j) {
234b78
+      b->dist_extra_bits[i] = (uint8_t)bits;
234b78
+      b->dist_offset[i] = base + j;
234b78
+      ++i;
234b78
+    }
234b78
+    bits = bits + half;
234b78
+    half = half ^ 1;
234b78
+  }
234b78
+}
234b78
+
234b78
 /* Precondition: s->distance_code < 0. */
234b78
 static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
234b78
     int safe, BrotliDecoderState* s, BrotliBitReader* br) {
234b78
-  int distval;
234b78
+  BrotliMetablockBodyArena* b = &s->arena.body;
234b78
+  uint32_t code;
234b78
+  uint32_t bits;
234b78
   BrotliBitReaderState memento;
234b78
   HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index];
234b78
   if (!safe) {
234b78
-    s->distance_code = (int)ReadSymbol(distance_tree, br);
234b78
+    code = ReadSymbol(distance_tree, br);
234b78
   } else {
234b78
-    uint32_t code;
234b78
     BrotliBitReaderSaveState(br, &memento);
234b78
     if (!SafeReadSymbol(distance_tree, br, &code)) {
234b78
       return BROTLI_FALSE;
234b78
     }
234b78
-    s->distance_code = (int)code;
234b78
   }
234b78
+  --s->block_length[2];
234b78
   /* Convert the distance code to the actual distance by possibly
234b78
-     looking up past distances from the s->ringbuffer. */
234b78
+     looking up past distances from the s->dist_rb. */
234b78
   s->distance_context = 0;
234b78
-  if ((s->distance_code & ~0xF) == 0) {
234b78
+  if ((code & ~0xFu) == 0) {
234b78
+    s->distance_code = (int)code;
234b78
     TakeDistanceFromRingBuffer(s);
234b78
-    --s->block_length[2];
234b78
     return BROTLI_TRUE;
234b78
   }
234b78
-  distval = s->distance_code - (int)s->num_direct_distance_codes;
234b78
-  if (distval >= 0) {
234b78
-    uint32_t nbits;
234b78
-    int postfix;
234b78
-    int offset;
234b78
-    if (!safe && (s->distance_postfix_bits == 0)) {
234b78
-      nbits = ((uint32_t)distval >> 1) + 1;
234b78
-      offset = ((2 + (distval & 1)) << nbits) - 4;
234b78
-      s->distance_code = (int)s->num_direct_distance_codes + offset +
234b78
-                         (int)BrotliReadBits(br, nbits);
234b78
-    } else {
234b78
-      /* This branch also works well when s->distance_postfix_bits == 0. */
234b78
-      uint32_t bits;
234b78
-      postfix = distval & s->distance_postfix_mask;
234b78
-      distval >>= s->distance_postfix_bits;
234b78
-      nbits = ((uint32_t)distval >> 1) + 1;
234b78
-      if (safe) {
234b78
-        if (!SafeReadBits(br, nbits, &bits)) {
234b78
-          s->distance_code = -1;  /* Restore precondition. */
234b78
-          BrotliBitReaderRestoreState(br, &memento);
234b78
-          return BROTLI_FALSE;
234b78
-        }
234b78
-      } else {
234b78
-        bits = BrotliReadBits(br, nbits);
234b78
-      }
234b78
-      offset = ((2 + (distval & 1)) << nbits) - 4;
234b78
-      s->distance_code = (int)s->num_direct_distance_codes +
234b78
-          ((offset + (int)bits) << s->distance_postfix_bits) + postfix;
234b78
+  if (!safe) {
234b78
+    bits = BrotliReadBits32(br, b->dist_extra_bits[code]);
234b78
+  } else {
234b78
+    if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) {
234b78
+      ++s->block_length[2];
234b78
+      BrotliBitReaderRestoreState(br, &memento);
234b78
+      return BROTLI_FALSE;
234b78
     }
234b78
   }
234b78
-  s->distance_code = s->distance_code - BROTLI_NUM_DISTANCE_SHORT_CODES + 1;
234b78
-  --s->block_length[2];
234b78
+  s->distance_code =
234b78
+      (int)(b->dist_offset[code] + (bits << s->distance_postfix_bits));
234b78
   return BROTLI_TRUE;
234b78
 }
234b78
 
234b78
@@ -1579,9 +1685,9 @@ static BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(
234b78
   *insert_length = v.insert_len_offset;
234b78
   if (!safe) {
234b78
     if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) {
234b78
-      insert_len_extra = BrotliReadBits(br, v.insert_len_extra_bits);
234b78
+      insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits);
234b78
     }
234b78
-    copy_length = BrotliReadBits(br, v.copy_len_extra_bits);
234b78
+    copy_length = BrotliReadBits24(br, v.copy_len_extra_bits);
234b78
   } else {
234b78
     if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) ||
234b78
         !SafeReadBits(br, v.copy_len_extra_bits, &copy_length)) {
234b78
@@ -1926,21 +2032,6 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
234b78
   return ProcessCommandsInternal(1, s);
234b78
 }
234b78
 
234b78
-/* Returns the maximum number of distance symbols which can only represent
234b78
-   distances not exceeding BROTLI_MAX_ALLOWED_DISTANCE. */
234b78
-static uint32_t BrotliMaxDistanceSymbol(uint32_t ndirect, uint32_t npostfix) {
234b78
-  static const uint32_t bound[BROTLI_MAX_NPOSTFIX + 1] = {0, 4, 12, 28};
234b78
-  static const uint32_t diff[BROTLI_MAX_NPOSTFIX + 1] = {73, 126, 228, 424};
234b78
-  uint32_t postfix = 1U << npostfix;
234b78
-  if (ndirect < bound[npostfix]) {
234b78
-    return ndirect + diff[npostfix] + postfix;
234b78
-  } else if (ndirect > bound[npostfix] + postfix) {
234b78
-    return ndirect + diff[npostfix];
234b78
-  } else {
234b78
-    return bound[npostfix] + diff[npostfix] + postfix;
234b78
-  }
234b78
-}
234b78
-
234b78
 BrotliDecoderResult BrotliDecoderDecompress(
234b78
     size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
234b78
     uint8_t* decoded_buffer) {
234b78
@@ -2158,33 +2249,23 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
234b78
           s->state = BROTLI_STATE_UNCOMPRESSED;
234b78
           break;
234b78
         }
234b78
+        s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER;
234b78
+      /* Fall through. */
234b78
+
234b78
+      case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: {
234b78
+        BrotliMetablockHeaderArena* h = &s->arena.header;
234b78
         s->loop_counter = 0;
234b78
+        /* Initialize compressed metablock header arena. */
234b78
+        h->sub_loop_counter = 0;
234b78
+        /* Make small negative indexes addressable. */
234b78
+        h->symbol_lists =
234b78
+            &h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
234b78
+        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
234b78
+        h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
234b78
+        h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
234b78
         s->state = BROTLI_STATE_HUFFMAN_CODE_0;
234b78
-        break;
234b78
-
234b78
-      case BROTLI_STATE_UNCOMPRESSED: {
234b78
-        result = CopyUncompressedBlockToOutput(
234b78
-            available_out, next_out, total_out, s);
234b78
-        if (result != BROTLI_DECODER_SUCCESS) {
234b78
-          break;
234b78
-        }
234b78
-        s->state = BROTLI_STATE_METABLOCK_DONE;
234b78
-        break;
234b78
       }
234b78
-
234b78
-      case BROTLI_STATE_METADATA:
234b78
-        for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
234b78
-          uint32_t bits;
234b78
-          /* Read one byte and ignore it. */
234b78
-          if (!BrotliSafeReadBits(br, 8, &bits)) {
234b78
-            result = BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
-            break;
234b78
-          }
234b78
-        }
234b78
-        if (result == BROTLI_DECODER_SUCCESS) {
234b78
-          s->state = BROTLI_STATE_METABLOCK_DONE;
234b78
-        }
234b78
-        break;
234b78
+      /* Fall through. */
234b78
 
234b78
       case BROTLI_STATE_HUFFMAN_CODE_0:
234b78
         if (s->loop_counter >= 3) {
234b78
@@ -2238,6 +2319,30 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
234b78
         break;
234b78
       }
234b78
 
234b78
+      case BROTLI_STATE_UNCOMPRESSED: {
234b78
+        result = CopyUncompressedBlockToOutput(
234b78
+            available_out, next_out, total_out, s);
234b78
+        if (result != BROTLI_DECODER_SUCCESS) {
234b78
+          break;
234b78
+        }
234b78
+        s->state = BROTLI_STATE_METABLOCK_DONE;
234b78
+        break;
234b78
+      }
234b78
+
234b78
+      case BROTLI_STATE_METADATA:
234b78
+        for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
234b78
+          uint32_t bits;
234b78
+          /* Read one byte and ignore it. */
234b78
+          if (!BrotliSafeReadBits(br, 8, &bits)) {
234b78
+            result = BROTLI_DECODER_NEEDS_MORE_INPUT;
234b78
+            break;
234b78
+          }
234b78
+        }
234b78
+        if (result == BROTLI_DECODER_SUCCESS) {
234b78
+          s->state = BROTLI_STATE_METABLOCK_DONE;
234b78
+        }
234b78
+        break;
234b78
+
234b78
       case BROTLI_STATE_METABLOCK_HEADER_2: {
234b78
         uint32_t bits;
234b78
         if (!BrotliSafeReadBits(br, 6, &bits)) {
234b78
@@ -2246,11 +2351,9 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
234b78
         }
234b78
         s->distance_postfix_bits = bits & BitMask(2);
234b78
         bits >>= 2;
234b78
-        s->num_direct_distance_codes = BROTLI_NUM_DISTANCE_SHORT_CODES +
234b78
-            (bits << s->distance_postfix_bits);
234b78
+        s->num_direct_distance_codes = bits << s->distance_postfix_bits;
234b78
         BROTLI_LOG_UINT(s->num_direct_distance_codes);
234b78
         BROTLI_LOG_UINT(s->distance_postfix_bits);
234b78
-        s->distance_postfix_mask = (int)BitMask(s->distance_postfix_bits);
234b78
         s->context_modes =
234b78
             (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);
234b78
         if (s->context_modes == 0) {
234b78
@@ -2282,17 +2385,19 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
234b78
       /* Fall through. */
234b78
 
234b78
       case BROTLI_STATE_CONTEXT_MAP_2: {
234b78
-        uint32_t num_direct_codes =
234b78
-            s->num_direct_distance_codes - BROTLI_NUM_DISTANCE_SHORT_CODES;
234b78
-        uint32_t num_distance_codes = BROTLI_DISTANCE_ALPHABET_SIZE(
234b78
-            s->distance_postfix_bits, num_direct_codes,
234b78
-            (s->large_window ? BROTLI_LARGE_MAX_DISTANCE_BITS :
234b78
-                               BROTLI_MAX_DISTANCE_BITS));
234b78
-        uint32_t max_distance_symbol = (s->large_window ?
234b78
-            BrotliMaxDistanceSymbol(
234b78
-                num_direct_codes, s->distance_postfix_bits) :
234b78
-            num_distance_codes);
234b78
+        uint32_t npostfix = s->distance_postfix_bits;
234b78
+        uint32_t ndirect = s->num_direct_distance_codes;
234b78
+        uint32_t distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
234b78
+            npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);
234b78
+        uint32_t distance_alphabet_size_limit = distance_alphabet_size_max;
234b78
         BROTLI_BOOL allocation_success = BROTLI_TRUE;
234b78
+        if (s->large_window) {
234b78
+          BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
234b78
+              BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);
234b78
+          distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
234b78
+              npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);
234b78
+          distance_alphabet_size_limit = limit.max_alphabet_size;
234b78
+        }
234b78
         result = DecodeContextMap(
234b78
             s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,
234b78
             &s->num_dist_htrees, &s->dist_context_map, s);
234b78
@@ -2306,8 +2411,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
234b78
             s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,
234b78
             BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);
234b78
         allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
234b78
-            s, &s->distance_hgroup, num_distance_codes,
234b78
-            max_distance_symbol, s->num_dist_htrees);
234b78
+            s, &s->distance_hgroup, distance_alphabet_size_max,
234b78
+            distance_alphabet_size_limit, s->num_dist_htrees);
234b78
         if (!allocation_success) {
234b78
           return SaveErrorCode(s,
234b78
               BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));
234b78
@@ -2329,18 +2434,24 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
234b78
         result = HuffmanTreeGroupDecode(hgroup, s);
234b78
         if (result != BROTLI_DECODER_SUCCESS) break;
234b78
         s->loop_counter++;
234b78
-        if (s->loop_counter >= 3) {
234b78
-          PrepareLiteralDecoding(s);
234b78
-          s->dist_context_map_slice = s->dist_context_map;
234b78
-          s->htree_command = s->insert_copy_hgroup.htrees[0];
234b78
-          if (!BrotliEnsureRingBuffer(s)) {
234b78
-            result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
234b78
-            break;
234b78
-          }
234b78
-          s->state = BROTLI_STATE_COMMAND_BEGIN;
234b78
+        if (s->loop_counter < 3) {
234b78
+          break;
234b78
         }
234b78
-        break;
234b78
+        s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY;
234b78
       }
234b78
+      /* Fall through. */
234b78
+
234b78
+      case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY:
234b78
+        PrepareLiteralDecoding(s);
234b78
+        s->dist_context_map_slice = s->dist_context_map;
234b78
+        s->htree_command = s->insert_copy_hgroup.htrees[0];
234b78
+        if (!BrotliEnsureRingBuffer(s)) {
234b78
+          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
234b78
+          break;
234b78
+        }
234b78
+        CalculateDistanceLut(s);
234b78
+        s->state = BROTLI_STATE_COMMAND_BEGIN;
234b78
+      /* Fall through. */
234b78
 
234b78
       case BROTLI_STATE_COMMAND_BEGIN:
234b78
       /* Fall through. */
234b78
diff --git a/c/dec/huffman.h b/c/dec/huffman.h
234b78
index 521ec6e..a8fbc45 100644
234b78
--- a/c/dec/huffman.h
234b78
+++ b/c/dec/huffman.h
234b78
@@ -18,12 +18,6 @@ extern "C" {
234b78
 
234b78
 #define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15
234b78
 
234b78
-/* Maximum possible Huffman table size for an alphabet size of (index * 32),
234b78
-   max code length 15 and root table bits 8. */
234b78
-static const uint16_t kMaxHuffmanTableSize[] = {
234b78
-  256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
234b78
-  854, 886, 920, 952, 984, 1016, 1048, 1080, 1112, 1144, 1176, 1208, 1240, 1272,
234b78
-  1304, 1336, 1368, 1400, 1432, 1464, 1496, 1528};
234b78
 /* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */
234b78
 #define BROTLI_HUFFMAN_MAX_SIZE_26 396
234b78
 /* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */
234b78
@@ -33,11 +27,66 @@ static const uint16_t kMaxHuffmanTableSize[] = {
234b78
 
234b78
 #define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5
234b78
 
234b78
+#if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \
234b78
+  BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0))
234b78
+#define BROTLI_HUFFMAN_CODE_FAST_LOAD
234b78
+#endif
234b78
+
234b78
+#if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD)
234b78
+/* Do not create this struct directly - use the ConstructHuffmanCode
234b78
+ * constructor below! */
234b78
 typedef struct {
234b78
   uint8_t bits;    /* number of bits used for this symbol */
234b78
   uint16_t value;  /* symbol value or table offset */
234b78
 } HuffmanCode;
234b78
 
234b78
+static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
234b78
+    const uint16_t value) {
234b78
+  HuffmanCode h;
234b78
+  h.bits = bits;
234b78
+  h.value = value;
234b78
+  return h;
234b78
+}
234b78
+
234b78
+/* Please use the following macros to optimize HuffmanCode accesses in hot
234b78
+ * paths.
234b78
+ *
234b78
+ * For example, assuming |table| contains a HuffmanCode pointer:
234b78
+ *
234b78
+ *   BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
234b78
+ *   BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table);
234b78
+ *   *bits = BROTLI_HC_GET_BITS(table);
234b78
+ *   *value = BROTLI_HC_GET_VALUE(table);
234b78
+ *   BROTLI_HC_ADJUST_TABLE_INDEX(table, offset);
234b78
+ *   *bits2 = BROTLI_HC_GET_BITS(table);
234b78
+ *   *value2 = BROTLI_HC_GET_VALUE(table);
234b78
+ *
234b78
+ */
234b78
+
234b78
+#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H)
234b78
+#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V)
234b78
+
234b78
+/* These must be given a HuffmanCode pointer! */
234b78
+#define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits)
234b78
+#define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value)
234b78
+
234b78
+#else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
234b78
+
234b78
+typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;
234b78
+
234b78
+static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
234b78
+    const uint16_t value) {
234b78
+  return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);
234b78
+}
234b78
+
234b78
+#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)
234b78
+#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H)
234b78
+
234b78
+/* These must be given a HuffmanCode pointer! */
234b78
+#define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF)
234b78
+#define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16)
234b78
+#endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
234b78
+
234b78
 /* Builds Huffman lookup table assuming code lengths are in symbol order. */
234b78
 BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
234b78
     const uint8_t* const code_lengths, uint16_t* count);
234b78
@@ -45,7 +94,7 @@ BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
234b78
 /* Builds Huffman lookup table assuming code lengths are in symbol order.
234b78
    Returns size of resulting table. */
234b78
 BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
234b78
-    int root_bits, const uint16_t* const symbol_lists, uint16_t* count_arg);
234b78
+    int root_bits, const uint16_t* const symbol_lists, uint16_t* count);
234b78
 
234b78
 /* Builds a simple Huffman table. The |num_symbols| parameter is to be
234b78
    interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,
234b78
@@ -55,13 +104,13 @@ BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
234b78
     int root_bits, uint16_t* symbols, uint32_t num_symbols);
234b78
 
234b78
 /* Contains a collection of Huffman trees with the same alphabet size. */
234b78
-/* max_symbol is needed due to simple codes since log2(alphabet_size) could be
234b78
-   greater than log2(max_symbol). */
234b78
+/* alphabet_size_limit is needed due to simple codes, since
234b78
+   log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */
234b78
 typedef struct {
234b78
   HuffmanCode** htrees;
234b78
   HuffmanCode* codes;
234b78
-  uint16_t alphabet_size;
234b78
-  uint16_t max_symbol;
234b78
+  uint16_t alphabet_size_max;
234b78
+  uint16_t alphabet_size_limit;
234b78
   uint16_t num_htrees;
234b78
 } HuffmanTreeGroup;
234b78
 
234b78
diff --git a/c/dec/prefix.h b/c/dec/prefix.h
234b78
index 3ea062d..481a2c7 100644
234b78
--- a/c/dec/prefix.h
234b78
+++ b/c/dec/prefix.h
234b78
@@ -13,24 +13,6 @@
234b78
 #include "../common/constants.h"
234b78
 #include <brotli/types.h>
234b78
 
234b78
-/* Represents the range of values belonging to a prefix code:
234b78
-   [offset, offset + 2^nbits) */
234b78
-struct PrefixCodeRange {
234b78
-  uint16_t offset;
234b78
-  uint8_t nbits;
234b78
-};
234b78
-
234b78
-static const struct PrefixCodeRange
234b78
-    kBlockLengthPrefixCode[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
234b78
-  {   1,  2}, {    5,  2}, {  9,   2}, {  13,  2},
234b78
-  {  17,  3}, {   25,  3}, {  33,  3}, {  41,  3},
234b78
-  {  49,  4}, {   65,  4}, {  81,  4}, {  97,  4},
234b78
-  { 113,  5}, {  145,  5}, { 177,  5}, { 209,  5},
234b78
-  { 241,  6}, {  305,  6}, { 369,  7}, { 497,  8},
234b78
-  { 753,  9}, { 1265, 10}, {2289, 11}, {4337, 12},
234b78
-  {8433, 13}, {16625, 24}
234b78
-};
234b78
-
234b78
 typedef struct CmdLutElement {
234b78
   uint8_t insert_len_extra_bits;
234b78
   uint8_t copy_len_extra_bits;
234b78
diff --git a/c/dec/state.c b/c/dec/state.c
234b78
index e0b37c2..f847836 100644
234b78
--- a/c/dec/state.c
234b78
+++ b/c/dec/state.c
234b78
@@ -33,10 +33,7 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
234b78
   s->state = BROTLI_STATE_UNINITED;
234b78
   s->large_window = 0;
234b78
   s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
234b78
-  s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
234b78
-  s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
234b78
   s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
234b78
-  s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
234b78
   s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
234b78
   s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
234b78
 
234b78
@@ -59,8 +56,6 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
234b78
   s->context_map_slice = NULL;
234b78
   s->dist_context_map_slice = NULL;
234b78
 
234b78
-  s->sub_loop_counter = 0;
234b78
-
234b78
   s->literal_hgroup.codes = NULL;
234b78
   s->literal_hgroup.htrees = NULL;
234b78
   s->insert_copy_hgroup.codes = NULL;
234b78
@@ -84,9 +79,6 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
234b78
   s->block_type_trees = NULL;
234b78
   s->block_len_trees = NULL;
234b78
 
234b78
-  /* Make small negative indexes addressable. */
234b78
-  s->symbol_lists = &s->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
234b78
-
234b78
   s->mtf_upper_bound = 63;
234b78
 
234b78
   s->dictionary = BrotliGetDictionary();
234b78
@@ -142,17 +134,20 @@ void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
234b78
 }
234b78
 
234b78
 BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,
234b78
-    HuffmanTreeGroup* group, uint32_t alphabet_size, uint32_t max_symbol,
234b78
-    uint32_t ntrees) {
234b78
-  /* Pack two allocations into one */
234b78
-  const size_t max_table_size = kMaxHuffmanTableSize[(alphabet_size + 31) >> 5];
234b78
+    HuffmanTreeGroup* group, uint32_t alphabet_size_max,
234b78
+    uint32_t alphabet_size_limit, uint32_t ntrees) {
234b78
+  /* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)
234b78
+     This number is discovered "unlimited" "enough" calculator; it is actually
234b78
+     a wee bigger than required in several cases (especially for alphabets with
234b78
+     less than 16 symbols). */
234b78
+  const size_t max_table_size = alphabet_size_limit + 376;
234b78
   const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
234b78
   const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
234b78
   /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */
234b78
   HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,
234b78
       code_size + htree_size);
234b78
-  group->alphabet_size = (uint16_t)alphabet_size;
234b78
-  group->max_symbol = (uint16_t)max_symbol;
234b78
+  group->alphabet_size_max = (uint16_t)alphabet_size_max;
234b78
+  group->alphabet_size_limit = (uint16_t)alphabet_size_limit;
234b78
   group->num_htrees = (uint16_t)ntrees;
234b78
   group->htrees = p;
234b78
   group->codes = (HuffmanCode*)(&p[ntrees]);
234b78
diff --git a/c/dec/state.h b/c/dec/state.h
234b78
index d28b639..54dab69 100644
234b78
--- a/c/dec/state.h
234b78
+++ b/c/dec/state.h
234b78
@@ -21,6 +21,95 @@
234b78
 extern "C" {
234b78
 #endif
234b78
 
234b78
+/* Graphviz diagram that describes state transitions:
234b78
+
234b78
+digraph States {
234b78
+  graph [compound=true]
234b78
+  concentrate=true
234b78
+  node [shape="box"]
234b78
+
234b78
+  UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}
234b78
+  subgraph cluster_metablock_workflow {
234b78
+    style="rounded"
234b78
+    label=< METABLOCK CYCLE >
234b78
+    METABLOCK_BEGIN -> METABLOCK_HEADER
234b78
+    METABLOCK_HEADER:sw -> METADATA
234b78
+    METABLOCK_HEADER:s -> UNCOMPRESSED
234b78
+    METABLOCK_HEADER:se -> METABLOCK_DONE:ne
234b78
+    METADATA:s -> METABLOCK_DONE:w
234b78
+    UNCOMPRESSED:s -> METABLOCK_DONE:n
234b78
+    METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint="false"]
234b78
+  }
234b78
+  INITIALIZE -> METABLOCK_BEGIN
234b78
+  METABLOCK_DONE -> DONE
234b78
+
234b78
+  subgraph cluster_compressed_metablock {
234b78
+    style="rounded"
234b78
+    label=< COMPRESSED METABLOCK >
234b78
+
234b78
+    subgraph cluster_command {
234b78
+      style="rounded"
234b78
+      label=< HOT LOOP >
234b78
+
234b78
+      _METABLOCK_DONE_PORT_ [shape=point style=invis]
234b78
+
234b78
+      {
234b78
+        // Set different shape for nodes returning from "compressed metablock".
234b78
+        node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;
234b78
+        CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;
234b78
+      }
234b78
+
234b78
+      CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY
234b78
+
234b78
+      // IO ("write") nodes are not in the hot loop!
234b78
+      CMD_INNER_WRITE [style=dashed]
234b78
+      CMD_INNER -> CMD_INNER_WRITE
234b78
+      CMD_POST_WRITE_1 [style=dashed]
234b78
+      CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1
234b78
+      CMD_POST_WRITE_2 [style=dashed]
234b78
+      CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2
234b78
+
234b78
+      CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint="false"]
234b78
+      CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}
234b78
+          [constraint="false"]
234b78
+      CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint="false"]
234b78
+      CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint="false"]
234b78
+      CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint="false"]
234b78
+      CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint="false"]
234b78
+      {rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;
234b78
+          CMD_POST_WRAP_COPY}
234b78
+      {rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}
234b78
+
234b78
+      {CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->
234b78
+          _METABLOCK_DONE_PORT_ [style=invis]
234b78
+      {CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_
234b78
+          [constraint="false" style=invis]
234b78
+    }
234b78
+
234b78
+    BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n
234b78
+    HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3
234b78
+    HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1
234b78
+    CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP
234b78
+    TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e
234b78
+    BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n
234b78
+
234b78
+    HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint="false"]
234b78
+    {rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}
234b78
+    {rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;
234b78
+        TREE_GROUP}
234b78
+  }
234b78
+  METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n
234b78
+
234b78
+  _METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se
234b78
+      [constraint="false" ltail=cluster_command]
234b78
+
234b78
+  UNINITED [shape=Mdiamond];
234b78
+  DONE [shape=Msquare];
234b78
+}
234b78
+
234b78
+
234b78
+ */
234b78
+
234b78
 typedef enum {
234b78
   BROTLI_STATE_UNINITED,
234b78
   BROTLI_STATE_LARGE_WINDOW_BITS,
234b78
@@ -39,6 +128,7 @@ typedef enum {
234b78
   BROTLI_STATE_METABLOCK_DONE,
234b78
   BROTLI_STATE_COMMAND_POST_WRITE_1,
234b78
   BROTLI_STATE_COMMAND_POST_WRITE_2,
234b78
+  BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,
234b78
   BROTLI_STATE_HUFFMAN_CODE_0,
234b78
   BROTLI_STATE_HUFFMAN_CODE_1,
234b78
   BROTLI_STATE_HUFFMAN_CODE_2,
234b78
@@ -46,6 +136,7 @@ typedef enum {
234b78
   BROTLI_STATE_CONTEXT_MAP_1,
234b78
   BROTLI_STATE_CONTEXT_MAP_2,
234b78
   BROTLI_STATE_TREE_GROUP,
234b78
+  BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,
234b78
   BROTLI_STATE_DONE
234b78
 } BrotliRunningState;
234b78
 
234b78
@@ -98,6 +189,50 @@ typedef enum {
234b78
   BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
234b78
 } BrotliRunningReadBlockLengthState;
234b78
 
234b78
+typedef struct BrotliMetablockHeaderArena {
234b78
+  BrotliRunningTreeGroupState substate_tree_group;
234b78
+  BrotliRunningContextMapState substate_context_map;
234b78
+  BrotliRunningHuffmanState substate_huffman;
234b78
+
234b78
+  uint32_t sub_loop_counter;
234b78
+
234b78
+  uint32_t repeat_code_len;
234b78
+  uint32_t prev_code_len;
234b78
+
234b78
+  /* For ReadHuffmanCode. */
234b78
+  uint32_t symbol;
234b78
+  uint32_t repeat;
234b78
+  uint32_t space;
234b78
+
234b78
+  /* Huffman table for "histograms". */
234b78
+  HuffmanCode table[32];
234b78
+  /* List of heads of symbol chains. */
234b78
+  uint16_t* symbol_lists;
234b78
+  /* Storage from symbol_lists. */
234b78
+  uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
234b78
+                               BROTLI_NUM_COMMAND_SYMBOLS];
234b78
+  /* Tails of symbol chains. */
234b78
+  int next_symbol[32];
234b78
+  uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
234b78
+  /* Population counts for the code lengths. */
234b78
+  uint16_t code_length_histo[16];
234b78
+
234b78
+  /* For HuffmanTreeGroupDecode. */
234b78
+  int htree_index;
234b78
+  HuffmanCode* next;
234b78
+
234b78
+  /* For DecodeContextMap. */
234b78
+  uint32_t context_index;
234b78
+  uint32_t max_run_length_prefix;
234b78
+  uint32_t code;
234b78
+  HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
234b78
+} BrotliMetablockHeaderArena;
234b78
+
234b78
+typedef struct BrotliMetablockBodyArena {
234b78
+  uint8_t dist_extra_bits[544];
234b78
+  uint32_t dist_offset[544];
234b78
+} BrotliMetablockBodyArena;
234b78
+
234b78
 struct BrotliDecoderStateStruct {
234b78
   BrotliRunningState state;
234b78
 
234b78
@@ -110,7 +245,8 @@ struct BrotliDecoderStateStruct {
234b78
   brotli_free_func free_func;
234b78
   void* memory_manager_opaque;
234b78
 
234b78
-  /* Temporary storage for remaining input. */
234b78
+  /* Temporary storage for remaining input. Brotli stream format is designed in
234b78
+     a way, that 64 bits are enough to make progress in decoding. */
234b78
   union {
234b78
     uint64_t u64;
234b78
     uint8_t u8[8];
234b78
@@ -125,7 +261,6 @@ struct BrotliDecoderStateStruct {
234b78
   int dist_rb_idx;
234b78
   int dist_rb[4];
234b78
   int error_code;
234b78
-  uint32_t sub_loop_counter;
234b78
   uint8_t* ringbuffer;
234b78
   uint8_t* ringbuffer_end;
234b78
   HuffmanCode* htree_command;
234b78
@@ -153,13 +288,10 @@ struct BrotliDecoderStateStruct {
234b78
   uint32_t block_type_rb[6];
234b78
   uint32_t distance_postfix_bits;
234b78
   uint32_t num_direct_distance_codes;
234b78
-  int distance_postfix_mask;
234b78
   uint32_t num_dist_htrees;
234b78
   uint8_t* dist_context_map;
234b78
   HuffmanCode* literal_htree;
234b78
   uint8_t dist_htree_index;
234b78
-  uint32_t repeat_code_len;
234b78
-  uint32_t prev_code_len;
234b78
 
234b78
   int copy_length;
234b78
   int distance_code;
234b78
@@ -168,33 +300,6 @@ struct BrotliDecoderStateStruct {
234b78
   size_t rb_roundtrips;  /* how many times we went around the ring-buffer */
234b78
   size_t partial_pos_out;  /* how much output to the user in total */
234b78
 
234b78
-  /* For ReadHuffmanCode. */
234b78
-  uint32_t symbol;
234b78
-  uint32_t repeat;
234b78
-  uint32_t space;
234b78
-
234b78
-  HuffmanCode table[32];
234b78
-  /* List of heads of symbol chains. */
234b78
-  uint16_t* symbol_lists;
234b78
-  /* Storage from symbol_lists. */
234b78
-  uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
234b78
-                               BROTLI_NUM_COMMAND_SYMBOLS];
234b78
-  /* Tails of symbol chains. */
234b78
-  int next_symbol[32];
234b78
-  uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
234b78
-  /* Population counts for the code lengths. */
234b78
-  uint16_t code_length_histo[16];
234b78
-
234b78
-  /* For HuffmanTreeGroupDecode. */
234b78
-  int htree_index;
234b78
-  HuffmanCode* next;
234b78
-
234b78
-  /* For DecodeContextMap. */
234b78
-  uint32_t context_index;
234b78
-  uint32_t max_run_length_prefix;
234b78
-  uint32_t code;
234b78
-  HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
234b78
-
234b78
   /* For InverseMoveToFrontTransform. */
234b78
   uint32_t mtf_upper_bound;
234b78
   uint32_t mtf[64 + 1];
234b78
@@ -203,10 +308,7 @@ struct BrotliDecoderStateStruct {
234b78
 
234b78
   /* States inside function calls. */
234b78
   BrotliRunningMetablockHeaderState substate_metablock_header;
234b78
-  BrotliRunningTreeGroupState substate_tree_group;
234b78
-  BrotliRunningContextMapState substate_context_map;
234b78
   BrotliRunningUncompressedState substate_uncompressed;
234b78
-  BrotliRunningHuffmanState substate_huffman;
234b78
   BrotliRunningDecodeUint8State substate_decode_uint8;
234b78
   BrotliRunningReadBlockLengthState substate_read_block_length;
234b78
 
234b78
@@ -229,6 +331,11 @@ struct BrotliDecoderStateStruct {
234b78
   const BrotliTransforms* transforms;
234b78
 
234b78
   uint32_t trivial_literal_contexts[8];  /* 256 bits */
234b78
+
234b78
+  union {
234b78
+    BrotliMetablockHeaderArena header;
234b78
+    BrotliMetablockBodyArena body;
234b78
+  } arena;
234b78
 };
234b78
 
234b78
 typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;
234b78
@@ -241,8 +348,8 @@ BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);
234b78
 BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(
234b78
     BrotliDecoderState* s);
234b78
 BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
234b78
-    BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size,
234b78
-    uint32_t max_symbol, uint32_t ntrees);
234b78
+    BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size_max,
234b78
+    uint32_t alphabet_size_limit, uint32_t ntrees);
234b78
 
234b78
 #define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
234b78
 
234b78
diff --git a/c/enc/brotli_bit_stream.c b/c/enc/brotli_bit_stream.c
234b78
index aaf2dad..8e68059 100644
234b78
--- a/c/enc/brotli_bit_stream.c
234b78
+++ b/c/enc/brotli_bit_stream.c
234b78
@@ -34,33 +34,18 @@ extern "C" {
234b78
   BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS)
234b78
 /* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */
234b78
 
234b78
-/* Represents the range of values belonging to a prefix code:
234b78
-   [offset, offset + 2^nbits) */
234b78
-typedef struct PrefixCodeRange {
234b78
-  uint32_t offset;
234b78
-  uint32_t nbits;
234b78
-} PrefixCodeRange;
234b78
-
234b78
-static const PrefixCodeRange
234b78
-    kBlockLengthPrefixCode[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
234b78
-  { 1, 2}, { 5, 2}, { 9, 2}, {13, 2}, {17, 3}, { 25, 3}, { 33, 3},
234b78
-  {41, 3}, {49, 4}, {65, 4}, {81, 4}, {97, 4}, {113, 5}, {145, 5},
234b78
-  {177, 5}, { 209,  5}, { 241,  6}, { 305,  6}, { 369,  7}, {  497,  8},
234b78
-  {753, 9}, {1265, 10}, {2289, 11}, {4337, 12}, {8433, 13}, {16625, 24}
234b78
-};
234b78
-
234b78
 static BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) {
234b78
   uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0);
234b78
   while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) &&
234b78
-      len >= kBlockLengthPrefixCode[code + 1].offset) ++code;
234b78
+      len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code;
234b78
   return code;
234b78
 }
234b78
 
234b78
 static BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code,
234b78
     uint32_t* n_extra, uint32_t* extra) {
234b78
   *code = BlockLengthPrefixCode(len);
234b78
-  *n_extra = kBlockLengthPrefixCode[*code].nbits;
234b78
-  *extra = len - kBlockLengthPrefixCode[*code].offset;
234b78
+  *n_extra = _kBrotliPrefixCodeRanges[*code].nbits;
234b78
+  *extra = len - _kBrotliPrefixCodeRanges[*code].offset;
234b78
 }
234b78
 
234b78
 typedef struct BlockTypeCodeCalculator {
234b78
diff --git a/research/brotli_decoder.c b/research/brotli_decoder.c
234b78
index b1d556d..4b0bc4a 100644
234b78
--- a/research/brotli_decoder.c
234b78
+++ b/research/brotli_decoder.c
234b78
@@ -38,6 +38,7 @@ void cleanup(Context* ctx) {
234b78
 
234b78
 void fail(Context* ctx, const char* message) {
234b78
   fprintf(stderr, "%s\n", message);
234b78
+  cleanup(ctx);
234b78
   exit(1);
234b78
 }
234b78
 
234b78
diff --git a/scripts/sources.lst b/scripts/sources.lst
234b78
index 5e8e817..cd0b343 100644
234b78
--- a/scripts/sources.lst
234b78
+++ b/scripts/sources.lst
234b78
@@ -5,6 +5,7 @@ BROTLI_CLI_C = \
234b78
   c/tools/brotli.c
234b78
 
234b78
 BROTLI_COMMON_C = \
234b78
+  c/common/constants.c \
234b78
   c/common/dictionary.c \
234b78
   c/common/transform.c
234b78
 
234b78
diff --git a/setup.py b/setup.py
234b78
index 1491db3..7bd6314 100644
234b78
--- a/setup.py
234b78
+++ b/setup.py
234b78
@@ -181,6 +181,7 @@ EXT_MODULES = [
234b78
         '_brotli',
234b78
         sources=[
234b78
             'python/_brotli.cc',
234b78
+            'c/common/constants.c',
234b78
             'c/common/dictionary.c',
234b78
             'c/common/transform.c',
234b78
             'c/dec/bit_reader.c',
234b78
-- 
234b78
2.25.4
234b78