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