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 = ¶ms->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