11cb0ef41Sopenharmony_ci/* Copyright 2014 Google Inc. All Rights Reserved.
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci   Distributed under MIT license.
41cb0ef41Sopenharmony_ci   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
51cb0ef41Sopenharmony_ci*/
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci/* Brotli bit stream functions to support the low level format. There are no
81cb0ef41Sopenharmony_ci   compression algorithms here, just the right ordering of bits to match the
91cb0ef41Sopenharmony_ci   specs. */
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include "./brotli_bit_stream.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci#include <string.h>  /* memcpy, memset */
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci#include "../common/constants.h"
161cb0ef41Sopenharmony_ci#include "../common/context.h"
171cb0ef41Sopenharmony_ci#include "../common/platform.h"
181cb0ef41Sopenharmony_ci#include <brotli/types.h>
191cb0ef41Sopenharmony_ci#include "./entropy_encode.h"
201cb0ef41Sopenharmony_ci#include "./entropy_encode_static.h"
211cb0ef41Sopenharmony_ci#include "./fast_log.h"
221cb0ef41Sopenharmony_ci#include "./histogram.h"
231cb0ef41Sopenharmony_ci#include "./memory.h"
241cb0ef41Sopenharmony_ci#include "./write_bits.h"
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci#if defined(__cplusplus) || defined(c_plusplus)
271cb0ef41Sopenharmony_ciextern "C" {
281cb0ef41Sopenharmony_ci#endif
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#define MAX_HUFFMAN_TREE_SIZE (2 * BROTLI_NUM_COMMAND_SYMBOLS + 1)
311cb0ef41Sopenharmony_ci/* The maximum size of Huffman dictionary for distances assuming that
321cb0ef41Sopenharmony_ci   NPOSTFIX = 0 and NDIRECT = 0. */
331cb0ef41Sopenharmony_ci#define MAX_SIMPLE_DISTANCE_ALPHABET_SIZE \
341cb0ef41Sopenharmony_ci  BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS)
351cb0ef41Sopenharmony_ci/* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cistatic BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) {
381cb0ef41Sopenharmony_ci  uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0);
391cb0ef41Sopenharmony_ci  while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) &&
401cb0ef41Sopenharmony_ci      len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code;
411cb0ef41Sopenharmony_ci  return code;
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cistatic BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code,
451cb0ef41Sopenharmony_ci    uint32_t* n_extra, uint32_t* extra) {
461cb0ef41Sopenharmony_ci  *code = BlockLengthPrefixCode(len);
471cb0ef41Sopenharmony_ci  *n_extra = _kBrotliPrefixCodeRanges[*code].nbits;
481cb0ef41Sopenharmony_ci  *extra = len - _kBrotliPrefixCodeRanges[*code].offset;
491cb0ef41Sopenharmony_ci}
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_citypedef struct BlockTypeCodeCalculator {
521cb0ef41Sopenharmony_ci  size_t last_type;
531cb0ef41Sopenharmony_ci  size_t second_last_type;
541cb0ef41Sopenharmony_ci} BlockTypeCodeCalculator;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_cistatic void InitBlockTypeCodeCalculator(BlockTypeCodeCalculator* self) {
571cb0ef41Sopenharmony_ci  self->last_type = 1;
581cb0ef41Sopenharmony_ci  self->second_last_type = 0;
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_cistatic BROTLI_INLINE size_t NextBlockTypeCode(
621cb0ef41Sopenharmony_ci    BlockTypeCodeCalculator* calculator, uint8_t type) {
631cb0ef41Sopenharmony_ci  size_t type_code = (type == calculator->last_type + 1) ? 1u :
641cb0ef41Sopenharmony_ci      (type == calculator->second_last_type) ? 0u : type + 2u;
651cb0ef41Sopenharmony_ci  calculator->second_last_type = calculator->last_type;
661cb0ef41Sopenharmony_ci  calculator->last_type = type;
671cb0ef41Sopenharmony_ci  return type_code;
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci/* |nibblesbits| represents the 2 bits to encode MNIBBLES (0-3)
711cb0ef41Sopenharmony_ci   REQUIRES: length > 0
721cb0ef41Sopenharmony_ci   REQUIRES: length <= (1 << 24) */
731cb0ef41Sopenharmony_cistatic void BrotliEncodeMlen(size_t length, uint64_t* bits,
741cb0ef41Sopenharmony_ci                             size_t* numbits, uint64_t* nibblesbits) {
751cb0ef41Sopenharmony_ci  size_t lg = (length == 1) ? 1 : Log2FloorNonZero((uint32_t)(length - 1)) + 1;
761cb0ef41Sopenharmony_ci  size_t mnibbles = (lg < 16 ? 16 : (lg + 3)) / 4;
771cb0ef41Sopenharmony_ci  BROTLI_DCHECK(length > 0);
781cb0ef41Sopenharmony_ci  BROTLI_DCHECK(length <= (1 << 24));
791cb0ef41Sopenharmony_ci  BROTLI_DCHECK(lg <= 24);
801cb0ef41Sopenharmony_ci  *nibblesbits = mnibbles - 4;
811cb0ef41Sopenharmony_ci  *numbits = mnibbles * 4;
821cb0ef41Sopenharmony_ci  *bits = length - 1;
831cb0ef41Sopenharmony_ci}
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_cistatic BROTLI_INLINE void StoreCommandExtra(
861cb0ef41Sopenharmony_ci    const Command* cmd, size_t* storage_ix, uint8_t* storage) {
871cb0ef41Sopenharmony_ci  uint32_t copylen_code = CommandCopyLenCode(cmd);
881cb0ef41Sopenharmony_ci  uint16_t inscode = GetInsertLengthCode(cmd->insert_len_);
891cb0ef41Sopenharmony_ci  uint16_t copycode = GetCopyLengthCode(copylen_code);
901cb0ef41Sopenharmony_ci  uint32_t insnumextra = GetInsertExtra(inscode);
911cb0ef41Sopenharmony_ci  uint64_t insextraval = cmd->insert_len_ - GetInsertBase(inscode);
921cb0ef41Sopenharmony_ci  uint64_t copyextraval = copylen_code - GetCopyBase(copycode);
931cb0ef41Sopenharmony_ci  uint64_t bits = (copyextraval << insnumextra) | insextraval;
941cb0ef41Sopenharmony_ci  BrotliWriteBits(
951cb0ef41Sopenharmony_ci      insnumextra + GetCopyExtra(copycode), bits, storage_ix, storage);
961cb0ef41Sopenharmony_ci}
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci/* Data structure that stores almost everything that is needed to encode each
991cb0ef41Sopenharmony_ci   block switch command. */
1001cb0ef41Sopenharmony_citypedef struct BlockSplitCode {
1011cb0ef41Sopenharmony_ci  BlockTypeCodeCalculator type_code_calculator;
1021cb0ef41Sopenharmony_ci  uint8_t type_depths[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];
1031cb0ef41Sopenharmony_ci  uint16_t type_bits[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];
1041cb0ef41Sopenharmony_ci  uint8_t length_depths[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
1051cb0ef41Sopenharmony_ci  uint16_t length_bits[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
1061cb0ef41Sopenharmony_ci} BlockSplitCode;
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci/* Stores a number between 0 and 255. */
1091cb0ef41Sopenharmony_cistatic void StoreVarLenUint8(size_t n, size_t* storage_ix, uint8_t* storage) {
1101cb0ef41Sopenharmony_ci  if (n == 0) {
1111cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 0, storage_ix, storage);
1121cb0ef41Sopenharmony_ci  } else {
1131cb0ef41Sopenharmony_ci    size_t nbits = Log2FloorNonZero(n);
1141cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 1, storage_ix, storage);
1151cb0ef41Sopenharmony_ci    BrotliWriteBits(3, nbits, storage_ix, storage);
1161cb0ef41Sopenharmony_ci    BrotliWriteBits(nbits, n - ((size_t)1 << nbits), storage_ix, storage);
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci/* Stores the compressed meta-block header.
1211cb0ef41Sopenharmony_ci   REQUIRES: length > 0
1221cb0ef41Sopenharmony_ci   REQUIRES: length <= (1 << 24) */
1231cb0ef41Sopenharmony_cistatic void StoreCompressedMetaBlockHeader(BROTLI_BOOL is_final_block,
1241cb0ef41Sopenharmony_ci                                           size_t length,
1251cb0ef41Sopenharmony_ci                                           size_t* storage_ix,
1261cb0ef41Sopenharmony_ci                                           uint8_t* storage) {
1271cb0ef41Sopenharmony_ci  uint64_t lenbits;
1281cb0ef41Sopenharmony_ci  size_t nlenbits;
1291cb0ef41Sopenharmony_ci  uint64_t nibblesbits;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  /* Write ISLAST bit. */
1321cb0ef41Sopenharmony_ci  BrotliWriteBits(1, (uint64_t)is_final_block, storage_ix, storage);
1331cb0ef41Sopenharmony_ci  /* Write ISEMPTY bit. */
1341cb0ef41Sopenharmony_ci  if (is_final_block) {
1351cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 0, storage_ix, storage);
1361cb0ef41Sopenharmony_ci  }
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits);
1391cb0ef41Sopenharmony_ci  BrotliWriteBits(2, nibblesbits, storage_ix, storage);
1401cb0ef41Sopenharmony_ci  BrotliWriteBits(nlenbits, lenbits, storage_ix, storage);
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  if (!is_final_block) {
1431cb0ef41Sopenharmony_ci    /* Write ISUNCOMPRESSED bit. */
1441cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 0, storage_ix, storage);
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci}
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci/* Stores the uncompressed meta-block header.
1491cb0ef41Sopenharmony_ci   REQUIRES: length > 0
1501cb0ef41Sopenharmony_ci   REQUIRES: length <= (1 << 24) */
1511cb0ef41Sopenharmony_cistatic void BrotliStoreUncompressedMetaBlockHeader(size_t length,
1521cb0ef41Sopenharmony_ci                                                   size_t* storage_ix,
1531cb0ef41Sopenharmony_ci                                                   uint8_t* storage) {
1541cb0ef41Sopenharmony_ci  uint64_t lenbits;
1551cb0ef41Sopenharmony_ci  size_t nlenbits;
1561cb0ef41Sopenharmony_ci  uint64_t nibblesbits;
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  /* Write ISLAST bit.
1591cb0ef41Sopenharmony_ci     Uncompressed block cannot be the last one, so set to 0. */
1601cb0ef41Sopenharmony_ci  BrotliWriteBits(1, 0, storage_ix, storage);
1611cb0ef41Sopenharmony_ci  BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits);
1621cb0ef41Sopenharmony_ci  BrotliWriteBits(2, nibblesbits, storage_ix, storage);
1631cb0ef41Sopenharmony_ci  BrotliWriteBits(nlenbits, lenbits, storage_ix, storage);
1641cb0ef41Sopenharmony_ci  /* Write ISUNCOMPRESSED bit. */
1651cb0ef41Sopenharmony_ci  BrotliWriteBits(1, 1, storage_ix, storage);
1661cb0ef41Sopenharmony_ci}
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_cistatic void BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(
1691cb0ef41Sopenharmony_ci    const int num_codes, const uint8_t* code_length_bitdepth,
1701cb0ef41Sopenharmony_ci    size_t* storage_ix, uint8_t* storage) {
1711cb0ef41Sopenharmony_ci  static const uint8_t kStorageOrder[BROTLI_CODE_LENGTH_CODES] = {
1721cb0ef41Sopenharmony_ci    1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15
1731cb0ef41Sopenharmony_ci  };
1741cb0ef41Sopenharmony_ci  /* The bit lengths of the Huffman code over the code length alphabet
1751cb0ef41Sopenharmony_ci     are compressed with the following static Huffman code:
1761cb0ef41Sopenharmony_ci       Symbol   Code
1771cb0ef41Sopenharmony_ci       ------   ----
1781cb0ef41Sopenharmony_ci       0          00
1791cb0ef41Sopenharmony_ci       1        1110
1801cb0ef41Sopenharmony_ci       2         110
1811cb0ef41Sopenharmony_ci       3          01
1821cb0ef41Sopenharmony_ci       4          10
1831cb0ef41Sopenharmony_ci       5        1111 */
1841cb0ef41Sopenharmony_ci  static const uint8_t kHuffmanBitLengthHuffmanCodeSymbols[6] = {
1851cb0ef41Sopenharmony_ci     0, 7, 3, 2, 1, 15
1861cb0ef41Sopenharmony_ci  };
1871cb0ef41Sopenharmony_ci  static const uint8_t kHuffmanBitLengthHuffmanCodeBitLengths[6] = {
1881cb0ef41Sopenharmony_ci    2, 4, 3, 2, 2, 4
1891cb0ef41Sopenharmony_ci  };
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  size_t skip_some = 0;  /* skips none. */
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  /* Throw away trailing zeros: */
1941cb0ef41Sopenharmony_ci  size_t codes_to_store = BROTLI_CODE_LENGTH_CODES;
1951cb0ef41Sopenharmony_ci  if (num_codes > 1) {
1961cb0ef41Sopenharmony_ci    for (; codes_to_store > 0; --codes_to_store) {
1971cb0ef41Sopenharmony_ci      if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
1981cb0ef41Sopenharmony_ci        break;
1991cb0ef41Sopenharmony_ci      }
2001cb0ef41Sopenharmony_ci    }
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci  if (code_length_bitdepth[kStorageOrder[0]] == 0 &&
2031cb0ef41Sopenharmony_ci      code_length_bitdepth[kStorageOrder[1]] == 0) {
2041cb0ef41Sopenharmony_ci    skip_some = 2;  /* skips two. */
2051cb0ef41Sopenharmony_ci    if (code_length_bitdepth[kStorageOrder[2]] == 0) {
2061cb0ef41Sopenharmony_ci      skip_some = 3;  /* skips three. */
2071cb0ef41Sopenharmony_ci    }
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci  BrotliWriteBits(2, skip_some, storage_ix, storage);
2101cb0ef41Sopenharmony_ci  {
2111cb0ef41Sopenharmony_ci    size_t i;
2121cb0ef41Sopenharmony_ci    for (i = skip_some; i < codes_to_store; ++i) {
2131cb0ef41Sopenharmony_ci      size_t l = code_length_bitdepth[kStorageOrder[i]];
2141cb0ef41Sopenharmony_ci      BrotliWriteBits(kHuffmanBitLengthHuffmanCodeBitLengths[l],
2151cb0ef41Sopenharmony_ci          kHuffmanBitLengthHuffmanCodeSymbols[l], storage_ix, storage);
2161cb0ef41Sopenharmony_ci    }
2171cb0ef41Sopenharmony_ci  }
2181cb0ef41Sopenharmony_ci}
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_cistatic void BrotliStoreHuffmanTreeToBitMask(
2211cb0ef41Sopenharmony_ci    const size_t huffman_tree_size, const uint8_t* huffman_tree,
2221cb0ef41Sopenharmony_ci    const uint8_t* huffman_tree_extra_bits, const uint8_t* code_length_bitdepth,
2231cb0ef41Sopenharmony_ci    const uint16_t* code_length_bitdepth_symbols,
2241cb0ef41Sopenharmony_ci    size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage) {
2251cb0ef41Sopenharmony_ci  size_t i;
2261cb0ef41Sopenharmony_ci  for (i = 0; i < huffman_tree_size; ++i) {
2271cb0ef41Sopenharmony_ci    size_t ix = huffman_tree[i];
2281cb0ef41Sopenharmony_ci    BrotliWriteBits(code_length_bitdepth[ix], code_length_bitdepth_symbols[ix],
2291cb0ef41Sopenharmony_ci                    storage_ix, storage);
2301cb0ef41Sopenharmony_ci    /* Extra bits */
2311cb0ef41Sopenharmony_ci    switch (ix) {
2321cb0ef41Sopenharmony_ci      case BROTLI_REPEAT_PREVIOUS_CODE_LENGTH:
2331cb0ef41Sopenharmony_ci        BrotliWriteBits(2, huffman_tree_extra_bits[i], storage_ix, storage);
2341cb0ef41Sopenharmony_ci        break;
2351cb0ef41Sopenharmony_ci      case BROTLI_REPEAT_ZERO_CODE_LENGTH:
2361cb0ef41Sopenharmony_ci        BrotliWriteBits(3, huffman_tree_extra_bits[i], storage_ix, storage);
2371cb0ef41Sopenharmony_ci        break;
2381cb0ef41Sopenharmony_ci    }
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci}
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_cistatic void StoreSimpleHuffmanTree(const uint8_t* depths,
2431cb0ef41Sopenharmony_ci                                   size_t symbols[4],
2441cb0ef41Sopenharmony_ci                                   size_t num_symbols,
2451cb0ef41Sopenharmony_ci                                   size_t max_bits,
2461cb0ef41Sopenharmony_ci                                   size_t* storage_ix, uint8_t* storage) {
2471cb0ef41Sopenharmony_ci  /* value of 1 indicates a simple Huffman code */
2481cb0ef41Sopenharmony_ci  BrotliWriteBits(2, 1, storage_ix, storage);
2491cb0ef41Sopenharmony_ci  BrotliWriteBits(2, num_symbols - 1, storage_ix, storage);  /* NSYM - 1 */
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci  {
2521cb0ef41Sopenharmony_ci    /* Sort */
2531cb0ef41Sopenharmony_ci    size_t i;
2541cb0ef41Sopenharmony_ci    for (i = 0; i < num_symbols; i++) {
2551cb0ef41Sopenharmony_ci      size_t j;
2561cb0ef41Sopenharmony_ci      for (j = i + 1; j < num_symbols; j++) {
2571cb0ef41Sopenharmony_ci        if (depths[symbols[j]] < depths[symbols[i]]) {
2581cb0ef41Sopenharmony_ci          BROTLI_SWAP(size_t, symbols, j, i);
2591cb0ef41Sopenharmony_ci        }
2601cb0ef41Sopenharmony_ci      }
2611cb0ef41Sopenharmony_ci    }
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci  if (num_symbols == 2) {
2651cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
2661cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);
2671cb0ef41Sopenharmony_ci  } else if (num_symbols == 3) {
2681cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
2691cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);
2701cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);
2711cb0ef41Sopenharmony_ci  } else {
2721cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
2731cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);
2741cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);
2751cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[3], storage_ix, storage);
2761cb0ef41Sopenharmony_ci    /* tree-select */
2771cb0ef41Sopenharmony_ci    BrotliWriteBits(1, depths[symbols[0]] == 1 ? 1 : 0, storage_ix, storage);
2781cb0ef41Sopenharmony_ci  }
2791cb0ef41Sopenharmony_ci}
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci/* num = alphabet size
2821cb0ef41Sopenharmony_ci   depths = symbol depths */
2831cb0ef41Sopenharmony_civoid BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,
2841cb0ef41Sopenharmony_ci                            HuffmanTree* tree,
2851cb0ef41Sopenharmony_ci                            size_t* storage_ix, uint8_t* storage) {
2861cb0ef41Sopenharmony_ci  /* Write the Huffman tree into the brotli-representation.
2871cb0ef41Sopenharmony_ci     The command alphabet is the largest, so this allocation will fit all
2881cb0ef41Sopenharmony_ci     alphabets. */
2891cb0ef41Sopenharmony_ci  uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS];
2901cb0ef41Sopenharmony_ci  uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS];
2911cb0ef41Sopenharmony_ci  size_t huffman_tree_size = 0;
2921cb0ef41Sopenharmony_ci  uint8_t code_length_bitdepth[BROTLI_CODE_LENGTH_CODES] = { 0 };
2931cb0ef41Sopenharmony_ci  uint16_t code_length_bitdepth_symbols[BROTLI_CODE_LENGTH_CODES];
2941cb0ef41Sopenharmony_ci  uint32_t huffman_tree_histogram[BROTLI_CODE_LENGTH_CODES] = { 0 };
2951cb0ef41Sopenharmony_ci  size_t i;
2961cb0ef41Sopenharmony_ci  int num_codes = 0;
2971cb0ef41Sopenharmony_ci  size_t code = 0;
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  BROTLI_DCHECK(num <= BROTLI_NUM_COMMAND_SYMBOLS);
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  BrotliWriteHuffmanTree(depths, num, &huffman_tree_size, huffman_tree,
3021cb0ef41Sopenharmony_ci                         huffman_tree_extra_bits);
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci  /* Calculate the statistics of the Huffman tree in brotli-representation. */
3051cb0ef41Sopenharmony_ci  for (i = 0; i < huffman_tree_size; ++i) {
3061cb0ef41Sopenharmony_ci    ++huffman_tree_histogram[huffman_tree[i]];
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  for (i = 0; i < BROTLI_CODE_LENGTH_CODES; ++i) {
3101cb0ef41Sopenharmony_ci    if (huffman_tree_histogram[i]) {
3111cb0ef41Sopenharmony_ci      if (num_codes == 0) {
3121cb0ef41Sopenharmony_ci        code = i;
3131cb0ef41Sopenharmony_ci        num_codes = 1;
3141cb0ef41Sopenharmony_ci      } else if (num_codes == 1) {
3151cb0ef41Sopenharmony_ci        num_codes = 2;
3161cb0ef41Sopenharmony_ci        break;
3171cb0ef41Sopenharmony_ci      }
3181cb0ef41Sopenharmony_ci    }
3191cb0ef41Sopenharmony_ci  }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  /* Calculate another Huffman tree to use for compressing both the
3221cb0ef41Sopenharmony_ci     earlier Huffman tree with. */
3231cb0ef41Sopenharmony_ci  BrotliCreateHuffmanTree(huffman_tree_histogram, BROTLI_CODE_LENGTH_CODES,
3241cb0ef41Sopenharmony_ci                          5, tree, code_length_bitdepth);
3251cb0ef41Sopenharmony_ci  BrotliConvertBitDepthsToSymbols(code_length_bitdepth,
3261cb0ef41Sopenharmony_ci                                  BROTLI_CODE_LENGTH_CODES,
3271cb0ef41Sopenharmony_ci                                  code_length_bitdepth_symbols);
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci  /* Now, we have all the data, let's start storing it */
3301cb0ef41Sopenharmony_ci  BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth,
3311cb0ef41Sopenharmony_ci                                               storage_ix, storage);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  if (num_codes == 1) {
3341cb0ef41Sopenharmony_ci    code_length_bitdepth[code] = 0;
3351cb0ef41Sopenharmony_ci  }
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  /* Store the real Huffman tree now. */
3381cb0ef41Sopenharmony_ci  BrotliStoreHuffmanTreeToBitMask(huffman_tree_size,
3391cb0ef41Sopenharmony_ci                                  huffman_tree,
3401cb0ef41Sopenharmony_ci                                  huffman_tree_extra_bits,
3411cb0ef41Sopenharmony_ci                                  code_length_bitdepth,
3421cb0ef41Sopenharmony_ci                                  code_length_bitdepth_symbols,
3431cb0ef41Sopenharmony_ci                                  storage_ix, storage);
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci/* Builds a Huffman tree from histogram[0:length] into depth[0:length] and
3471cb0ef41Sopenharmony_ci   bits[0:length] and stores the encoded tree to the bit stream. */
3481cb0ef41Sopenharmony_cistatic void BuildAndStoreHuffmanTree(const uint32_t* histogram,
3491cb0ef41Sopenharmony_ci                                     const size_t histogram_length,
3501cb0ef41Sopenharmony_ci                                     const size_t alphabet_size,
3511cb0ef41Sopenharmony_ci                                     HuffmanTree* tree,
3521cb0ef41Sopenharmony_ci                                     uint8_t* depth,
3531cb0ef41Sopenharmony_ci                                     uint16_t* bits,
3541cb0ef41Sopenharmony_ci                                     size_t* storage_ix,
3551cb0ef41Sopenharmony_ci                                     uint8_t* storage) {
3561cb0ef41Sopenharmony_ci  size_t count = 0;
3571cb0ef41Sopenharmony_ci  size_t s4[4] = { 0 };
3581cb0ef41Sopenharmony_ci  size_t i;
3591cb0ef41Sopenharmony_ci  size_t max_bits = 0;
3601cb0ef41Sopenharmony_ci  for (i = 0; i < histogram_length; i++) {
3611cb0ef41Sopenharmony_ci    if (histogram[i]) {
3621cb0ef41Sopenharmony_ci      if (count < 4) {
3631cb0ef41Sopenharmony_ci        s4[count] = i;
3641cb0ef41Sopenharmony_ci      } else if (count > 4) {
3651cb0ef41Sopenharmony_ci        break;
3661cb0ef41Sopenharmony_ci      }
3671cb0ef41Sopenharmony_ci      count++;
3681cb0ef41Sopenharmony_ci    }
3691cb0ef41Sopenharmony_ci  }
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci  {
3721cb0ef41Sopenharmony_ci    size_t max_bits_counter = alphabet_size - 1;
3731cb0ef41Sopenharmony_ci    while (max_bits_counter) {
3741cb0ef41Sopenharmony_ci      max_bits_counter >>= 1;
3751cb0ef41Sopenharmony_ci      ++max_bits;
3761cb0ef41Sopenharmony_ci    }
3771cb0ef41Sopenharmony_ci  }
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  if (count <= 1) {
3801cb0ef41Sopenharmony_ci    BrotliWriteBits(4, 1, storage_ix, storage);
3811cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, s4[0], storage_ix, storage);
3821cb0ef41Sopenharmony_ci    depth[s4[0]] = 0;
3831cb0ef41Sopenharmony_ci    bits[s4[0]] = 0;
3841cb0ef41Sopenharmony_ci    return;
3851cb0ef41Sopenharmony_ci  }
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  memset(depth, 0, histogram_length * sizeof(depth[0]));
3881cb0ef41Sopenharmony_ci  BrotliCreateHuffmanTree(histogram, histogram_length, 15, tree, depth);
3891cb0ef41Sopenharmony_ci  BrotliConvertBitDepthsToSymbols(depth, histogram_length, bits);
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  if (count <= 4) {
3921cb0ef41Sopenharmony_ci    StoreSimpleHuffmanTree(depth, s4, count, max_bits, storage_ix, storage);
3931cb0ef41Sopenharmony_ci  } else {
3941cb0ef41Sopenharmony_ci    BrotliStoreHuffmanTree(depth, histogram_length, tree, storage_ix, storage);
3951cb0ef41Sopenharmony_ci  }
3961cb0ef41Sopenharmony_ci}
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_cistatic BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(
3991cb0ef41Sopenharmony_ci    const HuffmanTree* v0, const HuffmanTree* v1) {
4001cb0ef41Sopenharmony_ci  return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);
4011cb0ef41Sopenharmony_ci}
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_civoid BrotliBuildAndStoreHuffmanTreeFast(MemoryManager* m,
4041cb0ef41Sopenharmony_ci                                        const uint32_t* histogram,
4051cb0ef41Sopenharmony_ci                                        const size_t histogram_total,
4061cb0ef41Sopenharmony_ci                                        const size_t max_bits,
4071cb0ef41Sopenharmony_ci                                        uint8_t* depth, uint16_t* bits,
4081cb0ef41Sopenharmony_ci                                        size_t* storage_ix,
4091cb0ef41Sopenharmony_ci                                        uint8_t* storage) {
4101cb0ef41Sopenharmony_ci  size_t count = 0;
4111cb0ef41Sopenharmony_ci  size_t symbols[4] = { 0 };
4121cb0ef41Sopenharmony_ci  size_t length = 0;
4131cb0ef41Sopenharmony_ci  size_t total = histogram_total;
4141cb0ef41Sopenharmony_ci  while (total != 0) {
4151cb0ef41Sopenharmony_ci    if (histogram[length]) {
4161cb0ef41Sopenharmony_ci      if (count < 4) {
4171cb0ef41Sopenharmony_ci        symbols[count] = length;
4181cb0ef41Sopenharmony_ci      }
4191cb0ef41Sopenharmony_ci      ++count;
4201cb0ef41Sopenharmony_ci      total -= histogram[length];
4211cb0ef41Sopenharmony_ci    }
4221cb0ef41Sopenharmony_ci    ++length;
4231cb0ef41Sopenharmony_ci  }
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ci  if (count <= 1) {
4261cb0ef41Sopenharmony_ci    BrotliWriteBits(4, 1, storage_ix, storage);
4271cb0ef41Sopenharmony_ci    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
4281cb0ef41Sopenharmony_ci    depth[symbols[0]] = 0;
4291cb0ef41Sopenharmony_ci    bits[symbols[0]] = 0;
4301cb0ef41Sopenharmony_ci    return;
4311cb0ef41Sopenharmony_ci  }
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci  memset(depth, 0, length * sizeof(depth[0]));
4341cb0ef41Sopenharmony_ci  {
4351cb0ef41Sopenharmony_ci    const size_t max_tree_size = 2 * length + 1;
4361cb0ef41Sopenharmony_ci    HuffmanTree* tree = BROTLI_ALLOC(m, HuffmanTree, max_tree_size);
4371cb0ef41Sopenharmony_ci    uint32_t count_limit;
4381cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree)) return;
4391cb0ef41Sopenharmony_ci    for (count_limit = 1; ; count_limit *= 2) {
4401cb0ef41Sopenharmony_ci      HuffmanTree* node = tree;
4411cb0ef41Sopenharmony_ci      size_t l;
4421cb0ef41Sopenharmony_ci      for (l = length; l != 0;) {
4431cb0ef41Sopenharmony_ci        --l;
4441cb0ef41Sopenharmony_ci        if (histogram[l]) {
4451cb0ef41Sopenharmony_ci          if (BROTLI_PREDICT_TRUE(histogram[l] >= count_limit)) {
4461cb0ef41Sopenharmony_ci            InitHuffmanTree(node, histogram[l], -1, (int16_t)l);
4471cb0ef41Sopenharmony_ci          } else {
4481cb0ef41Sopenharmony_ci            InitHuffmanTree(node, count_limit, -1, (int16_t)l);
4491cb0ef41Sopenharmony_ci          }
4501cb0ef41Sopenharmony_ci          ++node;
4511cb0ef41Sopenharmony_ci        }
4521cb0ef41Sopenharmony_ci      }
4531cb0ef41Sopenharmony_ci      {
4541cb0ef41Sopenharmony_ci        const int n = (int)(node - tree);
4551cb0ef41Sopenharmony_ci        HuffmanTree sentinel;
4561cb0ef41Sopenharmony_ci        int i = 0;      /* Points to the next leaf node. */
4571cb0ef41Sopenharmony_ci        int j = n + 1;  /* Points to the next non-leaf node. */
4581cb0ef41Sopenharmony_ci        int k;
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci        SortHuffmanTreeItems(tree, (size_t)n, SortHuffmanTree);
4611cb0ef41Sopenharmony_ci        /* The nodes are:
4621cb0ef41Sopenharmony_ci           [0, n): the sorted leaf nodes that we start with.
4631cb0ef41Sopenharmony_ci           [n]: we add a sentinel here.
4641cb0ef41Sopenharmony_ci           [n + 1, 2n): new parent nodes are added here, starting from
4651cb0ef41Sopenharmony_ci                        (n+1). These are naturally in ascending order.
4661cb0ef41Sopenharmony_ci           [2n]: we add a sentinel at the end as well.
4671cb0ef41Sopenharmony_ci           There will be (2n+1) elements at the end. */
4681cb0ef41Sopenharmony_ci        InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1);
4691cb0ef41Sopenharmony_ci        *node++ = sentinel;
4701cb0ef41Sopenharmony_ci        *node++ = sentinel;
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci        for (k = n - 1; k > 0; --k) {
4731cb0ef41Sopenharmony_ci          int left, right;
4741cb0ef41Sopenharmony_ci          if (tree[i].total_count_ <= tree[j].total_count_) {
4751cb0ef41Sopenharmony_ci            left = i;
4761cb0ef41Sopenharmony_ci            ++i;
4771cb0ef41Sopenharmony_ci          } else {
4781cb0ef41Sopenharmony_ci            left = j;
4791cb0ef41Sopenharmony_ci            ++j;
4801cb0ef41Sopenharmony_ci          }
4811cb0ef41Sopenharmony_ci          if (tree[i].total_count_ <= tree[j].total_count_) {
4821cb0ef41Sopenharmony_ci            right = i;
4831cb0ef41Sopenharmony_ci            ++i;
4841cb0ef41Sopenharmony_ci          } else {
4851cb0ef41Sopenharmony_ci            right = j;
4861cb0ef41Sopenharmony_ci            ++j;
4871cb0ef41Sopenharmony_ci          }
4881cb0ef41Sopenharmony_ci          /* The sentinel node becomes the parent node. */
4891cb0ef41Sopenharmony_ci          node[-1].total_count_ =
4901cb0ef41Sopenharmony_ci              tree[left].total_count_ + tree[right].total_count_;
4911cb0ef41Sopenharmony_ci          node[-1].index_left_ = (int16_t)left;
4921cb0ef41Sopenharmony_ci          node[-1].index_right_or_value_ = (int16_t)right;
4931cb0ef41Sopenharmony_ci          /* Add back the last sentinel node. */
4941cb0ef41Sopenharmony_ci          *node++ = sentinel;
4951cb0ef41Sopenharmony_ci        }
4961cb0ef41Sopenharmony_ci        if (BrotliSetDepth(2 * n - 1, tree, depth, 14)) {
4971cb0ef41Sopenharmony_ci          /* We need to pack the Huffman tree in 14 bits. If this was not
4981cb0ef41Sopenharmony_ci             successful, add fake entities to the lowest values and retry. */
4991cb0ef41Sopenharmony_ci          break;
5001cb0ef41Sopenharmony_ci        }
5011cb0ef41Sopenharmony_ci      }
5021cb0ef41Sopenharmony_ci    }
5031cb0ef41Sopenharmony_ci    BROTLI_FREE(m, tree);
5041cb0ef41Sopenharmony_ci  }
5051cb0ef41Sopenharmony_ci  BrotliConvertBitDepthsToSymbols(depth, length, bits);
5061cb0ef41Sopenharmony_ci  if (count <= 4) {
5071cb0ef41Sopenharmony_ci    size_t i;
5081cb0ef41Sopenharmony_ci    /* value of 1 indicates a simple Huffman code */
5091cb0ef41Sopenharmony_ci    BrotliWriteBits(2, 1, storage_ix, storage);
5101cb0ef41Sopenharmony_ci    BrotliWriteBits(2, count - 1, storage_ix, storage);  /* NSYM - 1 */
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ci    /* Sort */
5131cb0ef41Sopenharmony_ci    for (i = 0; i < count; i++) {
5141cb0ef41Sopenharmony_ci      size_t j;
5151cb0ef41Sopenharmony_ci      for (j = i + 1; j < count; j++) {
5161cb0ef41Sopenharmony_ci        if (depth[symbols[j]] < depth[symbols[i]]) {
5171cb0ef41Sopenharmony_ci          BROTLI_SWAP(size_t, symbols, j, i);
5181cb0ef41Sopenharmony_ci        }
5191cb0ef41Sopenharmony_ci      }
5201cb0ef41Sopenharmony_ci    }
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ci    if (count == 2) {
5231cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
5241cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);
5251cb0ef41Sopenharmony_ci    } else if (count == 3) {
5261cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
5271cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);
5281cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);
5291cb0ef41Sopenharmony_ci    } else {
5301cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);
5311cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);
5321cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);
5331cb0ef41Sopenharmony_ci      BrotliWriteBits(max_bits, symbols[3], storage_ix, storage);
5341cb0ef41Sopenharmony_ci      /* tree-select */
5351cb0ef41Sopenharmony_ci      BrotliWriteBits(1, depth[symbols[0]] == 1 ? 1 : 0, storage_ix, storage);
5361cb0ef41Sopenharmony_ci    }
5371cb0ef41Sopenharmony_ci  } else {
5381cb0ef41Sopenharmony_ci    uint8_t previous_value = 8;
5391cb0ef41Sopenharmony_ci    size_t i;
5401cb0ef41Sopenharmony_ci    /* Complex Huffman Tree */
5411cb0ef41Sopenharmony_ci    StoreStaticCodeLengthCode(storage_ix, storage);
5421cb0ef41Sopenharmony_ci
5431cb0ef41Sopenharmony_ci    /* Actual RLE coding. */
5441cb0ef41Sopenharmony_ci    for (i = 0; i < length;) {
5451cb0ef41Sopenharmony_ci      const uint8_t value = depth[i];
5461cb0ef41Sopenharmony_ci      size_t reps = 1;
5471cb0ef41Sopenharmony_ci      size_t k;
5481cb0ef41Sopenharmony_ci      for (k = i + 1; k < length && depth[k] == value; ++k) {
5491cb0ef41Sopenharmony_ci        ++reps;
5501cb0ef41Sopenharmony_ci      }
5511cb0ef41Sopenharmony_ci      i += reps;
5521cb0ef41Sopenharmony_ci      if (value == 0) {
5531cb0ef41Sopenharmony_ci        BrotliWriteBits(kZeroRepsDepth[reps], kZeroRepsBits[reps],
5541cb0ef41Sopenharmony_ci                        storage_ix, storage);
5551cb0ef41Sopenharmony_ci      } else {
5561cb0ef41Sopenharmony_ci        if (previous_value != value) {
5571cb0ef41Sopenharmony_ci          BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value],
5581cb0ef41Sopenharmony_ci                          storage_ix, storage);
5591cb0ef41Sopenharmony_ci          --reps;
5601cb0ef41Sopenharmony_ci        }
5611cb0ef41Sopenharmony_ci        if (reps < 3) {
5621cb0ef41Sopenharmony_ci          while (reps != 0) {
5631cb0ef41Sopenharmony_ci            reps--;
5641cb0ef41Sopenharmony_ci            BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value],
5651cb0ef41Sopenharmony_ci                            storage_ix, storage);
5661cb0ef41Sopenharmony_ci          }
5671cb0ef41Sopenharmony_ci        } else {
5681cb0ef41Sopenharmony_ci          reps -= 3;
5691cb0ef41Sopenharmony_ci          BrotliWriteBits(kNonZeroRepsDepth[reps], kNonZeroRepsBits[reps],
5701cb0ef41Sopenharmony_ci                          storage_ix, storage);
5711cb0ef41Sopenharmony_ci        }
5721cb0ef41Sopenharmony_ci        previous_value = value;
5731cb0ef41Sopenharmony_ci      }
5741cb0ef41Sopenharmony_ci    }
5751cb0ef41Sopenharmony_ci  }
5761cb0ef41Sopenharmony_ci}
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_cistatic size_t IndexOf(const uint8_t* v, size_t v_size, uint8_t value) {
5791cb0ef41Sopenharmony_ci  size_t i = 0;
5801cb0ef41Sopenharmony_ci  for (; i < v_size; ++i) {
5811cb0ef41Sopenharmony_ci    if (v[i] == value) return i;
5821cb0ef41Sopenharmony_ci  }
5831cb0ef41Sopenharmony_ci  return i;
5841cb0ef41Sopenharmony_ci}
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_cistatic void MoveToFront(uint8_t* v, size_t index) {
5871cb0ef41Sopenharmony_ci  uint8_t value = v[index];
5881cb0ef41Sopenharmony_ci  size_t i;
5891cb0ef41Sopenharmony_ci  for (i = index; i != 0; --i) {
5901cb0ef41Sopenharmony_ci    v[i] = v[i - 1];
5911cb0ef41Sopenharmony_ci  }
5921cb0ef41Sopenharmony_ci  v[0] = value;
5931cb0ef41Sopenharmony_ci}
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_cistatic void MoveToFrontTransform(const uint32_t* BROTLI_RESTRICT v_in,
5961cb0ef41Sopenharmony_ci                                 const size_t v_size,
5971cb0ef41Sopenharmony_ci                                 uint32_t* v_out) {
5981cb0ef41Sopenharmony_ci  size_t i;
5991cb0ef41Sopenharmony_ci  uint8_t mtf[256];
6001cb0ef41Sopenharmony_ci  uint32_t max_value;
6011cb0ef41Sopenharmony_ci  if (v_size == 0) {
6021cb0ef41Sopenharmony_ci    return;
6031cb0ef41Sopenharmony_ci  }
6041cb0ef41Sopenharmony_ci  max_value = v_in[0];
6051cb0ef41Sopenharmony_ci  for (i = 1; i < v_size; ++i) {
6061cb0ef41Sopenharmony_ci    if (v_in[i] > max_value) max_value = v_in[i];
6071cb0ef41Sopenharmony_ci  }
6081cb0ef41Sopenharmony_ci  BROTLI_DCHECK(max_value < 256u);
6091cb0ef41Sopenharmony_ci  for (i = 0; i <= max_value; ++i) {
6101cb0ef41Sopenharmony_ci    mtf[i] = (uint8_t)i;
6111cb0ef41Sopenharmony_ci  }
6121cb0ef41Sopenharmony_ci  {
6131cb0ef41Sopenharmony_ci    size_t mtf_size = max_value + 1;
6141cb0ef41Sopenharmony_ci    for (i = 0; i < v_size; ++i) {
6151cb0ef41Sopenharmony_ci      size_t index = IndexOf(mtf, mtf_size, (uint8_t)v_in[i]);
6161cb0ef41Sopenharmony_ci      BROTLI_DCHECK(index < mtf_size);
6171cb0ef41Sopenharmony_ci      v_out[i] = (uint32_t)index;
6181cb0ef41Sopenharmony_ci      MoveToFront(mtf, index);
6191cb0ef41Sopenharmony_ci    }
6201cb0ef41Sopenharmony_ci  }
6211cb0ef41Sopenharmony_ci}
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci/* Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of
6241cb0ef41Sopenharmony_ci   the run length plus extra bits (lower 9 bits is the prefix code and the rest
6251cb0ef41Sopenharmony_ci   are the extra bits). Non-zero values in v[] are shifted by
6261cb0ef41Sopenharmony_ci   *max_length_prefix. Will not create prefix codes bigger than the initial
6271cb0ef41Sopenharmony_ci   value of *max_run_length_prefix. The prefix code of run length L is simply
6281cb0ef41Sopenharmony_ci   Log2Floor(L) and the number of extra bits is the same as the prefix code. */
6291cb0ef41Sopenharmony_cistatic void RunLengthCodeZeros(const size_t in_size,
6301cb0ef41Sopenharmony_ci    uint32_t* BROTLI_RESTRICT v, size_t* BROTLI_RESTRICT out_size,
6311cb0ef41Sopenharmony_ci    uint32_t* BROTLI_RESTRICT max_run_length_prefix) {
6321cb0ef41Sopenharmony_ci  uint32_t max_reps = 0;
6331cb0ef41Sopenharmony_ci  size_t i;
6341cb0ef41Sopenharmony_ci  uint32_t max_prefix;
6351cb0ef41Sopenharmony_ci  for (i = 0; i < in_size;) {
6361cb0ef41Sopenharmony_ci    uint32_t reps = 0;
6371cb0ef41Sopenharmony_ci    for (; i < in_size && v[i] != 0; ++i) ;
6381cb0ef41Sopenharmony_ci    for (; i < in_size && v[i] == 0; ++i) {
6391cb0ef41Sopenharmony_ci      ++reps;
6401cb0ef41Sopenharmony_ci    }
6411cb0ef41Sopenharmony_ci    max_reps = BROTLI_MAX(uint32_t, reps, max_reps);
6421cb0ef41Sopenharmony_ci  }
6431cb0ef41Sopenharmony_ci  max_prefix = max_reps > 0 ? Log2FloorNonZero(max_reps) : 0;
6441cb0ef41Sopenharmony_ci  max_prefix = BROTLI_MIN(uint32_t, max_prefix, *max_run_length_prefix);
6451cb0ef41Sopenharmony_ci  *max_run_length_prefix = max_prefix;
6461cb0ef41Sopenharmony_ci  *out_size = 0;
6471cb0ef41Sopenharmony_ci  for (i = 0; i < in_size;) {
6481cb0ef41Sopenharmony_ci    BROTLI_DCHECK(*out_size <= i);
6491cb0ef41Sopenharmony_ci    if (v[i] != 0) {
6501cb0ef41Sopenharmony_ci      v[*out_size] = v[i] + *max_run_length_prefix;
6511cb0ef41Sopenharmony_ci      ++i;
6521cb0ef41Sopenharmony_ci      ++(*out_size);
6531cb0ef41Sopenharmony_ci    } else {
6541cb0ef41Sopenharmony_ci      uint32_t reps = 1;
6551cb0ef41Sopenharmony_ci      size_t k;
6561cb0ef41Sopenharmony_ci      for (k = i + 1; k < in_size && v[k] == 0; ++k) {
6571cb0ef41Sopenharmony_ci        ++reps;
6581cb0ef41Sopenharmony_ci      }
6591cb0ef41Sopenharmony_ci      i += reps;
6601cb0ef41Sopenharmony_ci      while (reps != 0) {
6611cb0ef41Sopenharmony_ci        if (reps < (2u << max_prefix)) {
6621cb0ef41Sopenharmony_ci          uint32_t run_length_prefix = Log2FloorNonZero(reps);
6631cb0ef41Sopenharmony_ci          const uint32_t extra_bits = reps - (1u << run_length_prefix);
6641cb0ef41Sopenharmony_ci          v[*out_size] = run_length_prefix + (extra_bits << 9);
6651cb0ef41Sopenharmony_ci          ++(*out_size);
6661cb0ef41Sopenharmony_ci          break;
6671cb0ef41Sopenharmony_ci        } else {
6681cb0ef41Sopenharmony_ci          const uint32_t extra_bits = (1u << max_prefix) - 1u;
6691cb0ef41Sopenharmony_ci          v[*out_size] = max_prefix + (extra_bits << 9);
6701cb0ef41Sopenharmony_ci          reps -= (2u << max_prefix) - 1u;
6711cb0ef41Sopenharmony_ci          ++(*out_size);
6721cb0ef41Sopenharmony_ci        }
6731cb0ef41Sopenharmony_ci      }
6741cb0ef41Sopenharmony_ci    }
6751cb0ef41Sopenharmony_ci  }
6761cb0ef41Sopenharmony_ci}
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci#define SYMBOL_BITS 9
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_cistatic void EncodeContextMap(MemoryManager* m,
6811cb0ef41Sopenharmony_ci                             const uint32_t* context_map,
6821cb0ef41Sopenharmony_ci                             size_t context_map_size,
6831cb0ef41Sopenharmony_ci                             size_t num_clusters,
6841cb0ef41Sopenharmony_ci                             HuffmanTree* tree,
6851cb0ef41Sopenharmony_ci                             size_t* storage_ix, uint8_t* storage) {
6861cb0ef41Sopenharmony_ci  size_t i;
6871cb0ef41Sopenharmony_ci  uint32_t* rle_symbols;
6881cb0ef41Sopenharmony_ci  uint32_t max_run_length_prefix = 6;
6891cb0ef41Sopenharmony_ci  size_t num_rle_symbols = 0;
6901cb0ef41Sopenharmony_ci  uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
6911cb0ef41Sopenharmony_ci  static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u;
6921cb0ef41Sopenharmony_ci  uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
6931cb0ef41Sopenharmony_ci  uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci  StoreVarLenUint8(num_clusters - 1, storage_ix, storage);
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_ci  if (num_clusters == 1) {
6981cb0ef41Sopenharmony_ci    return;
6991cb0ef41Sopenharmony_ci  }
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci  rle_symbols = BROTLI_ALLOC(m, uint32_t, context_map_size);
7021cb0ef41Sopenharmony_ci  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(rle_symbols)) return;
7031cb0ef41Sopenharmony_ci  MoveToFrontTransform(context_map, context_map_size, rle_symbols);
7041cb0ef41Sopenharmony_ci  RunLengthCodeZeros(context_map_size, rle_symbols,
7051cb0ef41Sopenharmony_ci                     &num_rle_symbols, &max_run_length_prefix);
7061cb0ef41Sopenharmony_ci  memset(histogram, 0, sizeof(histogram));
7071cb0ef41Sopenharmony_ci  for (i = 0; i < num_rle_symbols; ++i) {
7081cb0ef41Sopenharmony_ci    ++histogram[rle_symbols[i] & kSymbolMask];
7091cb0ef41Sopenharmony_ci  }
7101cb0ef41Sopenharmony_ci  {
7111cb0ef41Sopenharmony_ci    BROTLI_BOOL use_rle = TO_BROTLI_BOOL(max_run_length_prefix > 0);
7121cb0ef41Sopenharmony_ci    BrotliWriteBits(1, (uint64_t)use_rle, storage_ix, storage);
7131cb0ef41Sopenharmony_ci    if (use_rle) {
7141cb0ef41Sopenharmony_ci      BrotliWriteBits(4, max_run_length_prefix - 1, storage_ix, storage);
7151cb0ef41Sopenharmony_ci    }
7161cb0ef41Sopenharmony_ci  }
7171cb0ef41Sopenharmony_ci  BuildAndStoreHuffmanTree(histogram, num_clusters + max_run_length_prefix,
7181cb0ef41Sopenharmony_ci                           num_clusters + max_run_length_prefix,
7191cb0ef41Sopenharmony_ci                           tree, depths, bits, storage_ix, storage);
7201cb0ef41Sopenharmony_ci  for (i = 0; i < num_rle_symbols; ++i) {
7211cb0ef41Sopenharmony_ci    const uint32_t rle_symbol = rle_symbols[i] & kSymbolMask;
7221cb0ef41Sopenharmony_ci    const uint32_t extra_bits_val = rle_symbols[i] >> SYMBOL_BITS;
7231cb0ef41Sopenharmony_ci    BrotliWriteBits(depths[rle_symbol], bits[rle_symbol], storage_ix, storage);
7241cb0ef41Sopenharmony_ci    if (rle_symbol > 0 && rle_symbol <= max_run_length_prefix) {
7251cb0ef41Sopenharmony_ci      BrotliWriteBits(rle_symbol, extra_bits_val, storage_ix, storage);
7261cb0ef41Sopenharmony_ci    }
7271cb0ef41Sopenharmony_ci  }
7281cb0ef41Sopenharmony_ci  BrotliWriteBits(1, 1, storage_ix, storage);  /* use move-to-front */
7291cb0ef41Sopenharmony_ci  BROTLI_FREE(m, rle_symbols);
7301cb0ef41Sopenharmony_ci}
7311cb0ef41Sopenharmony_ci
7321cb0ef41Sopenharmony_ci/* Stores the block switch command with index block_ix to the bit stream. */
7331cb0ef41Sopenharmony_cistatic BROTLI_INLINE void StoreBlockSwitch(BlockSplitCode* code,
7341cb0ef41Sopenharmony_ci                                           const uint32_t block_len,
7351cb0ef41Sopenharmony_ci                                           const uint8_t block_type,
7361cb0ef41Sopenharmony_ci                                           BROTLI_BOOL is_first_block,
7371cb0ef41Sopenharmony_ci                                           size_t* storage_ix,
7381cb0ef41Sopenharmony_ci                                           uint8_t* storage) {
7391cb0ef41Sopenharmony_ci  size_t typecode = NextBlockTypeCode(&code->type_code_calculator, block_type);
7401cb0ef41Sopenharmony_ci  size_t lencode;
7411cb0ef41Sopenharmony_ci  uint32_t len_nextra;
7421cb0ef41Sopenharmony_ci  uint32_t len_extra;
7431cb0ef41Sopenharmony_ci  if (!is_first_block) {
7441cb0ef41Sopenharmony_ci    BrotliWriteBits(code->type_depths[typecode], code->type_bits[typecode],
7451cb0ef41Sopenharmony_ci                    storage_ix, storage);
7461cb0ef41Sopenharmony_ci  }
7471cb0ef41Sopenharmony_ci  GetBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra);
7481cb0ef41Sopenharmony_ci
7491cb0ef41Sopenharmony_ci  BrotliWriteBits(code->length_depths[lencode], code->length_bits[lencode],
7501cb0ef41Sopenharmony_ci                  storage_ix, storage);
7511cb0ef41Sopenharmony_ci  BrotliWriteBits(len_nextra, len_extra, storage_ix, storage);
7521cb0ef41Sopenharmony_ci}
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci/* Builds a BlockSplitCode data structure from the block split given by the
7551cb0ef41Sopenharmony_ci   vector of block types and block lengths and stores it to the bit stream. */
7561cb0ef41Sopenharmony_cistatic void BuildAndStoreBlockSplitCode(const uint8_t* types,
7571cb0ef41Sopenharmony_ci                                        const uint32_t* lengths,
7581cb0ef41Sopenharmony_ci                                        const size_t num_blocks,
7591cb0ef41Sopenharmony_ci                                        const size_t num_types,
7601cb0ef41Sopenharmony_ci                                        HuffmanTree* tree,
7611cb0ef41Sopenharmony_ci                                        BlockSplitCode* code,
7621cb0ef41Sopenharmony_ci                                        size_t* storage_ix,
7631cb0ef41Sopenharmony_ci                                        uint8_t* storage) {
7641cb0ef41Sopenharmony_ci  uint32_t type_histo[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];
7651cb0ef41Sopenharmony_ci  uint32_t length_histo[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
7661cb0ef41Sopenharmony_ci  size_t i;
7671cb0ef41Sopenharmony_ci  BlockTypeCodeCalculator type_code_calculator;
7681cb0ef41Sopenharmony_ci  memset(type_histo, 0, (num_types + 2) * sizeof(type_histo[0]));
7691cb0ef41Sopenharmony_ci  memset(length_histo, 0, sizeof(length_histo));
7701cb0ef41Sopenharmony_ci  InitBlockTypeCodeCalculator(&type_code_calculator);
7711cb0ef41Sopenharmony_ci  for (i = 0; i < num_blocks; ++i) {
7721cb0ef41Sopenharmony_ci    size_t type_code = NextBlockTypeCode(&type_code_calculator, types[i]);
7731cb0ef41Sopenharmony_ci    if (i != 0) ++type_histo[type_code];
7741cb0ef41Sopenharmony_ci    ++length_histo[BlockLengthPrefixCode(lengths[i])];
7751cb0ef41Sopenharmony_ci  }
7761cb0ef41Sopenharmony_ci  StoreVarLenUint8(num_types - 1, storage_ix, storage);
7771cb0ef41Sopenharmony_ci  if (num_types > 1) {  /* TODO: else? could StoreBlockSwitch occur? */
7781cb0ef41Sopenharmony_ci    BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree,
7791cb0ef41Sopenharmony_ci                             &code->type_depths[0], &code->type_bits[0],
7801cb0ef41Sopenharmony_ci                             storage_ix, storage);
7811cb0ef41Sopenharmony_ci    BuildAndStoreHuffmanTree(&length_histo[0], BROTLI_NUM_BLOCK_LEN_SYMBOLS,
7821cb0ef41Sopenharmony_ci                             BROTLI_NUM_BLOCK_LEN_SYMBOLS,
7831cb0ef41Sopenharmony_ci                             tree, &code->length_depths[0],
7841cb0ef41Sopenharmony_ci                             &code->length_bits[0], storage_ix, storage);
7851cb0ef41Sopenharmony_ci    StoreBlockSwitch(code, lengths[0], types[0], 1, storage_ix, storage);
7861cb0ef41Sopenharmony_ci  }
7871cb0ef41Sopenharmony_ci}
7881cb0ef41Sopenharmony_ci
7891cb0ef41Sopenharmony_ci/* Stores a context map where the histogram type is always the block type. */
7901cb0ef41Sopenharmony_cistatic void StoreTrivialContextMap(size_t num_types,
7911cb0ef41Sopenharmony_ci                                   size_t context_bits,
7921cb0ef41Sopenharmony_ci                                   HuffmanTree* tree,
7931cb0ef41Sopenharmony_ci                                   size_t* storage_ix,
7941cb0ef41Sopenharmony_ci                                   uint8_t* storage) {
7951cb0ef41Sopenharmony_ci  StoreVarLenUint8(num_types - 1, storage_ix, storage);
7961cb0ef41Sopenharmony_ci  if (num_types > 1) {
7971cb0ef41Sopenharmony_ci    size_t repeat_code = context_bits - 1u;
7981cb0ef41Sopenharmony_ci    size_t repeat_bits = (1u << repeat_code) - 1u;
7991cb0ef41Sopenharmony_ci    size_t alphabet_size = num_types + repeat_code;
8001cb0ef41Sopenharmony_ci    uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
8011cb0ef41Sopenharmony_ci    uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
8021cb0ef41Sopenharmony_ci    uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
8031cb0ef41Sopenharmony_ci    size_t i;
8041cb0ef41Sopenharmony_ci    memset(histogram, 0, alphabet_size * sizeof(histogram[0]));
8051cb0ef41Sopenharmony_ci    /* Write RLEMAX. */
8061cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 1, storage_ix, storage);
8071cb0ef41Sopenharmony_ci    BrotliWriteBits(4, repeat_code - 1, storage_ix, storage);
8081cb0ef41Sopenharmony_ci    histogram[repeat_code] = (uint32_t)num_types;
8091cb0ef41Sopenharmony_ci    histogram[0] = 1;
8101cb0ef41Sopenharmony_ci    for (i = context_bits; i < alphabet_size; ++i) {
8111cb0ef41Sopenharmony_ci      histogram[i] = 1;
8121cb0ef41Sopenharmony_ci    }
8131cb0ef41Sopenharmony_ci    BuildAndStoreHuffmanTree(histogram, alphabet_size, alphabet_size,
8141cb0ef41Sopenharmony_ci                             tree, depths, bits, storage_ix, storage);
8151cb0ef41Sopenharmony_ci    for (i = 0; i < num_types; ++i) {
8161cb0ef41Sopenharmony_ci      size_t code = (i == 0 ? 0 : i + context_bits - 1);
8171cb0ef41Sopenharmony_ci      BrotliWriteBits(depths[code], bits[code], storage_ix, storage);
8181cb0ef41Sopenharmony_ci      BrotliWriteBits(
8191cb0ef41Sopenharmony_ci          depths[repeat_code], bits[repeat_code], storage_ix, storage);
8201cb0ef41Sopenharmony_ci      BrotliWriteBits(repeat_code, repeat_bits, storage_ix, storage);
8211cb0ef41Sopenharmony_ci    }
8221cb0ef41Sopenharmony_ci    /* Write IMTF (inverse-move-to-front) bit. */
8231cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 1, storage_ix, storage);
8241cb0ef41Sopenharmony_ci  }
8251cb0ef41Sopenharmony_ci}
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_ci/* Manages the encoding of one block category (literal, command or distance). */
8281cb0ef41Sopenharmony_citypedef struct BlockEncoder {
8291cb0ef41Sopenharmony_ci  size_t histogram_length_;
8301cb0ef41Sopenharmony_ci  size_t num_block_types_;
8311cb0ef41Sopenharmony_ci  const uint8_t* block_types_;  /* Not owned. */
8321cb0ef41Sopenharmony_ci  const uint32_t* block_lengths_;  /* Not owned. */
8331cb0ef41Sopenharmony_ci  size_t num_blocks_;
8341cb0ef41Sopenharmony_ci  BlockSplitCode block_split_code_;
8351cb0ef41Sopenharmony_ci  size_t block_ix_;
8361cb0ef41Sopenharmony_ci  size_t block_len_;
8371cb0ef41Sopenharmony_ci  size_t entropy_ix_;
8381cb0ef41Sopenharmony_ci  uint8_t* depths_;
8391cb0ef41Sopenharmony_ci  uint16_t* bits_;
8401cb0ef41Sopenharmony_ci} BlockEncoder;
8411cb0ef41Sopenharmony_ci
8421cb0ef41Sopenharmony_cistatic void InitBlockEncoder(BlockEncoder* self, size_t histogram_length,
8431cb0ef41Sopenharmony_ci    size_t num_block_types, const uint8_t* block_types,
8441cb0ef41Sopenharmony_ci    const uint32_t* block_lengths, const size_t num_blocks) {
8451cb0ef41Sopenharmony_ci  self->histogram_length_ = histogram_length;
8461cb0ef41Sopenharmony_ci  self->num_block_types_ = num_block_types;
8471cb0ef41Sopenharmony_ci  self->block_types_ = block_types;
8481cb0ef41Sopenharmony_ci  self->block_lengths_ = block_lengths;
8491cb0ef41Sopenharmony_ci  self->num_blocks_ = num_blocks;
8501cb0ef41Sopenharmony_ci  InitBlockTypeCodeCalculator(&self->block_split_code_.type_code_calculator);
8511cb0ef41Sopenharmony_ci  self->block_ix_ = 0;
8521cb0ef41Sopenharmony_ci  self->block_len_ = num_blocks == 0 ? 0 : block_lengths[0];
8531cb0ef41Sopenharmony_ci  self->entropy_ix_ = 0;
8541cb0ef41Sopenharmony_ci  self->depths_ = 0;
8551cb0ef41Sopenharmony_ci  self->bits_ = 0;
8561cb0ef41Sopenharmony_ci}
8571cb0ef41Sopenharmony_ci
8581cb0ef41Sopenharmony_cistatic void CleanupBlockEncoder(MemoryManager* m, BlockEncoder* self) {
8591cb0ef41Sopenharmony_ci  BROTLI_FREE(m, self->depths_);
8601cb0ef41Sopenharmony_ci  BROTLI_FREE(m, self->bits_);
8611cb0ef41Sopenharmony_ci}
8621cb0ef41Sopenharmony_ci
8631cb0ef41Sopenharmony_ci/* Creates entropy codes of block lengths and block types and stores them
8641cb0ef41Sopenharmony_ci   to the bit stream. */
8651cb0ef41Sopenharmony_cistatic void BuildAndStoreBlockSwitchEntropyCodes(BlockEncoder* self,
8661cb0ef41Sopenharmony_ci    HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) {
8671cb0ef41Sopenharmony_ci  BuildAndStoreBlockSplitCode(self->block_types_, self->block_lengths_,
8681cb0ef41Sopenharmony_ci      self->num_blocks_, self->num_block_types_, tree, &self->block_split_code_,
8691cb0ef41Sopenharmony_ci      storage_ix, storage);
8701cb0ef41Sopenharmony_ci}
8711cb0ef41Sopenharmony_ci
8721cb0ef41Sopenharmony_ci/* Stores the next symbol with the entropy code of the current block type.
8731cb0ef41Sopenharmony_ci   Updates the block type and block length at block boundaries. */
8741cb0ef41Sopenharmony_cistatic void StoreSymbol(BlockEncoder* self, size_t symbol, size_t* storage_ix,
8751cb0ef41Sopenharmony_ci    uint8_t* storage) {
8761cb0ef41Sopenharmony_ci  if (self->block_len_ == 0) {
8771cb0ef41Sopenharmony_ci    size_t block_ix = ++self->block_ix_;
8781cb0ef41Sopenharmony_ci    uint32_t block_len = self->block_lengths_[block_ix];
8791cb0ef41Sopenharmony_ci    uint8_t block_type = self->block_types_[block_ix];
8801cb0ef41Sopenharmony_ci    self->block_len_ = block_len;
8811cb0ef41Sopenharmony_ci    self->entropy_ix_ = block_type * self->histogram_length_;
8821cb0ef41Sopenharmony_ci    StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0,
8831cb0ef41Sopenharmony_ci        storage_ix, storage);
8841cb0ef41Sopenharmony_ci  }
8851cb0ef41Sopenharmony_ci  --self->block_len_;
8861cb0ef41Sopenharmony_ci  {
8871cb0ef41Sopenharmony_ci    size_t ix = self->entropy_ix_ + symbol;
8881cb0ef41Sopenharmony_ci    BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage);
8891cb0ef41Sopenharmony_ci  }
8901cb0ef41Sopenharmony_ci}
8911cb0ef41Sopenharmony_ci
8921cb0ef41Sopenharmony_ci/* Stores the next symbol with the entropy code of the current block type and
8931cb0ef41Sopenharmony_ci   context value.
8941cb0ef41Sopenharmony_ci   Updates the block type and block length at block boundaries. */
8951cb0ef41Sopenharmony_cistatic void StoreSymbolWithContext(BlockEncoder* self, size_t symbol,
8961cb0ef41Sopenharmony_ci    size_t context, const uint32_t* context_map, size_t* storage_ix,
8971cb0ef41Sopenharmony_ci    uint8_t* storage, const size_t context_bits) {
8981cb0ef41Sopenharmony_ci  if (self->block_len_ == 0) {
8991cb0ef41Sopenharmony_ci    size_t block_ix = ++self->block_ix_;
9001cb0ef41Sopenharmony_ci    uint32_t block_len = self->block_lengths_[block_ix];
9011cb0ef41Sopenharmony_ci    uint8_t block_type = self->block_types_[block_ix];
9021cb0ef41Sopenharmony_ci    self->block_len_ = block_len;
9031cb0ef41Sopenharmony_ci    self->entropy_ix_ = (size_t)block_type << context_bits;
9041cb0ef41Sopenharmony_ci    StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0,
9051cb0ef41Sopenharmony_ci        storage_ix, storage);
9061cb0ef41Sopenharmony_ci  }
9071cb0ef41Sopenharmony_ci  --self->block_len_;
9081cb0ef41Sopenharmony_ci  {
9091cb0ef41Sopenharmony_ci    size_t histo_ix = context_map[self->entropy_ix_ + context];
9101cb0ef41Sopenharmony_ci    size_t ix = histo_ix * self->histogram_length_ + symbol;
9111cb0ef41Sopenharmony_ci    BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage);
9121cb0ef41Sopenharmony_ci  }
9131cb0ef41Sopenharmony_ci}
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_ci#define FN(X) X ## Literal
9161cb0ef41Sopenharmony_ci/* NOLINTNEXTLINE(build/include) */
9171cb0ef41Sopenharmony_ci#include "./block_encoder_inc.h"
9181cb0ef41Sopenharmony_ci#undef FN
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ci#define FN(X) X ## Command
9211cb0ef41Sopenharmony_ci/* NOLINTNEXTLINE(build/include) */
9221cb0ef41Sopenharmony_ci#include "./block_encoder_inc.h"
9231cb0ef41Sopenharmony_ci#undef FN
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci#define FN(X) X ## Distance
9261cb0ef41Sopenharmony_ci/* NOLINTNEXTLINE(build/include) */
9271cb0ef41Sopenharmony_ci#include "./block_encoder_inc.h"
9281cb0ef41Sopenharmony_ci#undef FN
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_cistatic void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {
9311cb0ef41Sopenharmony_ci  *storage_ix = (*storage_ix + 7u) & ~7u;
9321cb0ef41Sopenharmony_ci  storage[*storage_ix >> 3] = 0;
9331cb0ef41Sopenharmony_ci}
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_civoid BrotliStoreMetaBlock(MemoryManager* m,
9361cb0ef41Sopenharmony_ci    const uint8_t* input, size_t start_pos, size_t length, size_t mask,
9371cb0ef41Sopenharmony_ci    uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,
9381cb0ef41Sopenharmony_ci    const BrotliEncoderParams* params, ContextType literal_context_mode,
9391cb0ef41Sopenharmony_ci    const Command* commands, size_t n_commands, const MetaBlockSplit* mb,
9401cb0ef41Sopenharmony_ci    size_t* storage_ix, uint8_t* storage) {
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  size_t pos = start_pos;
9431cb0ef41Sopenharmony_ci  size_t i;
9441cb0ef41Sopenharmony_ci  uint32_t num_distance_symbols = params->dist.alphabet_size_max;
9451cb0ef41Sopenharmony_ci  uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit;
9461cb0ef41Sopenharmony_ci  HuffmanTree* tree;
9471cb0ef41Sopenharmony_ci  ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
9481cb0ef41Sopenharmony_ci  BlockEncoder literal_enc;
9491cb0ef41Sopenharmony_ci  BlockEncoder command_enc;
9501cb0ef41Sopenharmony_ci  BlockEncoder distance_enc;
9511cb0ef41Sopenharmony_ci  const BrotliDistanceParams* dist = &params->dist;
9521cb0ef41Sopenharmony_ci  BROTLI_DCHECK(
9531cb0ef41Sopenharmony_ci      num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS);
9541cb0ef41Sopenharmony_ci
9551cb0ef41Sopenharmony_ci  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ci  tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);
9581cb0ef41Sopenharmony_ci  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree)) return;
9591cb0ef41Sopenharmony_ci  InitBlockEncoder(&literal_enc, BROTLI_NUM_LITERAL_SYMBOLS,
9601cb0ef41Sopenharmony_ci      mb->literal_split.num_types, mb->literal_split.types,
9611cb0ef41Sopenharmony_ci      mb->literal_split.lengths, mb->literal_split.num_blocks);
9621cb0ef41Sopenharmony_ci  InitBlockEncoder(&command_enc, BROTLI_NUM_COMMAND_SYMBOLS,
9631cb0ef41Sopenharmony_ci      mb->command_split.num_types, mb->command_split.types,
9641cb0ef41Sopenharmony_ci      mb->command_split.lengths, mb->command_split.num_blocks);
9651cb0ef41Sopenharmony_ci  InitBlockEncoder(&distance_enc, num_effective_distance_symbols,
9661cb0ef41Sopenharmony_ci      mb->distance_split.num_types, mb->distance_split.types,
9671cb0ef41Sopenharmony_ci      mb->distance_split.lengths, mb->distance_split.num_blocks);
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_ci  BuildAndStoreBlockSwitchEntropyCodes(&literal_enc, tree, storage_ix, storage);
9701cb0ef41Sopenharmony_ci  BuildAndStoreBlockSwitchEntropyCodes(&command_enc, tree, storage_ix, storage);
9711cb0ef41Sopenharmony_ci  BuildAndStoreBlockSwitchEntropyCodes(
9721cb0ef41Sopenharmony_ci      &distance_enc, tree, storage_ix, storage);
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci  BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage);
9751cb0ef41Sopenharmony_ci  BrotliWriteBits(
9761cb0ef41Sopenharmony_ci      4, dist->num_direct_distance_codes >> dist->distance_postfix_bits,
9771cb0ef41Sopenharmony_ci      storage_ix, storage);
9781cb0ef41Sopenharmony_ci  for (i = 0; i < mb->literal_split.num_types; ++i) {
9791cb0ef41Sopenharmony_ci    BrotliWriteBits(2, literal_context_mode, storage_ix, storage);
9801cb0ef41Sopenharmony_ci  }
9811cb0ef41Sopenharmony_ci
9821cb0ef41Sopenharmony_ci  if (mb->literal_context_map_size == 0) {
9831cb0ef41Sopenharmony_ci    StoreTrivialContextMap(mb->literal_histograms_size,
9841cb0ef41Sopenharmony_ci        BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage);
9851cb0ef41Sopenharmony_ci  } else {
9861cb0ef41Sopenharmony_ci    EncodeContextMap(m,
9871cb0ef41Sopenharmony_ci        mb->literal_context_map, mb->literal_context_map_size,
9881cb0ef41Sopenharmony_ci        mb->literal_histograms_size, tree, storage_ix, storage);
9891cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m)) return;
9901cb0ef41Sopenharmony_ci  }
9911cb0ef41Sopenharmony_ci
9921cb0ef41Sopenharmony_ci  if (mb->distance_context_map_size == 0) {
9931cb0ef41Sopenharmony_ci    StoreTrivialContextMap(mb->distance_histograms_size,
9941cb0ef41Sopenharmony_ci        BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage);
9951cb0ef41Sopenharmony_ci  } else {
9961cb0ef41Sopenharmony_ci    EncodeContextMap(m,
9971cb0ef41Sopenharmony_ci        mb->distance_context_map, mb->distance_context_map_size,
9981cb0ef41Sopenharmony_ci        mb->distance_histograms_size, tree, storage_ix, storage);
9991cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m)) return;
10001cb0ef41Sopenharmony_ci  }
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_ci  BuildAndStoreEntropyCodesLiteral(m, &literal_enc, mb->literal_histograms,
10031cb0ef41Sopenharmony_ci      mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,
10041cb0ef41Sopenharmony_ci      storage_ix, storage);
10051cb0ef41Sopenharmony_ci  if (BROTLI_IS_OOM(m)) return;
10061cb0ef41Sopenharmony_ci  BuildAndStoreEntropyCodesCommand(m, &command_enc, mb->command_histograms,
10071cb0ef41Sopenharmony_ci      mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree,
10081cb0ef41Sopenharmony_ci      storage_ix, storage);
10091cb0ef41Sopenharmony_ci  if (BROTLI_IS_OOM(m)) return;
10101cb0ef41Sopenharmony_ci  BuildAndStoreEntropyCodesDistance(m, &distance_enc, mb->distance_histograms,
10111cb0ef41Sopenharmony_ci      mb->distance_histograms_size, num_distance_symbols, tree,
10121cb0ef41Sopenharmony_ci      storage_ix, storage);
10131cb0ef41Sopenharmony_ci  if (BROTLI_IS_OOM(m)) return;
10141cb0ef41Sopenharmony_ci  BROTLI_FREE(m, tree);
10151cb0ef41Sopenharmony_ci
10161cb0ef41Sopenharmony_ci  for (i = 0; i < n_commands; ++i) {
10171cb0ef41Sopenharmony_ci    const Command cmd = commands[i];
10181cb0ef41Sopenharmony_ci    size_t cmd_code = cmd.cmd_prefix_;
10191cb0ef41Sopenharmony_ci    StoreSymbol(&command_enc, cmd_code, storage_ix, storage);
10201cb0ef41Sopenharmony_ci    StoreCommandExtra(&cmd, storage_ix, storage);
10211cb0ef41Sopenharmony_ci    if (mb->literal_context_map_size == 0) {
10221cb0ef41Sopenharmony_ci      size_t j;
10231cb0ef41Sopenharmony_ci      for (j = cmd.insert_len_; j != 0; --j) {
10241cb0ef41Sopenharmony_ci        StoreSymbol(&literal_enc, input[pos & mask], storage_ix, storage);
10251cb0ef41Sopenharmony_ci        ++pos;
10261cb0ef41Sopenharmony_ci      }
10271cb0ef41Sopenharmony_ci    } else {
10281cb0ef41Sopenharmony_ci      size_t j;
10291cb0ef41Sopenharmony_ci      for (j = cmd.insert_len_; j != 0; --j) {
10301cb0ef41Sopenharmony_ci        size_t context =
10311cb0ef41Sopenharmony_ci            BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);
10321cb0ef41Sopenharmony_ci        uint8_t literal = input[pos & mask];
10331cb0ef41Sopenharmony_ci        StoreSymbolWithContext(&literal_enc, literal, context,
10341cb0ef41Sopenharmony_ci            mb->literal_context_map, storage_ix, storage,
10351cb0ef41Sopenharmony_ci            BROTLI_LITERAL_CONTEXT_BITS);
10361cb0ef41Sopenharmony_ci        prev_byte2 = prev_byte;
10371cb0ef41Sopenharmony_ci        prev_byte = literal;
10381cb0ef41Sopenharmony_ci        ++pos;
10391cb0ef41Sopenharmony_ci      }
10401cb0ef41Sopenharmony_ci    }
10411cb0ef41Sopenharmony_ci    pos += CommandCopyLen(&cmd);
10421cb0ef41Sopenharmony_ci    if (CommandCopyLen(&cmd)) {
10431cb0ef41Sopenharmony_ci      prev_byte2 = input[(pos - 2) & mask];
10441cb0ef41Sopenharmony_ci      prev_byte = input[(pos - 1) & mask];
10451cb0ef41Sopenharmony_ci      if (cmd.cmd_prefix_ >= 128) {
10461cb0ef41Sopenharmony_ci        size_t dist_code = cmd.dist_prefix_ & 0x3FF;
10471cb0ef41Sopenharmony_ci        uint32_t distnumextra = cmd.dist_prefix_ >> 10;
10481cb0ef41Sopenharmony_ci        uint64_t distextra = cmd.dist_extra_;
10491cb0ef41Sopenharmony_ci        if (mb->distance_context_map_size == 0) {
10501cb0ef41Sopenharmony_ci          StoreSymbol(&distance_enc, dist_code, storage_ix, storage);
10511cb0ef41Sopenharmony_ci        } else {
10521cb0ef41Sopenharmony_ci          size_t context = CommandDistanceContext(&cmd);
10531cb0ef41Sopenharmony_ci          StoreSymbolWithContext(&distance_enc, dist_code, context,
10541cb0ef41Sopenharmony_ci              mb->distance_context_map, storage_ix, storage,
10551cb0ef41Sopenharmony_ci              BROTLI_DISTANCE_CONTEXT_BITS);
10561cb0ef41Sopenharmony_ci        }
10571cb0ef41Sopenharmony_ci        BrotliWriteBits(distnumextra, distextra, storage_ix, storage);
10581cb0ef41Sopenharmony_ci      }
10591cb0ef41Sopenharmony_ci    }
10601cb0ef41Sopenharmony_ci  }
10611cb0ef41Sopenharmony_ci  CleanupBlockEncoder(m, &distance_enc);
10621cb0ef41Sopenharmony_ci  CleanupBlockEncoder(m, &command_enc);
10631cb0ef41Sopenharmony_ci  CleanupBlockEncoder(m, &literal_enc);
10641cb0ef41Sopenharmony_ci  if (is_last) {
10651cb0ef41Sopenharmony_ci    JumpToByteBoundary(storage_ix, storage);
10661cb0ef41Sopenharmony_ci  }
10671cb0ef41Sopenharmony_ci}
10681cb0ef41Sopenharmony_ci
10691cb0ef41Sopenharmony_cistatic void BuildHistograms(const uint8_t* input,
10701cb0ef41Sopenharmony_ci                            size_t start_pos,
10711cb0ef41Sopenharmony_ci                            size_t mask,
10721cb0ef41Sopenharmony_ci                            const Command* commands,
10731cb0ef41Sopenharmony_ci                            size_t n_commands,
10741cb0ef41Sopenharmony_ci                            HistogramLiteral* lit_histo,
10751cb0ef41Sopenharmony_ci                            HistogramCommand* cmd_histo,
10761cb0ef41Sopenharmony_ci                            HistogramDistance* dist_histo) {
10771cb0ef41Sopenharmony_ci  size_t pos = start_pos;
10781cb0ef41Sopenharmony_ci  size_t i;
10791cb0ef41Sopenharmony_ci  for (i = 0; i < n_commands; ++i) {
10801cb0ef41Sopenharmony_ci    const Command cmd = commands[i];
10811cb0ef41Sopenharmony_ci    size_t j;
10821cb0ef41Sopenharmony_ci    HistogramAddCommand(cmd_histo, cmd.cmd_prefix_);
10831cb0ef41Sopenharmony_ci    for (j = cmd.insert_len_; j != 0; --j) {
10841cb0ef41Sopenharmony_ci      HistogramAddLiteral(lit_histo, input[pos & mask]);
10851cb0ef41Sopenharmony_ci      ++pos;
10861cb0ef41Sopenharmony_ci    }
10871cb0ef41Sopenharmony_ci    pos += CommandCopyLen(&cmd);
10881cb0ef41Sopenharmony_ci    if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {
10891cb0ef41Sopenharmony_ci      HistogramAddDistance(dist_histo, cmd.dist_prefix_ & 0x3FF);
10901cb0ef41Sopenharmony_ci    }
10911cb0ef41Sopenharmony_ci  }
10921cb0ef41Sopenharmony_ci}
10931cb0ef41Sopenharmony_ci
10941cb0ef41Sopenharmony_cistatic void StoreDataWithHuffmanCodes(const uint8_t* input,
10951cb0ef41Sopenharmony_ci                                      size_t start_pos,
10961cb0ef41Sopenharmony_ci                                      size_t mask,
10971cb0ef41Sopenharmony_ci                                      const Command* commands,
10981cb0ef41Sopenharmony_ci                                      size_t n_commands,
10991cb0ef41Sopenharmony_ci                                      const uint8_t* lit_depth,
11001cb0ef41Sopenharmony_ci                                      const uint16_t* lit_bits,
11011cb0ef41Sopenharmony_ci                                      const uint8_t* cmd_depth,
11021cb0ef41Sopenharmony_ci                                      const uint16_t* cmd_bits,
11031cb0ef41Sopenharmony_ci                                      const uint8_t* dist_depth,
11041cb0ef41Sopenharmony_ci                                      const uint16_t* dist_bits,
11051cb0ef41Sopenharmony_ci                                      size_t* storage_ix,
11061cb0ef41Sopenharmony_ci                                      uint8_t* storage) {
11071cb0ef41Sopenharmony_ci  size_t pos = start_pos;
11081cb0ef41Sopenharmony_ci  size_t i;
11091cb0ef41Sopenharmony_ci  for (i = 0; i < n_commands; ++i) {
11101cb0ef41Sopenharmony_ci    const Command cmd = commands[i];
11111cb0ef41Sopenharmony_ci    const size_t cmd_code = cmd.cmd_prefix_;
11121cb0ef41Sopenharmony_ci    size_t j;
11131cb0ef41Sopenharmony_ci    BrotliWriteBits(
11141cb0ef41Sopenharmony_ci        cmd_depth[cmd_code], cmd_bits[cmd_code], storage_ix, storage);
11151cb0ef41Sopenharmony_ci    StoreCommandExtra(&cmd, storage_ix, storage);
11161cb0ef41Sopenharmony_ci    for (j = cmd.insert_len_; j != 0; --j) {
11171cb0ef41Sopenharmony_ci      const uint8_t literal = input[pos & mask];
11181cb0ef41Sopenharmony_ci      BrotliWriteBits(
11191cb0ef41Sopenharmony_ci          lit_depth[literal], lit_bits[literal], storage_ix, storage);
11201cb0ef41Sopenharmony_ci      ++pos;
11211cb0ef41Sopenharmony_ci    }
11221cb0ef41Sopenharmony_ci    pos += CommandCopyLen(&cmd);
11231cb0ef41Sopenharmony_ci    if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {
11241cb0ef41Sopenharmony_ci      const size_t dist_code = cmd.dist_prefix_ & 0x3FF;
11251cb0ef41Sopenharmony_ci      const uint32_t distnumextra = cmd.dist_prefix_ >> 10;
11261cb0ef41Sopenharmony_ci      const uint32_t distextra = cmd.dist_extra_;
11271cb0ef41Sopenharmony_ci      BrotliWriteBits(dist_depth[dist_code], dist_bits[dist_code],
11281cb0ef41Sopenharmony_ci                      storage_ix, storage);
11291cb0ef41Sopenharmony_ci      BrotliWriteBits(distnumextra, distextra, storage_ix, storage);
11301cb0ef41Sopenharmony_ci    }
11311cb0ef41Sopenharmony_ci  }
11321cb0ef41Sopenharmony_ci}
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_civoid BrotliStoreMetaBlockTrivial(MemoryManager* m,
11351cb0ef41Sopenharmony_ci    const uint8_t* input, size_t start_pos, size_t length, size_t mask,
11361cb0ef41Sopenharmony_ci    BROTLI_BOOL is_last, const BrotliEncoderParams* params,
11371cb0ef41Sopenharmony_ci    const Command* commands, size_t n_commands,
11381cb0ef41Sopenharmony_ci    size_t* storage_ix, uint8_t* storage) {
11391cb0ef41Sopenharmony_ci  HistogramLiteral lit_histo;
11401cb0ef41Sopenharmony_ci  HistogramCommand cmd_histo;
11411cb0ef41Sopenharmony_ci  HistogramDistance dist_histo;
11421cb0ef41Sopenharmony_ci  uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
11431cb0ef41Sopenharmony_ci  uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
11441cb0ef41Sopenharmony_ci  uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];
11451cb0ef41Sopenharmony_ci  uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];
11461cb0ef41Sopenharmony_ci  uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
11471cb0ef41Sopenharmony_ci  uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
11481cb0ef41Sopenharmony_ci  HuffmanTree* tree;
11491cb0ef41Sopenharmony_ci  uint32_t num_distance_symbols = params->dist.alphabet_size_max;
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
11521cb0ef41Sopenharmony_ci
11531cb0ef41Sopenharmony_ci  HistogramClearLiteral(&lit_histo);
11541cb0ef41Sopenharmony_ci  HistogramClearCommand(&cmd_histo);
11551cb0ef41Sopenharmony_ci  HistogramClearDistance(&dist_histo);
11561cb0ef41Sopenharmony_ci
11571cb0ef41Sopenharmony_ci  BuildHistograms(input, start_pos, mask, commands, n_commands,
11581cb0ef41Sopenharmony_ci                  &lit_histo, &cmd_histo, &dist_histo);
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci  BrotliWriteBits(13, 0, storage_ix, storage);
11611cb0ef41Sopenharmony_ci
11621cb0ef41Sopenharmony_ci  tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);
11631cb0ef41Sopenharmony_ci  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree)) return;
11641cb0ef41Sopenharmony_ci  BuildAndStoreHuffmanTree(lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS,
11651cb0ef41Sopenharmony_ci                           BROTLI_NUM_LITERAL_SYMBOLS, tree,
11661cb0ef41Sopenharmony_ci                           lit_depth, lit_bits,
11671cb0ef41Sopenharmony_ci                           storage_ix, storage);
11681cb0ef41Sopenharmony_ci  BuildAndStoreHuffmanTree(cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS,
11691cb0ef41Sopenharmony_ci                           BROTLI_NUM_COMMAND_SYMBOLS, tree,
11701cb0ef41Sopenharmony_ci                           cmd_depth, cmd_bits,
11711cb0ef41Sopenharmony_ci                           storage_ix, storage);
11721cb0ef41Sopenharmony_ci  BuildAndStoreHuffmanTree(dist_histo.data_, MAX_SIMPLE_DISTANCE_ALPHABET_SIZE,
11731cb0ef41Sopenharmony_ci                           num_distance_symbols, tree,
11741cb0ef41Sopenharmony_ci                           dist_depth, dist_bits,
11751cb0ef41Sopenharmony_ci                           storage_ix, storage);
11761cb0ef41Sopenharmony_ci  BROTLI_FREE(m, tree);
11771cb0ef41Sopenharmony_ci  StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
11781cb0ef41Sopenharmony_ci                            n_commands, lit_depth, lit_bits,
11791cb0ef41Sopenharmony_ci                            cmd_depth, cmd_bits,
11801cb0ef41Sopenharmony_ci                            dist_depth, dist_bits,
11811cb0ef41Sopenharmony_ci                            storage_ix, storage);
11821cb0ef41Sopenharmony_ci  if (is_last) {
11831cb0ef41Sopenharmony_ci    JumpToByteBoundary(storage_ix, storage);
11841cb0ef41Sopenharmony_ci  }
11851cb0ef41Sopenharmony_ci}
11861cb0ef41Sopenharmony_ci
11871cb0ef41Sopenharmony_civoid BrotliStoreMetaBlockFast(MemoryManager* m,
11881cb0ef41Sopenharmony_ci    const uint8_t* input, size_t start_pos, size_t length, size_t mask,
11891cb0ef41Sopenharmony_ci    BROTLI_BOOL is_last, const BrotliEncoderParams* params,
11901cb0ef41Sopenharmony_ci    const Command* commands, size_t n_commands,
11911cb0ef41Sopenharmony_ci    size_t* storage_ix, uint8_t* storage) {
11921cb0ef41Sopenharmony_ci  uint32_t num_distance_symbols = params->dist.alphabet_size_max;
11931cb0ef41Sopenharmony_ci  uint32_t distance_alphabet_bits =
11941cb0ef41Sopenharmony_ci      Log2FloorNonZero(num_distance_symbols - 1) + 1;
11951cb0ef41Sopenharmony_ci
11961cb0ef41Sopenharmony_ci  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
11971cb0ef41Sopenharmony_ci
11981cb0ef41Sopenharmony_ci  BrotliWriteBits(13, 0, storage_ix, storage);
11991cb0ef41Sopenharmony_ci
12001cb0ef41Sopenharmony_ci  if (n_commands <= 128) {
12011cb0ef41Sopenharmony_ci    uint32_t histogram[BROTLI_NUM_LITERAL_SYMBOLS] = { 0 };
12021cb0ef41Sopenharmony_ci    size_t pos = start_pos;
12031cb0ef41Sopenharmony_ci    size_t num_literals = 0;
12041cb0ef41Sopenharmony_ci    size_t i;
12051cb0ef41Sopenharmony_ci    uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
12061cb0ef41Sopenharmony_ci    uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
12071cb0ef41Sopenharmony_ci    for (i = 0; i < n_commands; ++i) {
12081cb0ef41Sopenharmony_ci      const Command cmd = commands[i];
12091cb0ef41Sopenharmony_ci      size_t j;
12101cb0ef41Sopenharmony_ci      for (j = cmd.insert_len_; j != 0; --j) {
12111cb0ef41Sopenharmony_ci        ++histogram[input[pos & mask]];
12121cb0ef41Sopenharmony_ci        ++pos;
12131cb0ef41Sopenharmony_ci      }
12141cb0ef41Sopenharmony_ci      num_literals += cmd.insert_len_;
12151cb0ef41Sopenharmony_ci      pos += CommandCopyLen(&cmd);
12161cb0ef41Sopenharmony_ci    }
12171cb0ef41Sopenharmony_ci    BrotliBuildAndStoreHuffmanTreeFast(m, histogram, num_literals,
12181cb0ef41Sopenharmony_ci                                       /* max_bits = */ 8,
12191cb0ef41Sopenharmony_ci                                       lit_depth, lit_bits,
12201cb0ef41Sopenharmony_ci                                       storage_ix, storage);
12211cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m)) return;
12221cb0ef41Sopenharmony_ci    StoreStaticCommandHuffmanTree(storage_ix, storage);
12231cb0ef41Sopenharmony_ci    StoreStaticDistanceHuffmanTree(storage_ix, storage);
12241cb0ef41Sopenharmony_ci    StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
12251cb0ef41Sopenharmony_ci                              n_commands, lit_depth, lit_bits,
12261cb0ef41Sopenharmony_ci                              kStaticCommandCodeDepth,
12271cb0ef41Sopenharmony_ci                              kStaticCommandCodeBits,
12281cb0ef41Sopenharmony_ci                              kStaticDistanceCodeDepth,
12291cb0ef41Sopenharmony_ci                              kStaticDistanceCodeBits,
12301cb0ef41Sopenharmony_ci                              storage_ix, storage);
12311cb0ef41Sopenharmony_ci  } else {
12321cb0ef41Sopenharmony_ci    HistogramLiteral lit_histo;
12331cb0ef41Sopenharmony_ci    HistogramCommand cmd_histo;
12341cb0ef41Sopenharmony_ci    HistogramDistance dist_histo;
12351cb0ef41Sopenharmony_ci    uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
12361cb0ef41Sopenharmony_ci    uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
12371cb0ef41Sopenharmony_ci    uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];
12381cb0ef41Sopenharmony_ci    uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];
12391cb0ef41Sopenharmony_ci    uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
12401cb0ef41Sopenharmony_ci    uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
12411cb0ef41Sopenharmony_ci    HistogramClearLiteral(&lit_histo);
12421cb0ef41Sopenharmony_ci    HistogramClearCommand(&cmd_histo);
12431cb0ef41Sopenharmony_ci    HistogramClearDistance(&dist_histo);
12441cb0ef41Sopenharmony_ci    BuildHistograms(input, start_pos, mask, commands, n_commands,
12451cb0ef41Sopenharmony_ci                    &lit_histo, &cmd_histo, &dist_histo);
12461cb0ef41Sopenharmony_ci    BrotliBuildAndStoreHuffmanTreeFast(m, lit_histo.data_,
12471cb0ef41Sopenharmony_ci                                       lit_histo.total_count_,
12481cb0ef41Sopenharmony_ci                                       /* max_bits = */ 8,
12491cb0ef41Sopenharmony_ci                                       lit_depth, lit_bits,
12501cb0ef41Sopenharmony_ci                                       storage_ix, storage);
12511cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m)) return;
12521cb0ef41Sopenharmony_ci    BrotliBuildAndStoreHuffmanTreeFast(m, cmd_histo.data_,
12531cb0ef41Sopenharmony_ci                                       cmd_histo.total_count_,
12541cb0ef41Sopenharmony_ci                                       /* max_bits = */ 10,
12551cb0ef41Sopenharmony_ci                                       cmd_depth, cmd_bits,
12561cb0ef41Sopenharmony_ci                                       storage_ix, storage);
12571cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m)) return;
12581cb0ef41Sopenharmony_ci    BrotliBuildAndStoreHuffmanTreeFast(m, dist_histo.data_,
12591cb0ef41Sopenharmony_ci                                       dist_histo.total_count_,
12601cb0ef41Sopenharmony_ci                                       /* max_bits = */
12611cb0ef41Sopenharmony_ci                                       distance_alphabet_bits,
12621cb0ef41Sopenharmony_ci                                       dist_depth, dist_bits,
12631cb0ef41Sopenharmony_ci                                       storage_ix, storage);
12641cb0ef41Sopenharmony_ci    if (BROTLI_IS_OOM(m)) return;
12651cb0ef41Sopenharmony_ci    StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
12661cb0ef41Sopenharmony_ci                              n_commands, lit_depth, lit_bits,
12671cb0ef41Sopenharmony_ci                              cmd_depth, cmd_bits,
12681cb0ef41Sopenharmony_ci                              dist_depth, dist_bits,
12691cb0ef41Sopenharmony_ci                              storage_ix, storage);
12701cb0ef41Sopenharmony_ci  }
12711cb0ef41Sopenharmony_ci
12721cb0ef41Sopenharmony_ci  if (is_last) {
12731cb0ef41Sopenharmony_ci    JumpToByteBoundary(storage_ix, storage);
12741cb0ef41Sopenharmony_ci  }
12751cb0ef41Sopenharmony_ci}
12761cb0ef41Sopenharmony_ci
12771cb0ef41Sopenharmony_ci/* This is for storing uncompressed blocks (simple raw storage of
12781cb0ef41Sopenharmony_ci   bytes-as-bytes). */
12791cb0ef41Sopenharmony_civoid BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block,
12801cb0ef41Sopenharmony_ci                                      const uint8_t* BROTLI_RESTRICT input,
12811cb0ef41Sopenharmony_ci                                      size_t position, size_t mask,
12821cb0ef41Sopenharmony_ci                                      size_t len,
12831cb0ef41Sopenharmony_ci                                      size_t* BROTLI_RESTRICT storage_ix,
12841cb0ef41Sopenharmony_ci                                      uint8_t* BROTLI_RESTRICT storage) {
12851cb0ef41Sopenharmony_ci  size_t masked_pos = position & mask;
12861cb0ef41Sopenharmony_ci  BrotliStoreUncompressedMetaBlockHeader(len, storage_ix, storage);
12871cb0ef41Sopenharmony_ci  JumpToByteBoundary(storage_ix, storage);
12881cb0ef41Sopenharmony_ci
12891cb0ef41Sopenharmony_ci  if (masked_pos + len > mask + 1) {
12901cb0ef41Sopenharmony_ci    size_t len1 = mask + 1 - masked_pos;
12911cb0ef41Sopenharmony_ci    memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len1);
12921cb0ef41Sopenharmony_ci    *storage_ix += len1 << 3;
12931cb0ef41Sopenharmony_ci    len -= len1;
12941cb0ef41Sopenharmony_ci    masked_pos = 0;
12951cb0ef41Sopenharmony_ci  }
12961cb0ef41Sopenharmony_ci  memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len);
12971cb0ef41Sopenharmony_ci  *storage_ix += len << 3;
12981cb0ef41Sopenharmony_ci
12991cb0ef41Sopenharmony_ci  /* We need to clear the next 4 bytes to continue to be
13001cb0ef41Sopenharmony_ci     compatible with BrotliWriteBits. */
13011cb0ef41Sopenharmony_ci  BrotliWriteBitsPrepareStorage(*storage_ix, storage);
13021cb0ef41Sopenharmony_ci
13031cb0ef41Sopenharmony_ci  /* Since the uncompressed block itself may not be the final block, add an
13041cb0ef41Sopenharmony_ci     empty one after this. */
13051cb0ef41Sopenharmony_ci  if (is_final_block) {
13061cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */
13071cb0ef41Sopenharmony_ci    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */
13081cb0ef41Sopenharmony_ci    JumpToByteBoundary(storage_ix, storage);
13091cb0ef41Sopenharmony_ci  }
13101cb0ef41Sopenharmony_ci}
13111cb0ef41Sopenharmony_ci
13121cb0ef41Sopenharmony_ci#if defined(__cplusplus) || defined(c_plusplus)
13131cb0ef41Sopenharmony_ci}  /* extern "C" */
13141cb0ef41Sopenharmony_ci#endif
1315