1/* NOLINT(build/header_guard) */ 2/* Copyright 2018 Google Inc. All Rights Reserved. 3 4 Distributed under MIT license. 5 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 6*/ 7 8/* template parameters: FN, HASHER_A, HASHER_B */ 9 10/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A 11 and HASHER_B. */ 12 13#define HashComposite HASHER() 14 15#define FN_A(X) EXPAND_CAT(X, HASHER_A) 16#define FN_B(X) EXPAND_CAT(X, HASHER_B) 17 18static BROTLI_INLINE size_t FN(HashTypeLength)(void) { 19 size_t a = FN_A(HashTypeLength)(); 20 size_t b = FN_B(HashTypeLength)(); 21 return a > b ? a : b; 22} 23 24static BROTLI_INLINE size_t FN(StoreLookahead)(void) { 25 size_t a = FN_A(StoreLookahead)(); 26 size_t b = FN_B(StoreLookahead)(); 27 return a > b ? a : b; 28} 29 30typedef struct HashComposite { 31 HASHER_A ha; 32 HASHER_B hb; 33 HasherCommon hb_common; 34 35 /* Shortcuts. */ 36 void* extra; 37 HasherCommon* common; 38 39 BROTLI_BOOL fresh; 40 const BrotliEncoderParams* params; 41} HashComposite; 42 43static void FN(Initialize)(HasherCommon* common, 44 HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) { 45 self->common = common; 46 self->extra = common->extra; 47 48 self->hb_common = *self->common; 49 self->fresh = BROTLI_TRUE; 50 self->params = params; 51 /* TODO: Initialize of the hashers is defered to Prepare (and params 52 remembered here) because we don't get the one_shot and input_size params 53 here that are needed to know the memory size of them. Instead provide 54 those params to all hashers FN(Initialize) */ 55} 56 57static void FN(Prepare)( 58 HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot, 59 size_t input_size, const uint8_t* BROTLI_RESTRICT data) { 60 if (self->fresh) { 61 self->fresh = BROTLI_FALSE; 62 self->hb_common.extra = (uint8_t*)self->extra + 63 FN_A(HashMemAllocInBytes)(self->params, one_shot, input_size); 64 65 FN_A(Initialize)(self->common, &self->ha, self->params); 66 FN_B(Initialize)(&self->hb_common, &self->hb, self->params); 67 } 68 FN_A(Prepare)(&self->ha, one_shot, input_size, data); 69 FN_B(Prepare)(&self->hb, one_shot, input_size, data); 70} 71 72static BROTLI_INLINE size_t FN(HashMemAllocInBytes)( 73 const BrotliEncoderParams* params, BROTLI_BOOL one_shot, 74 size_t input_size) { 75 return FN_A(HashMemAllocInBytes)(params, one_shot, input_size) + 76 FN_B(HashMemAllocInBytes)(params, one_shot, input_size); 77} 78 79static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self, 80 const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { 81 FN_A(Store)(&self->ha, data, mask, ix); 82 FN_B(Store)(&self->hb, data, mask, ix); 83} 84 85static BROTLI_INLINE void FN(StoreRange)( 86 HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data, 87 const size_t mask, const size_t ix_start, 88 const size_t ix_end) { 89 FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end); 90 FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end); 91} 92 93static BROTLI_INLINE void FN(StitchToPreviousBlock)( 94 HashComposite* BROTLI_RESTRICT self, 95 size_t num_bytes, size_t position, const uint8_t* ringbuffer, 96 size_t ring_buffer_mask) { 97 FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position, 98 ringbuffer, ring_buffer_mask); 99 FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position, 100 ringbuffer, ring_buffer_mask); 101} 102 103static BROTLI_INLINE void FN(PrepareDistanceCache)( 104 HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) { 105 FN_A(PrepareDistanceCache)(&self->ha, distance_cache); 106 FN_B(PrepareDistanceCache)(&self->hb, distance_cache); 107} 108 109static BROTLI_INLINE void FN(FindLongestMatch)( 110 HashComposite* BROTLI_RESTRICT self, 111 const BrotliEncoderDictionary* dictionary, 112 const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, 113 const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, 114 const size_t max_length, const size_t max_backward, 115 const size_t dictionary_distance, const size_t max_distance, 116 HasherSearchResult* BROTLI_RESTRICT out) { 117 FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask, 118 distance_cache, cur_ix, max_length, max_backward, dictionary_distance, 119 max_distance, out); 120 FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask, 121 distance_cache, cur_ix, max_length, max_backward, dictionary_distance, 122 max_distance, out); 123} 124 125#undef HashComposite 126