blob: 1827ce6019a66fe8a7096cfc9c6806192698ca61 [file] [log] [blame]
Eugene Klyuchnikov771eb102015-11-27 11:27:11 +01001/* Copyright 2010 Google Inc. All Rights Reserved.
2
Eugene Klyuchnikov24ffa782015-12-11 11:11:51 +01003 Distributed under MIT license.
Eugene Klyuchnikov771eb102015-11-27 11:27:11 +01004 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5*/
6
Eugene Kliuchnikov352b0b22016-06-03 11:19:23 +02007/* A (forgetful) hash table to the data seen by the compressor, to
8 help create backward references to previous data. */
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +02009
10#ifndef BROTLI_ENC_HASH_H_
11#define BROTLI_ENC_HASH_H_
12
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +020013#include <string.h> /* memcmp, memset */
Eugene Kliuchnikov02829182016-06-03 10:51:04 +020014
Eugene Kliuchnikov20481892016-07-26 14:41:59 +020015#include "../common/constants.h"
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +020016#include "../common/dictionary.h"
Eugene Kliuchnikovda254cf2017-12-12 14:33:12 +010017#include "../common/platform.h"
Eugene Kliuchnikov81480012016-08-23 14:40:33 +020018#include <brotli/types.h>
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -050019#include "./encoder_dict.h"
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020020#include "./fast_log.h"
21#include "./find_match_length.h"
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +020022#include "./memory.h"
Eugene Kliuchnikov20481892016-07-26 14:41:59 +020023#include "./quality.h"
Zoltan Szabadkae7650082014-03-20 14:32:35 +010024#include "./static_dict.h"
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020025
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +020026#if defined(__cplusplus) || defined(c_plusplus)
27extern "C" {
28#endif
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020029
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +010030/* Pointer to hasher data.
31 *
32 * Excluding initialization and destruction, hasher can be passed as
33 * HasherHandle by value.
34 *
35 * Typically hasher data consists of 3 sections:
36 * * HasherCommon structure
37 * * private structured hasher data, depending on hasher type
38 * * private dynamic hasher data, depending on hasher type and parameters
39 */
40typedef uint8_t* HasherHandle;
41
42typedef struct {
43 BrotliHasherParams params;
44
45 /* False if hasher needs to be "prepared" before use. */
46 BROTLI_BOOL is_prepared_;
47
48 size_t dict_num_lookups;
49 size_t dict_num_matches;
50} HasherCommon;
51
52static BROTLI_INLINE HasherCommon* GetHasherCommon(HasherHandle handle) {
53 return (HasherCommon*)handle;
54}
55
Eugene Kliuchnikov20481892016-07-26 14:41:59 +020056#define score_t size_t
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +010057
Zoltan Szabadka8844b7f2016-01-07 16:27:49 +010058static const uint32_t kCutoffTransformsCount = 10;
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +010059/* 0, 12, 27, 23, 42, 63, 56, 48, 59, 64 */
60/* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */
61static const uint64_t kCutoffTransforms =
62 BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200);
Lode Vandevenne17ed2582015-08-10 13:13:58 +020063
Eugene Kliuchnikov20481892016-07-26 14:41:59 +020064typedef struct HasherSearchResult {
65 size_t len;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +020066 size_t distance;
67 score_t score;
Eugene Kliuchnikov52441062017-07-21 10:07:24 +020068 int len_code_delta; /* == len_code - len */
Eugene Kliuchnikov20481892016-07-26 14:41:59 +020069} HasherSearchResult;
70
Eugene Kliuchnikov352b0b22016-06-03 11:19:23 +020071/* kHashMul32 multiplier has these properties:
72 * The multiplier must be odd. Otherwise we may lose the highest bit.
Eugene Kliuchnikove9b278a2016-10-31 14:33:59 +010073 * No long streaks of ones or zeros.
Eugene Kliuchnikov352b0b22016-06-03 11:19:23 +020074 * There is no effort to ensure that it is a prime, the oddity is enough
75 for this use.
76 * The number has been tuned heuristically against compression benchmarks. */
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -050077static const uint32_t kHashMul32 = 0x1E35A7BD;
78static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1E35A7BD, 0x1E35A7BD);
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +010079static const uint64_t kHashMul64Long =
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -050080 BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020081
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +020082static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {
Eugene Kliuchnikovda254cf2017-12-12 14:33:12 +010083 uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
Eugene Kliuchnikov352b0b22016-06-03 11:19:23 +020084 /* The higher bits contain more mixture from the multiplication,
85 so we take our results from there. */
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +020086 return h >> (32 - 14);
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +020087}
88
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +010089static BROTLI_INLINE void PrepareDistanceCache(
90 int* BROTLI_RESTRICT distance_cache, const int num_distances) {
91 if (num_distances > 4) {
92 int last_distance = distance_cache[0];
93 distance_cache[4] = last_distance - 1;
94 distance_cache[5] = last_distance + 1;
95 distance_cache[6] = last_distance - 2;
96 distance_cache[7] = last_distance + 2;
97 distance_cache[8] = last_distance - 3;
98 distance_cache[9] = last_distance + 3;
99 if (num_distances > 10) {
100 int next_last_distance = distance_cache[1];
101 distance_cache[10] = next_last_distance - 1;
102 distance_cache[11] = next_last_distance + 1;
103 distance_cache[12] = next_last_distance - 2;
104 distance_cache[13] = next_last_distance + 2;
105 distance_cache[14] = next_last_distance - 3;
106 distance_cache[15] = next_last_distance + 3;
107 }
108 }
109}
110
111#define BROTLI_LITERAL_BYTE_SCORE 135
112#define BROTLI_DISTANCE_BIT_PENALTY 30
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200113/* Score must be positive after applying maximal penalty. */
114#define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t))
115
Eugene Kliuchnikov352b0b22016-06-03 11:19:23 +0200116/* Usually, we always choose the longest backward reference. This function
117 allows for the exception of that rule.
118
119 If we choose a backward reference that is further away, it will
120 usually be coded with more bits. We approximate this by assuming
121 log2(distance). If the distance can be expressed in terms of the
122 last four distances, we use some heuristic constants to estimate
123 the bits cost. For the first up to four literals we use the bit
124 cost of the literals from the literal cost model, after that we
125 use the average bit cost of the cost model.
126
127 This function is used to sometimes discard a longer backward reference
128 when it is not much longer and the bit cost for encoding it is more
129 than the saved literals.
130
131 backward_reference_offset MUST be positive. */
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200132static BROTLI_INLINE score_t BackwardReferenceScore(
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200133 size_t copy_length, size_t backward_reference_offset) {
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200134 return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length -
135 BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);
Zoltan Szabadkae7650082014-03-20 14:32:35 +0100136}
137
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200138static BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100139 size_t copy_length) {
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200140 return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100141 BROTLI_SCORE_BASE + 15;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200142}
143
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100144static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
145 size_t distance_short_code) {
146 return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE);
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200147}
148
149static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500150 const BrotliEncoderDictionary* dictionary, size_t item, const uint8_t* data,
151 size_t max_length, size_t max_backward, size_t max_distance,
152 HasherSearchResult* out) {
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200153 size_t len;
154 size_t dist;
155 size_t offset;
156 size_t matchlen;
157 size_t backward;
158 score_t score;
Eugene Kliuchnikov8d3fdc12017-01-26 11:32:18 +0100159 len = item & 0x1F;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200160 dist = item >> 5;
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500161 offset = dictionary->words->offsets_by_length[len] + len * dist;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200162 if (len > max_length) {
163 return BROTLI_FALSE;
164 }
165
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100166 matchlen =
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500167 FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);
168 if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200169 return BROTLI_FALSE;
170 }
171 {
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100172 size_t cut = len - matchlen;
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500173 size_t transform_id = (cut << 2) +
174 (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200175 backward = max_backward + dist + 1 +
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500176 (transform_id << dictionary->words->size_bits_by_length[len]);
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200177 }
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500178 if (backward > max_distance) {
Eugene Kliuchnikovd63e8f72017-08-04 10:02:56 +0200179 return BROTLI_FALSE;
180 }
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200181 score = BackwardReferenceScore(matchlen, backward);
182 if (score < out->score) {
183 return BROTLI_FALSE;
184 }
185 out->len = matchlen;
Eugene Kliuchnikov52441062017-07-21 10:07:24 +0200186 out->len_code_delta = (int)len - (int)matchlen;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200187 out->distance = backward;
188 out->score = score;
189 return BROTLI_TRUE;
190}
191
Eugene Kliuchnikov52441062017-07-21 10:07:24 +0200192static BROTLI_INLINE void SearchInStaticDictionary(
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500193 const BrotliEncoderDictionary* dictionary,
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100194 HasherHandle handle, const uint8_t* data, size_t max_length,
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500195 size_t max_backward, size_t max_distance,
196 HasherSearchResult* out, BROTLI_BOOL shallow) {
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200197 size_t key;
198 size_t i;
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100199 HasherCommon* self = GetHasherCommon(handle);
200 if (self->dict_num_matches < (self->dict_num_lookups >> 7)) {
Eugene Kliuchnikov52441062017-07-21 10:07:24 +0200201 return;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200202 }
203 key = Hash14(data) << 1;
Eugene Kliuchnikov0a63f992016-09-21 17:20:36 +0200204 for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500205 size_t item = dictionary->hash_table[key];
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100206 self->dict_num_lookups++;
207 if (item != 0) {
208 BROTLI_BOOL item_matches = TestStaticDictionaryItem(
Eugene Kliuchnikov35e69fc2018-02-26 09:04:36 -0500209 dictionary, item, data, max_length, max_backward, max_distance, out);
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100210 if (item_matches) {
211 self->dict_num_matches++;
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100212 }
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200213 }
214 }
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +0200215}
216
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200217typedef struct BackwardMatch {
Zoltan Szabadka8844b7f2016-01-07 16:27:49 +0100218 uint32_t distance;
219 uint32_t length_and_code;
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200220} BackwardMatch;
Zoltan Szabadkab3d37232015-06-12 16:25:41 +0200221
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200222static BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self,
223 size_t dist, size_t len) {
224 self->distance = (uint32_t)dist;
225 self->length_and_code = (uint32_t)(len << 5);
226}
Zoltan Szabadkab4f39bf2014-10-28 13:25:22 +0100227
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200228static BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self,
229 size_t dist, size_t len, size_t len_code) {
230 self->distance = (uint32_t)dist;
231 self->length_and_code =
232 (uint32_t)((len << 5) | (len == len_code ? 0 : len_code));
233}
234
235static BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) {
236 return self->length_and_code >> 5;
237}
238
239static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
240 size_t code = self->length_and_code & 31;
241 return code ? code : BackwardMatchLength(self);
242}
243
244#define EXPAND_CAT(a, b) CAT(a, b)
245#define CAT(a, b) a ## b
246#define FN(X) EXPAND_CAT(X, HASHER())
247
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200248#define HASHER() H10
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200249#define BUCKET_BITS 17
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100250#define MAX_TREE_SEARCH_DEPTH 64
251#define MAX_TREE_COMP_LENGTH 128
252#include "./hash_to_binary_tree_inc.h" /* NOLINT(build/include) */
253#undef MAX_TREE_SEARCH_DEPTH
254#undef MAX_TREE_COMP_LENGTH
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200255#undef BUCKET_BITS
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200256#undef HASHER
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100257/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */
258#define MAX_NUM_MATCHES_H10 128
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100259
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200260/* For BUCKET_SWEEP == 1, enabling the dictionary lookup makes compression
261 a little faster (0.5% - 1%) and it compresses 0.15% better on small text
Eugene Kliuchnikove9b278a2016-10-31 14:33:59 +0100262 and HTML inputs. */
Zoltan Szabadkab820c392016-03-15 10:50:16 +0100263
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200264#define HASHER() H2
265#define BUCKET_BITS 16
266#define BUCKET_SWEEP 1
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100267#define HASH_LEN 5
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200268#define USE_DICTIONARY 1
269#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
270#undef BUCKET_SWEEP
271#undef USE_DICTIONARY
272#undef HASHER
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100273
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200274#define HASHER() H3
275#define BUCKET_SWEEP 2
276#define USE_DICTIONARY 0
277#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
278#undef USE_DICTIONARY
279#undef BUCKET_SWEEP
280#undef BUCKET_BITS
281#undef HASHER
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100282
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200283#define HASHER() H4
284#define BUCKET_BITS 17
285#define BUCKET_SWEEP 4
286#define USE_DICTIONARY 1
287#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
288#undef USE_DICTIONARY
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100289#undef HASH_LEN
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200290#undef BUCKET_SWEEP
291#undef BUCKET_BITS
292#undef HASHER
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100293
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200294#define HASHER() H5
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200295#include "./hash_longest_match_inc.h" /* NOLINT(build/include) */
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200296#undef HASHER
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100297
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200298#define HASHER() H6
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100299#include "./hash_longest_match64_inc.h" /* NOLINT(build/include) */
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200300#undef HASHER
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100301
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200302#define BUCKET_BITS 15
303
304#define NUM_LAST_DISTANCES_TO_CHECK 4
305#define NUM_BANKS 1
306#define BANK_BITS 16
307#define HASHER() H40
308#include "./hash_forgetful_chain_inc.h" /* NOLINT(build/include) */
309#undef HASHER
310#undef NUM_LAST_DISTANCES_TO_CHECK
311
312#define NUM_LAST_DISTANCES_TO_CHECK 10
313#define HASHER() H41
314#include "./hash_forgetful_chain_inc.h" /* NOLINT(build/include) */
315#undef HASHER
316#undef NUM_LAST_DISTANCES_TO_CHECK
317#undef NUM_BANKS
318#undef BANK_BITS
319
320#define NUM_LAST_DISTANCES_TO_CHECK 16
321#define NUM_BANKS 512
322#define BANK_BITS 9
323#define HASHER() H42
324#include "./hash_forgetful_chain_inc.h" /* NOLINT(build/include) */
325#undef HASHER
326#undef NUM_LAST_DISTANCES_TO_CHECK
327#undef NUM_BANKS
328#undef BANK_BITS
329
330#undef BUCKET_BITS
331
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100332#define HASHER() H54
333#define BUCKET_BITS 20
334#define BUCKET_SWEEP 4
335#define HASH_LEN 7
336#define USE_DICTIONARY 0
337#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
338#undef USE_DICTIONARY
339#undef HASH_LEN
340#undef BUCKET_SWEEP
341#undef BUCKET_BITS
342#undef HASHER
343
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200344#undef FN
345#undef CAT
346#undef EXPAND_CAT
Zoltan Szabadkadbb53e62016-01-27 09:50:39 +0100347
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100348#define FOR_GENERIC_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200349#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
350
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100351static BROTLI_INLINE void DestroyHasher(
352 MemoryManager* m, HasherHandle* handle) {
353 if (*handle == NULL) return;
354 BROTLI_FREE(m, *handle);
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200355}
356
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100357static BROTLI_INLINE void HasherReset(HasherHandle handle) {
358 if (handle == NULL) return;
359 GetHasherCommon(handle)->is_prepared_ = BROTLI_FALSE;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200360}
361
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100362static BROTLI_INLINE size_t HasherSize(const BrotliEncoderParams* params,
363 BROTLI_BOOL one_shot, const size_t input_size) {
364 size_t result = sizeof(HasherCommon);
365 switch (params->hasher.type) {
366#define SIZE_(N) \
367 case N: \
368 result += HashMemAllocInBytesH ## N(params, one_shot, input_size); \
369 break;
370 FOR_ALL_HASHERS(SIZE_)
371#undef SIZE_
372 default:
373 break;
Eugene Kliuchnikov20481892016-07-26 14:41:59 +0200374 }
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100375 return result;
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200376}
377
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100378static BROTLI_INLINE void HasherSetup(MemoryManager* m, HasherHandle* handle,
379 BrotliEncoderParams* params, const uint8_t* data, size_t position,
380 size_t input_size, BROTLI_BOOL is_last) {
381 HasherHandle self = NULL;
382 HasherCommon* common = NULL;
383 BROTLI_BOOL one_shot = (position == 0 && is_last);
384 if (*handle == NULL) {
385 size_t alloc_size;
386 ChooseHasher(params, &params->hasher);
387 alloc_size = HasherSize(params, one_shot, input_size);
388 self = BROTLI_ALLOC(m, uint8_t, alloc_size);
389 if (BROTLI_IS_OOM(m)) return;
390 *handle = self;
391 common = GetHasherCommon(self);
392 common->params = params->hasher;
393 switch (common->params.type) {
394#define INITIALIZE_(N) \
395 case N: \
396 InitializeH ## N(*handle, params); \
397 break;
398 FOR_ALL_HASHERS(INITIALIZE_);
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100399#undef INITIALIZE_
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100400 default:
401 break;
402 }
403 HasherReset(*handle);
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100404 }
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200405
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100406 self = *handle;
407 common = GetHasherCommon(self);
408 if (!common->is_prepared_) {
409 switch (common->params.type) {
410#define PREPARE_(N) \
411 case N: \
412 PrepareH ## N(self, one_shot, input_size, data); \
413 break;
414 FOR_ALL_HASHERS(PREPARE_)
415#undef PREPARE_
416 default: break;
417 }
418 if (position == 0) {
419 common->dict_num_lookups = 0;
420 common->dict_num_matches = 0;
421 }
422 common->is_prepared_ = BROTLI_TRUE;
423 }
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200424}
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200425
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100426static BROTLI_INLINE void InitOrStitchToPreviousBlock(
Eugene Kliuchnikovcdca91b2017-03-06 14:22:45 +0100427 MemoryManager* m, HasherHandle* handle, const uint8_t* data, size_t mask,
428 BrotliEncoderParams* params, size_t position, size_t input_size,
429 BROTLI_BOOL is_last) {
430 HasherHandle self;
431 HasherSetup(m, handle, params, data, position, input_size, is_last);
432 if (BROTLI_IS_OOM(m)) return;
433 self = *handle;
434 switch (GetHasherCommon(self)->params.type) {
435#define INIT_(N) \
436 case N: \
437 StitchToPreviousBlockH ## N(self, input_size, position, data, mask); \
Eugene Kliuchnikov11df8432017-02-06 14:20:43 +0100438 break;
439 FOR_ALL_HASHERS(INIT_)
440#undef INIT_
441 default: break;
442 }
443}
444
Eugene Kliuchnikovb972c672016-06-13 11:01:04 +0200445#if defined(__cplusplus) || defined(c_plusplus)
446} /* extern "C" */
447#endif
Zoltan Szabadkac66e4e32013-10-23 13:06:13 +0200448
Eugene Kliuchnikov352b0b22016-06-03 11:19:23 +0200449#endif /* BROTLI_ENC_HASH_H_ */