126fa459cSmrg/* Copyright 2010 Google Inc. All Rights Reserved.
226fa459cSmrg
326fa459cSmrg   Distributed under MIT license.
426fa459cSmrg   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
526fa459cSmrg*/
626fa459cSmrg
726fa459cSmrg/* A (forgetful) hash table to the data seen by the compressor, to
826fa459cSmrg   help create backward references to previous data. */
926fa459cSmrg
1026fa459cSmrg#ifndef BROTLI_ENC_HASH_H_
1126fa459cSmrg#define BROTLI_ENC_HASH_H_
1226fa459cSmrg
1326fa459cSmrg#include <string.h>  /* memcmp, memset */
1426fa459cSmrg
1526fa459cSmrg#include "../common/constants.h"
1626fa459cSmrg#include "../common/dictionary.h"
1726fa459cSmrg#include "../common/platform.h"
1826fa459cSmrg#include <brotli/types.h>
1926fa459cSmrg#include "./encoder_dict.h"
2026fa459cSmrg#include "./fast_log.h"
2126fa459cSmrg#include "./find_match_length.h"
2226fa459cSmrg#include "./memory.h"
2326fa459cSmrg#include "./quality.h"
2426fa459cSmrg#include "./static_dict.h"
2526fa459cSmrg
2626fa459cSmrg#if defined(__cplusplus) || defined(c_plusplus)
2726fa459cSmrgextern "C" {
2826fa459cSmrg#endif
2926fa459cSmrg
3026fa459cSmrgtypedef struct {
3126fa459cSmrg  /* Dynamically allocated area; first member for quickest access. */
3226fa459cSmrg  void* extra;
3326fa459cSmrg
3426fa459cSmrg  size_t dict_num_lookups;
3526fa459cSmrg  size_t dict_num_matches;
3626fa459cSmrg
3726fa459cSmrg  BrotliHasherParams params;
3826fa459cSmrg
3926fa459cSmrg  /* False if hasher needs to be "prepared" before use. */
4026fa459cSmrg  BROTLI_BOOL is_prepared_;
4126fa459cSmrg} HasherCommon;
4226fa459cSmrg
4326fa459cSmrg#define score_t size_t
4426fa459cSmrg
4526fa459cSmrgstatic const uint32_t kCutoffTransformsCount = 10;
4626fa459cSmrg/*   0,  12,   27,    23,    42,    63,    56,    48,    59,    64 */
4726fa459cSmrg/* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */
4826fa459cSmrgstatic const uint64_t kCutoffTransforms =
4926fa459cSmrg    BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200);
5026fa459cSmrg
5126fa459cSmrgtypedef struct HasherSearchResult {
5226fa459cSmrg  size_t len;
5326fa459cSmrg  size_t distance;
5426fa459cSmrg  score_t score;
5526fa459cSmrg  int len_code_delta; /* == len_code - len */
5626fa459cSmrg} HasherSearchResult;
5726fa459cSmrg
5826fa459cSmrg/* kHashMul32 multiplier has these properties:
5926fa459cSmrg   * The multiplier must be odd. Otherwise we may lose the highest bit.
6026fa459cSmrg   * No long streaks of ones or zeros.
6126fa459cSmrg   * There is no effort to ensure that it is a prime, the oddity is enough
6226fa459cSmrg     for this use.
6326fa459cSmrg   * The number has been tuned heuristically against compression benchmarks. */
6426fa459cSmrgstatic const uint32_t kHashMul32 = 0x1E35A7BD;
6526fa459cSmrgstatic const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1E35A7BD, 0x1E35A7BD);
6626fa459cSmrgstatic const uint64_t kHashMul64Long =
6726fa459cSmrg    BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);
6826fa459cSmrg
6926fa459cSmrgstatic BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {
7026fa459cSmrg  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
7126fa459cSmrg  /* The higher bits contain more mixture from the multiplication,
7226fa459cSmrg     so we take our results from there. */
7326fa459cSmrg  return h >> (32 - 14);
7426fa459cSmrg}
7526fa459cSmrg
7626fa459cSmrgstatic BROTLI_INLINE void PrepareDistanceCache(
7726fa459cSmrg    int* BROTLI_RESTRICT distance_cache, const int num_distances) {
7826fa459cSmrg  if (num_distances > 4) {
7926fa459cSmrg    int last_distance = distance_cache[0];
8026fa459cSmrg    distance_cache[4] = last_distance - 1;
8126fa459cSmrg    distance_cache[5] = last_distance + 1;
8226fa459cSmrg    distance_cache[6] = last_distance - 2;
8326fa459cSmrg    distance_cache[7] = last_distance + 2;
8426fa459cSmrg    distance_cache[8] = last_distance - 3;
8526fa459cSmrg    distance_cache[9] = last_distance + 3;
8626fa459cSmrg    if (num_distances > 10) {
8726fa459cSmrg      int next_last_distance = distance_cache[1];
8826fa459cSmrg      distance_cache[10] = next_last_distance - 1;
8926fa459cSmrg      distance_cache[11] = next_last_distance + 1;
9026fa459cSmrg      distance_cache[12] = next_last_distance - 2;
9126fa459cSmrg      distance_cache[13] = next_last_distance + 2;
9226fa459cSmrg      distance_cache[14] = next_last_distance - 3;
9326fa459cSmrg      distance_cache[15] = next_last_distance + 3;
9426fa459cSmrg    }
9526fa459cSmrg  }
9626fa459cSmrg}
9726fa459cSmrg
9826fa459cSmrg#define BROTLI_LITERAL_BYTE_SCORE 135
9926fa459cSmrg#define BROTLI_DISTANCE_BIT_PENALTY 30
10026fa459cSmrg/* Score must be positive after applying maximal penalty. */
10126fa459cSmrg#define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t))
10226fa459cSmrg
10326fa459cSmrg/* Usually, we always choose the longest backward reference. This function
10426fa459cSmrg   allows for the exception of that rule.
10526fa459cSmrg
10626fa459cSmrg   If we choose a backward reference that is further away, it will
10726fa459cSmrg   usually be coded with more bits. We approximate this by assuming
10826fa459cSmrg   log2(distance). If the distance can be expressed in terms of the
10926fa459cSmrg   last four distances, we use some heuristic constants to estimate
11026fa459cSmrg   the bits cost. For the first up to four literals we use the bit
11126fa459cSmrg   cost of the literals from the literal cost model, after that we
11226fa459cSmrg   use the average bit cost of the cost model.
11326fa459cSmrg
11426fa459cSmrg   This function is used to sometimes discard a longer backward reference
11526fa459cSmrg   when it is not much longer and the bit cost for encoding it is more
11626fa459cSmrg   than the saved literals.
11726fa459cSmrg
11826fa459cSmrg   backward_reference_offset MUST be positive. */
11926fa459cSmrgstatic BROTLI_INLINE score_t BackwardReferenceScore(
12026fa459cSmrg    size_t copy_length, size_t backward_reference_offset) {
12126fa459cSmrg  return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length -
12226fa459cSmrg      BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);
12326fa459cSmrg}
12426fa459cSmrg
12526fa459cSmrgstatic BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(
12626fa459cSmrg    size_t copy_length) {
12726fa459cSmrg  return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +
12826fa459cSmrg      BROTLI_SCORE_BASE + 15;
12926fa459cSmrg}
13026fa459cSmrg
13126fa459cSmrgstatic BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
13226fa459cSmrg    size_t distance_short_code) {
13326fa459cSmrg  return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE);
13426fa459cSmrg}
13526fa459cSmrg
13626fa459cSmrgstatic BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
13726fa459cSmrg    const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,
13826fa459cSmrg    const uint8_t* data, size_t max_length, size_t max_backward,
13926fa459cSmrg    size_t max_distance, HasherSearchResult* out) {
14026fa459cSmrg  size_t offset;
14126fa459cSmrg  size_t matchlen;
14226fa459cSmrg  size_t backward;
14326fa459cSmrg  score_t score;
14426fa459cSmrg  offset = dictionary->words->offsets_by_length[len] + len * word_idx;
14526fa459cSmrg  if (len > max_length) {
14626fa459cSmrg    return BROTLI_FALSE;
14726fa459cSmrg  }
14826fa459cSmrg
14926fa459cSmrg  matchlen =
15026fa459cSmrg      FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);
15126fa459cSmrg  if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {
15226fa459cSmrg    return BROTLI_FALSE;
15326fa459cSmrg  }
15426fa459cSmrg  {
15526fa459cSmrg    size_t cut = len - matchlen;
15626fa459cSmrg    size_t transform_id = (cut << 2) +
15726fa459cSmrg        (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);
15826fa459cSmrg    backward = max_backward + 1 + word_idx +
15926fa459cSmrg        (transform_id << dictionary->words->size_bits_by_length[len]);
16026fa459cSmrg  }
16126fa459cSmrg  if (backward > max_distance) {
16226fa459cSmrg    return BROTLI_FALSE;
16326fa459cSmrg  }
16426fa459cSmrg  score = BackwardReferenceScore(matchlen, backward);
16526fa459cSmrg  if (score < out->score) {
16626fa459cSmrg    return BROTLI_FALSE;
16726fa459cSmrg  }
16826fa459cSmrg  out->len = matchlen;
16926fa459cSmrg  out->len_code_delta = (int)len - (int)matchlen;
17026fa459cSmrg  out->distance = backward;
17126fa459cSmrg  out->score = score;
17226fa459cSmrg  return BROTLI_TRUE;
17326fa459cSmrg}
17426fa459cSmrg
17526fa459cSmrgstatic BROTLI_INLINE void SearchInStaticDictionary(
17626fa459cSmrg    const BrotliEncoderDictionary* dictionary,
17726fa459cSmrg    HasherCommon* common, const uint8_t* data, size_t max_length,
17826fa459cSmrg    size_t max_backward, size_t max_distance,
17926fa459cSmrg    HasherSearchResult* out, BROTLI_BOOL shallow) {
18026fa459cSmrg  size_t key;
18126fa459cSmrg  size_t i;
18226fa459cSmrg  if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {
18326fa459cSmrg    return;
18426fa459cSmrg  }
18526fa459cSmrg  key = Hash14(data) << 1;
18626fa459cSmrg  for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {
18726fa459cSmrg    common->dict_num_lookups++;
18826fa459cSmrg    if (dictionary->hash_table_lengths[key] != 0) {
18926fa459cSmrg      BROTLI_BOOL item_matches = TestStaticDictionaryItem(
19026fa459cSmrg          dictionary, dictionary->hash_table_lengths[key],
19126fa459cSmrg          dictionary->hash_table_words[key], data,
19226fa459cSmrg          max_length, max_backward, max_distance, out);
19326fa459cSmrg      if (item_matches) {
19426fa459cSmrg        common->dict_num_matches++;
19526fa459cSmrg      }
19626fa459cSmrg    }
19726fa459cSmrg  }
19826fa459cSmrg}
19926fa459cSmrg
20026fa459cSmrgtypedef struct BackwardMatch {
20126fa459cSmrg  uint32_t distance;
20226fa459cSmrg  uint32_t length_and_code;
20326fa459cSmrg} BackwardMatch;
20426fa459cSmrg
20526fa459cSmrgstatic BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self,
20626fa459cSmrg    size_t dist, size_t len) {
20726fa459cSmrg  self->distance = (uint32_t)dist;
20826fa459cSmrg  self->length_and_code = (uint32_t)(len << 5);
20926fa459cSmrg}
21026fa459cSmrg
21126fa459cSmrgstatic BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self,
21226fa459cSmrg    size_t dist, size_t len, size_t len_code) {
21326fa459cSmrg  self->distance = (uint32_t)dist;
21426fa459cSmrg  self->length_and_code =
21526fa459cSmrg      (uint32_t)((len << 5) | (len == len_code ? 0 : len_code));
21626fa459cSmrg}
21726fa459cSmrg
21826fa459cSmrgstatic BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) {
21926fa459cSmrg  return self->length_and_code >> 5;
22026fa459cSmrg}
22126fa459cSmrg
22226fa459cSmrgstatic BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
22326fa459cSmrg  size_t code = self->length_and_code & 31;
22426fa459cSmrg  return code ? code : BackwardMatchLength(self);
22526fa459cSmrg}
22626fa459cSmrg
22726fa459cSmrg#define EXPAND_CAT(a, b) CAT(a, b)
22826fa459cSmrg#define CAT(a, b) a ## b
22926fa459cSmrg#define FN(X) EXPAND_CAT(X, HASHER())
23026fa459cSmrg
23126fa459cSmrg#define HASHER() H10
23226fa459cSmrg#define BUCKET_BITS 17
23326fa459cSmrg#define MAX_TREE_SEARCH_DEPTH 64
23426fa459cSmrg#define MAX_TREE_COMP_LENGTH 128
23526fa459cSmrg#include "./hash_to_binary_tree_inc.h"  /* NOLINT(build/include) */
23626fa459cSmrg#undef MAX_TREE_SEARCH_DEPTH
23726fa459cSmrg#undef MAX_TREE_COMP_LENGTH
23826fa459cSmrg#undef BUCKET_BITS
23926fa459cSmrg#undef HASHER
24026fa459cSmrg/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */
24126fa459cSmrg#define MAX_NUM_MATCHES_H10 128
24226fa459cSmrg
24326fa459cSmrg/* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression
24426fa459cSmrg   a little faster (0.5% - 1%) and it compresses 0.15% better on small text
24526fa459cSmrg   and HTML inputs. */
24626fa459cSmrg
24726fa459cSmrg#define HASHER() H2
24826fa459cSmrg#define BUCKET_BITS 16
24926fa459cSmrg#define BUCKET_SWEEP_BITS 0
25026fa459cSmrg#define HASH_LEN 5
25126fa459cSmrg#define USE_DICTIONARY 1
25226fa459cSmrg#include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
25326fa459cSmrg#undef BUCKET_SWEEP_BITS
25426fa459cSmrg#undef USE_DICTIONARY
25526fa459cSmrg#undef HASHER
25626fa459cSmrg
25726fa459cSmrg#define HASHER() H3
25826fa459cSmrg#define BUCKET_SWEEP_BITS 1
25926fa459cSmrg#define USE_DICTIONARY 0
26026fa459cSmrg#include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
26126fa459cSmrg#undef USE_DICTIONARY
26226fa459cSmrg#undef BUCKET_SWEEP_BITS
26326fa459cSmrg#undef BUCKET_BITS
26426fa459cSmrg#undef HASHER
26526fa459cSmrg
26626fa459cSmrg#define HASHER() H4
26726fa459cSmrg#define BUCKET_BITS 17
26826fa459cSmrg#define BUCKET_SWEEP_BITS 2
26926fa459cSmrg#define USE_DICTIONARY 1
27026fa459cSmrg#include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
27126fa459cSmrg#undef USE_DICTIONARY
27226fa459cSmrg#undef HASH_LEN
27326fa459cSmrg#undef BUCKET_SWEEP_BITS
27426fa459cSmrg#undef BUCKET_BITS
27526fa459cSmrg#undef HASHER
27626fa459cSmrg
27726fa459cSmrg#define HASHER() H5
27826fa459cSmrg#include "./hash_longest_match_inc.h"  /* NOLINT(build/include) */
27926fa459cSmrg#undef HASHER
28026fa459cSmrg
28126fa459cSmrg#define HASHER() H6
28226fa459cSmrg#include "./hash_longest_match64_inc.h"  /* NOLINT(build/include) */
28326fa459cSmrg#undef HASHER
28426fa459cSmrg
28526fa459cSmrg#define BUCKET_BITS 15
28626fa459cSmrg
28726fa459cSmrg#define NUM_LAST_DISTANCES_TO_CHECK 4
28826fa459cSmrg#define NUM_BANKS 1
28926fa459cSmrg#define BANK_BITS 16
29026fa459cSmrg#define HASHER() H40
29126fa459cSmrg#include "./hash_forgetful_chain_inc.h"  /* NOLINT(build/include) */
29226fa459cSmrg#undef HASHER
29326fa459cSmrg#undef NUM_LAST_DISTANCES_TO_CHECK
29426fa459cSmrg
29526fa459cSmrg#define NUM_LAST_DISTANCES_TO_CHECK 10
29626fa459cSmrg#define HASHER() H41
29726fa459cSmrg#include "./hash_forgetful_chain_inc.h"  /* NOLINT(build/include) */
29826fa459cSmrg#undef HASHER
29926fa459cSmrg#undef NUM_LAST_DISTANCES_TO_CHECK
30026fa459cSmrg#undef NUM_BANKS
30126fa459cSmrg#undef BANK_BITS
30226fa459cSmrg
30326fa459cSmrg#define NUM_LAST_DISTANCES_TO_CHECK 16
30426fa459cSmrg#define NUM_BANKS 512
30526fa459cSmrg#define BANK_BITS 9
30626fa459cSmrg#define HASHER() H42
30726fa459cSmrg#include "./hash_forgetful_chain_inc.h"  /* NOLINT(build/include) */
30826fa459cSmrg#undef HASHER
30926fa459cSmrg#undef NUM_LAST_DISTANCES_TO_CHECK
31026fa459cSmrg#undef NUM_BANKS
31126fa459cSmrg#undef BANK_BITS
31226fa459cSmrg
31326fa459cSmrg#undef BUCKET_BITS
31426fa459cSmrg
31526fa459cSmrg#define HASHER() H54
31626fa459cSmrg#define BUCKET_BITS 20
31726fa459cSmrg#define BUCKET_SWEEP_BITS 2
31826fa459cSmrg#define HASH_LEN 7
31926fa459cSmrg#define USE_DICTIONARY 0
32026fa459cSmrg#include "./hash_longest_match_quickly_inc.h"  /* NOLINT(build/include) */
32126fa459cSmrg#undef USE_DICTIONARY
32226fa459cSmrg#undef HASH_LEN
32326fa459cSmrg#undef BUCKET_SWEEP_BITS
32426fa459cSmrg#undef BUCKET_BITS
32526fa459cSmrg#undef HASHER
32626fa459cSmrg
32726fa459cSmrg/* fast large window hashers */
32826fa459cSmrg
32926fa459cSmrg#define HASHER() HROLLING_FAST
33026fa459cSmrg#define CHUNKLEN 32
33126fa459cSmrg#define JUMP 4
33226fa459cSmrg#define NUMBUCKETS 16777216
33326fa459cSmrg#define MASK ((NUMBUCKETS * 64) - 1)
33426fa459cSmrg#include "./hash_rolling_inc.h"  /* NOLINT(build/include) */
33526fa459cSmrg#undef JUMP
33626fa459cSmrg#undef HASHER
33726fa459cSmrg
33826fa459cSmrg
33926fa459cSmrg#define HASHER() HROLLING
34026fa459cSmrg#define JUMP 1
34126fa459cSmrg#include "./hash_rolling_inc.h"  /* NOLINT(build/include) */
34226fa459cSmrg#undef MASK
34326fa459cSmrg#undef NUMBUCKETS
34426fa459cSmrg#undef JUMP
34526fa459cSmrg#undef CHUNKLEN
34626fa459cSmrg#undef HASHER
34726fa459cSmrg
34826fa459cSmrg#define HASHER() H35
34926fa459cSmrg#define HASHER_A H3
35026fa459cSmrg#define HASHER_B HROLLING_FAST
35126fa459cSmrg#include "./hash_composite_inc.h"  /* NOLINT(build/include) */
35226fa459cSmrg#undef HASHER_A
35326fa459cSmrg#undef HASHER_B
35426fa459cSmrg#undef HASHER
35526fa459cSmrg
35626fa459cSmrg#define HASHER() H55
35726fa459cSmrg#define HASHER_A H54
35826fa459cSmrg#define HASHER_B HROLLING_FAST
35926fa459cSmrg#include "./hash_composite_inc.h"  /* NOLINT(build/include) */
36026fa459cSmrg#undef HASHER_A
36126fa459cSmrg#undef HASHER_B
36226fa459cSmrg#undef HASHER
36326fa459cSmrg
36426fa459cSmrg#define HASHER() H65
36526fa459cSmrg#define HASHER_A H6
36626fa459cSmrg#define HASHER_B HROLLING
36726fa459cSmrg#include "./hash_composite_inc.h"  /* NOLINT(build/include) */
36826fa459cSmrg#undef HASHER_A
36926fa459cSmrg#undef HASHER_B
37026fa459cSmrg#undef HASHER
37126fa459cSmrg
37226fa459cSmrg#undef FN
37326fa459cSmrg#undef CAT
37426fa459cSmrg#undef EXPAND_CAT
37526fa459cSmrg
37626fa459cSmrg#define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
37726fa459cSmrg#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)
37826fa459cSmrg#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)
37926fa459cSmrg#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
38026fa459cSmrg
38126fa459cSmrgtypedef struct {
38226fa459cSmrg  HasherCommon common;
38326fa459cSmrg
38426fa459cSmrg  union {
38526fa459cSmrg#define MEMBER_(N) \
38626fa459cSmrg    H ## N _H ## N;
38726fa459cSmrg    FOR_ALL_HASHERS(MEMBER_)
38826fa459cSmrg#undef MEMBER_
38926fa459cSmrg  } privat;
39026fa459cSmrg} Hasher;
39126fa459cSmrg
39226fa459cSmrg/* MUST be invoked before any other method. */
39326fa459cSmrgstatic BROTLI_INLINE void HasherInit(Hasher* hasher) {
39426fa459cSmrg  hasher->common.extra = NULL;
39526fa459cSmrg}
39626fa459cSmrg
39726fa459cSmrgstatic BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {
39826fa459cSmrg  if (hasher->common.extra == NULL) return;
39926fa459cSmrg  BROTLI_FREE(m, hasher->common.extra);
40026fa459cSmrg}
40126fa459cSmrg
40226fa459cSmrgstatic BROTLI_INLINE void HasherReset(Hasher* hasher) {
40326fa459cSmrg  hasher->common.is_prepared_ = BROTLI_FALSE;
40426fa459cSmrg}
40526fa459cSmrg
40626fa459cSmrgstatic BROTLI_INLINE size_t HasherSize(const BrotliEncoderParams* params,
40726fa459cSmrg    BROTLI_BOOL one_shot, const size_t input_size) {
40826fa459cSmrg  switch (params->hasher.type) {
40926fa459cSmrg#define SIZE_(N)                                                      \
41026fa459cSmrg    case N:                                                           \
41126fa459cSmrg      return HashMemAllocInBytesH ## N(params, one_shot, input_size);
41226fa459cSmrg    FOR_ALL_HASHERS(SIZE_)
41326fa459cSmrg#undef SIZE_
41426fa459cSmrg    default:
41526fa459cSmrg      break;
41626fa459cSmrg  }
41726fa459cSmrg  return 0;  /* Default case. */
41826fa459cSmrg}
41926fa459cSmrg
42026fa459cSmrgstatic BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,
42126fa459cSmrg    BrotliEncoderParams* params, const uint8_t* data, size_t position,
42226fa459cSmrg    size_t input_size, BROTLI_BOOL is_last) {
42326fa459cSmrg  BROTLI_BOOL one_shot = (position == 0 && is_last);
42426fa459cSmrg  if (hasher->common.extra == NULL) {
42526fa459cSmrg    size_t alloc_size;
42626fa459cSmrg    ChooseHasher(params, &params->hasher);
42726fa459cSmrg    alloc_size = HasherSize(params, one_shot, input_size);
42826fa459cSmrg    hasher->common.extra = BROTLI_ALLOC(m, uint8_t, alloc_size);
42926fa459cSmrg    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra)) return;
43026fa459cSmrg    hasher->common.params = params->hasher;
43126fa459cSmrg    switch (hasher->common.params.type) {
43226fa459cSmrg#define INITIALIZE_(N)                        \
43326fa459cSmrg      case N:                                 \
43426fa459cSmrg        InitializeH ## N(&hasher->common,     \
43526fa459cSmrg            &hasher->privat._H ## N, params); \
43626fa459cSmrg        break;
43726fa459cSmrg      FOR_ALL_HASHERS(INITIALIZE_);
43826fa459cSmrg#undef INITIALIZE_
43926fa459cSmrg      default:
44026fa459cSmrg        break;
44126fa459cSmrg    }
44226fa459cSmrg    HasherReset(hasher);
44326fa459cSmrg  }
44426fa459cSmrg
44526fa459cSmrg  if (!hasher->common.is_prepared_) {
44626fa459cSmrg    switch (hasher->common.params.type) {
44726fa459cSmrg#define PREPARE_(N)                      \
44826fa459cSmrg      case N:                            \
44926fa459cSmrg        PrepareH ## N(                   \
45026fa459cSmrg            &hasher->privat._H ## N,     \
45126fa459cSmrg            one_shot, input_size, data); \
45226fa459cSmrg        break;
45326fa459cSmrg      FOR_ALL_HASHERS(PREPARE_)
45426fa459cSmrg#undef PREPARE_
45526fa459cSmrg      default: break;
45626fa459cSmrg    }
45726fa459cSmrg    if (position == 0) {
45826fa459cSmrg      hasher->common.dict_num_lookups = 0;
45926fa459cSmrg      hasher->common.dict_num_matches = 0;
46026fa459cSmrg    }
46126fa459cSmrg    hasher->common.is_prepared_ = BROTLI_TRUE;
46226fa459cSmrg  }
46326fa459cSmrg}
46426fa459cSmrg
46526fa459cSmrgstatic BROTLI_INLINE void InitOrStitchToPreviousBlock(
46626fa459cSmrg    MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,
46726fa459cSmrg    BrotliEncoderParams* params, size_t position, size_t input_size,
46826fa459cSmrg    BROTLI_BOOL is_last) {
46926fa459cSmrg  HasherSetup(m, hasher, params, data, position, input_size, is_last);
47026fa459cSmrg  if (BROTLI_IS_OOM(m)) return;
47126fa459cSmrg  switch (hasher->common.params.type) {
47226fa459cSmrg#define INIT_(N)                             \
47326fa459cSmrg    case N:                                  \
47426fa459cSmrg      StitchToPreviousBlockH ## N(           \
47526fa459cSmrg          &hasher->privat._H ## N,           \
47626fa459cSmrg          input_size, position, data, mask); \
47726fa459cSmrg    break;
47826fa459cSmrg    FOR_ALL_HASHERS(INIT_)
47926fa459cSmrg#undef INIT_
48026fa459cSmrg    default: break;
48126fa459cSmrg  }
48226fa459cSmrg}
48326fa459cSmrg
48426fa459cSmrg#if defined(__cplusplus) || defined(c_plusplus)
48526fa459cSmrg}  /* extern "C" */
48626fa459cSmrg#endif
48726fa459cSmrg
48826fa459cSmrg#endif  /* BROTLI_ENC_HASH_H_ */
489