1 /* NOLINT(build/header_guard) */
2 /* Copyright 2018 Google Inc. All Rights Reserved.
4 Distributed under MIT license.
5 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
8 /* template parameters: FN, HASHER_A, HASHER_B */
10 /* Composite hasher: This hasher allows to combine two other hashers, HASHER_A
13 #define HashComposite HASHER()
15 #define FN_A(X) EXPAND_CAT(X, HASHER_A)
16 #define FN_B(X) EXPAND_CAT(X, HASHER_B)
18 static BROTLI_INLINE
size_t FN(HashTypeLength
)(void) {
19 size_t a
= FN_A(HashTypeLength
)();
20 size_t b
= FN_B(HashTypeLength
)();
24 static BROTLI_INLINE
size_t FN(StoreLookahead
)(void) {
25 size_t a
= FN_A(StoreLookahead
)();
26 size_t b
= FN_B(StoreLookahead
)();
30 typedef struct HashComposite
{
33 const BrotliEncoderParams
* params
;
36 static BROTLI_INLINE HashComposite
* FN(Self
)(HasherHandle handle
) {
37 return (HashComposite
*)&(GetHasherCommon(handle
)[1]);
40 static void FN(Initialize
)(
41 HasherHandle handle
, const BrotliEncoderParams
* params
) {
42 HashComposite
* self
= FN(Self
)(handle
);
45 self
->params
= params
;
46 /* TODO: Initialize of the hashers is defered to Prepare (and params
47 remembered here) because we don't get the one_shot and input_size params
48 here that are needed to know the memory size of them. Instead provide
49 those params to all hashers FN(Initialize) */
52 static void FN(Prepare
)(HasherHandle handle
, BROTLI_BOOL one_shot
,
53 size_t input_size
, const uint8_t* data
) {
54 HashComposite
* self
= FN(Self
)(handle
);
56 HasherCommon
* common_a
;
57 HasherCommon
* common_b
;
59 self
->ha
= handle
+ sizeof(HasherCommon
) + sizeof(HashComposite
);
60 common_a
= (HasherCommon
*)self
->ha
;
61 common_a
->params
= self
->params
->hasher
;
62 common_a
->is_prepared_
= BROTLI_FALSE
;
63 common_a
->dict_num_lookups
= 0;
64 common_a
->dict_num_matches
= 0;
65 FN_A(Initialize
)(self
->ha
, self
->params
);
67 self
->hb
= self
->ha
+ sizeof(HasherCommon
) + FN_A(HashMemAllocInBytes
)(
68 self
->params
, one_shot
, input_size
);
69 common_b
= (HasherCommon
*)self
->hb
;
70 common_b
->params
= self
->params
->hasher
;
71 common_b
->is_prepared_
= BROTLI_FALSE
;
72 common_b
->dict_num_lookups
= 0;
73 common_b
->dict_num_matches
= 0;
74 FN_B(Initialize
)(self
->hb
, self
->params
);
76 FN_A(Prepare
)(self
->ha
, one_shot
, input_size
, data
);
77 FN_B(Prepare
)(self
->hb
, one_shot
, input_size
, data
);
80 static BROTLI_INLINE
size_t FN(HashMemAllocInBytes
)(
81 const BrotliEncoderParams
* params
, BROTLI_BOOL one_shot
,
83 return sizeof(HashComposite
) + 2 * sizeof(HasherCommon
) +
84 FN_A(HashMemAllocInBytes
)(params
, one_shot
, input_size
) +
85 FN_B(HashMemAllocInBytes
)(params
, one_shot
, input_size
);
88 static BROTLI_INLINE
void FN(Store
)(HasherHandle BROTLI_RESTRICT handle
,
89 const uint8_t* BROTLI_RESTRICT data
, const size_t mask
, const size_t ix
) {
90 HashComposite
* self
= FN(Self
)(handle
);
91 FN_A(Store
)(self
->ha
, data
, mask
, ix
);
92 FN_B(Store
)(self
->hb
, data
, mask
, ix
);
95 static BROTLI_INLINE
void FN(StoreRange
)(HasherHandle handle
,
96 const uint8_t* data
, const size_t mask
, const size_t ix_start
,
97 const size_t ix_end
) {
98 HashComposite
* self
= FN(Self
)(handle
);
99 FN_A(StoreRange
)(self
->ha
, data
, mask
, ix_start
, ix_end
);
100 FN_B(StoreRange
)(self
->hb
, data
, mask
, ix_start
, ix_end
);
103 static BROTLI_INLINE
void FN(StitchToPreviousBlock
)(HasherHandle handle
,
104 size_t num_bytes
, size_t position
, const uint8_t* ringbuffer
,
105 size_t ring_buffer_mask
) {
106 HashComposite
* self
= FN(Self
)(handle
);
107 FN_A(StitchToPreviousBlock
)(self
->ha
, num_bytes
, position
, ringbuffer
,
109 FN_B(StitchToPreviousBlock
)(self
->hb
, num_bytes
, position
, ringbuffer
,
113 static BROTLI_INLINE
void FN(PrepareDistanceCache
)(
114 HasherHandle handle
, int* BROTLI_RESTRICT distance_cache
) {
115 HashComposite
* self
= FN(Self
)(handle
);
116 FN_A(PrepareDistanceCache
)(self
->ha
, distance_cache
);
117 FN_B(PrepareDistanceCache
)(self
->hb
, distance_cache
);
120 static BROTLI_INLINE
void FN(FindLongestMatch
)(HasherHandle handle
,
121 const BrotliEncoderDictionary
* dictionary
,
122 const uint8_t* BROTLI_RESTRICT data
, const size_t ring_buffer_mask
,
123 const int* BROTLI_RESTRICT distance_cache
, const size_t cur_ix
,
124 const size_t max_length
, const size_t max_backward
, const size_t gap
,
125 const size_t max_distance
, HasherSearchResult
* BROTLI_RESTRICT out
) {
126 HashComposite
* self
= FN(Self
)(handle
);
127 FN_A(FindLongestMatch
)(self
->ha
, dictionary
, data
, ring_buffer_mask
,
128 distance_cache
, cur_ix
, max_length
, max_backward
, gap
, max_distance
, out
);
129 FN_B(FindLongestMatch
)(self
->hb
, dictionary
, data
, ring_buffer_mask
,
130 distance_cache
, cur_ix
, max_length
, max_backward
, gap
, max_distance
, out
);