| 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 |  | 
| 18 | static 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 |  | 
| 24 | static 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 |  | 
| 30 | typedef struct HashComposite { | 
| 31 |   HasherHandle ha; | 
| 32 |   HasherHandle hb; | 
| 33 |   const BrotliEncoderParams* params; | 
| 34 | } HashComposite; | 
| 35 |  | 
| 36 | static BROTLI_INLINE HashComposite* FN(Self)(HasherHandle handle) { | 
| 37 |   return (HashComposite*)&(GetHasherCommon(handle)[1]); | 
| 38 | } | 
| 39 |  | 
| 40 | static void FN(Initialize)( | 
| 41 |     HasherHandle handle, const BrotliEncoderParams* params) { | 
| 42 |   HashComposite* self = FN(Self)(handle); | 
| 43 |   self->ha = 0; | 
| 44 |   self->hb = 0; | 
| 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) */ | 
| 50 | } | 
| 51 |  | 
| 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); | 
| 55 |   if (!self->ha) { | 
| 56 |     HasherCommon* common_a; | 
| 57 |     HasherCommon* common_b; | 
| 58 |  | 
| 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); | 
| 66 |  | 
| 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); | 
| 75 |   } | 
| 76 |   FN_A(Prepare)(self->ha, one_shot, input_size, data); | 
| 77 |   FN_B(Prepare)(self->hb, one_shot, input_size, data); | 
| 78 | } | 
| 79 |  | 
| 80 | static BROTLI_INLINE size_t FN(HashMemAllocInBytes)( | 
| 81 |     const BrotliEncoderParams* params, BROTLI_BOOL one_shot, | 
| 82 |     size_t input_size) { | 
| 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); | 
| 86 | } | 
| 87 |  | 
| 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); | 
| 93 | } | 
| 94 |  | 
| 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); | 
| 101 | } | 
| 102 |  | 
| 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, | 
| 108 |       ring_buffer_mask); | 
| 109 |   FN_B(StitchToPreviousBlock)(self->hb, num_bytes, position, ringbuffer, | 
| 110 |       ring_buffer_mask); | 
| 111 | } | 
| 112 |  | 
| 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); | 
| 118 | } | 
| 119 |  | 
| 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, | 
| 125 |     const size_t gap, const size_t max_distance, | 
| 126 |     HasherSearchResult* BROTLI_RESTRICT out) { | 
| 127 |   HashComposite* self = FN(Self)(handle); | 
| 128 |   FN_A(FindLongestMatch)(self->ha, dictionary, data, ring_buffer_mask, | 
| 129 |       distance_cache, cur_ix, max_length, max_backward, gap, | 
| 130 |       max_distance, out); | 
| 131 |   FN_B(FindLongestMatch)(self->hb, dictionary, data, ring_buffer_mask, | 
| 132 |       distance_cache, cur_ix, max_length, max_backward, gap, | 
| 133 |       max_distance, out); | 
| 134 | } | 
| 135 |  | 
| 136 | #undef HashComposite | 
| 137 |  |