brotli 0.2.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +34 -0
  3. data/.github/workflows/publish.yml +34 -0
  4. data/Gemfile +6 -3
  5. data/Rakefile +16 -9
  6. data/brotli.gemspec +7 -13
  7. data/ext/brotli/brotli.c +209 -31
  8. data/ext/brotli/buffer.c +1 -7
  9. data/ext/brotli/buffer.h +1 -1
  10. data/ext/brotli/extconf.rb +20 -18
  11. data/lib/brotli/version.rb +1 -1
  12. data/test/brotli_test.rb +104 -0
  13. data/test/brotli_writer_test.rb +36 -0
  14. data/test/test_helper.rb +8 -0
  15. data/vendor/brotli/c/common/constants.c +15 -0
  16. data/vendor/brotli/c/common/constants.h +136 -0
  17. data/vendor/brotli/c/common/context.c +156 -0
  18. data/vendor/brotli/c/common/context.h +4 -152
  19. data/vendor/brotli/c/common/dictionary.bin.br +0 -0
  20. data/vendor/brotli/c/common/dictionary.c +10 -1
  21. data/vendor/brotli/c/common/platform.c +22 -0
  22. data/vendor/brotli/c/common/platform.h +43 -17
  23. data/vendor/brotli/c/common/transform.c +59 -3
  24. data/vendor/brotli/c/common/transform.h +5 -0
  25. data/vendor/brotli/c/common/version.h +2 -2
  26. data/vendor/brotli/c/dec/bit_reader.c +28 -0
  27. data/vendor/brotli/c/dec/bit_reader.h +58 -16
  28. data/vendor/brotli/c/dec/decode.c +353 -251
  29. data/vendor/brotli/c/dec/huffman.h +6 -12
  30. data/vendor/brotli/c/dec/prefix.h +0 -18
  31. data/vendor/brotli/c/dec/state.c +9 -14
  32. data/vendor/brotli/c/dec/state.h +144 -37
  33. data/vendor/brotli/c/enc/backward_references.c +8 -7
  34. data/vendor/brotli/c/enc/backward_references.h +5 -4
  35. data/vendor/brotli/c/enc/backward_references_hq.c +51 -33
  36. data/vendor/brotli/c/enc/backward_references_hq.h +11 -8
  37. data/vendor/brotli/c/enc/backward_references_inc.h +24 -14
  38. data/vendor/brotli/c/enc/block_splitter.c +3 -3
  39. data/vendor/brotli/c/enc/block_splitter_inc.h +15 -6
  40. data/vendor/brotli/c/enc/brotli_bit_stream.c +13 -30
  41. data/vendor/brotli/c/enc/cluster_inc.h +6 -3
  42. data/vendor/brotli/c/enc/command.c +28 -0
  43. data/vendor/brotli/c/enc/command.h +12 -12
  44. data/vendor/brotli/c/enc/compress_fragment_two_pass.c +1 -1
  45. data/vendor/brotli/c/enc/dictionary_hash.c +1826 -1100
  46. data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
  47. data/vendor/brotli/c/enc/encode.c +104 -39
  48. data/vendor/brotli/c/enc/encoder_dict.c +3 -2
  49. data/vendor/brotli/c/enc/encoder_dict.h +3 -1
  50. data/vendor/brotli/c/enc/entropy_encode.c +2 -0
  51. data/vendor/brotli/c/enc/entropy_encode.h +2 -2
  52. data/vendor/brotli/c/enc/fast_log.c +105 -0
  53. data/vendor/brotli/c/enc/fast_log.h +19 -100
  54. data/vendor/brotli/c/enc/find_match_length.h +2 -3
  55. data/vendor/brotli/c/enc/hash.h +80 -90
  56. data/vendor/brotli/c/enc/hash_composite_inc.h +52 -63
  57. data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +88 -49
  58. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +50 -50
  59. data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -50
  60. data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +91 -60
  61. data/vendor/brotli/c/enc/hash_rolling_inc.h +23 -27
  62. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +39 -38
  63. data/vendor/brotli/c/enc/memory.h +24 -12
  64. data/vendor/brotli/c/enc/metablock.c +23 -27
  65. data/vendor/brotli/c/enc/metablock_inc.h +1 -1
  66. data/vendor/brotli/c/enc/params.h +3 -1
  67. data/vendor/brotli/c/enc/ringbuffer.h +4 -1
  68. data/vendor/brotli/c/enc/utf8_util.c +1 -1
  69. data/vendor/brotli/c/enc/write_bits.h +27 -25
  70. data/vendor/brotli/c/include/brotli/encode.h +22 -1
  71. data/vendor/brotli/c/include/brotli/port.h +14 -0
  72. metadata +17 -97
  73. data/.travis.yml +0 -31
  74. data/docs/Brotli.html +0 -485
  75. data/docs/Brotli/Error.html +0 -124
  76. data/docs/_index.html +0 -122
  77. data/docs/class_list.html +0 -51
  78. data/docs/css/common.css +0 -1
  79. data/docs/css/full_list.css +0 -58
  80. data/docs/css/style.css +0 -496
  81. data/docs/file.README.html +0 -127
  82. data/docs/file_list.html +0 -56
  83. data/docs/frames.html +0 -17
  84. data/docs/index.html +0 -127
  85. data/docs/js/app.js +0 -292
  86. data/docs/js/full_list.js +0 -216
  87. data/docs/js/jquery.js +0 -4
  88. data/docs/method_list.html +0 -67
  89. data/docs/top-level-namespace.html +0 -110
  90. data/spec/brotli_spec.rb +0 -88
  91. data/spec/inflate_spec.rb +0 -75
  92. data/spec/spec_helper.rb +0 -4
@@ -20,7 +20,8 @@ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }
20
20
  static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }
21
21
 
22
22
  /* HashBytes is the function that chooses the bucket to place the address in. */
23
- static uint32_t FN(HashBytes)(const uint8_t* data, const int shift) {
23
+ static uint32_t FN(HashBytes)(
24
+ const uint8_t* BROTLI_RESTRICT data, const int shift) {
24
25
  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
25
26
  /* The higher bits contain more mixture from the multiplication,
26
27
  so we take our results from there. */
@@ -38,42 +39,46 @@ typedef struct HashLongestMatch {
38
39
  /* Mask for accessing entries in a block (in a ring-buffer manner). */
39
40
  uint32_t block_mask_;
40
41
 
42
+ int block_bits_;
43
+ int num_last_distances_to_check_;
44
+
45
+ /* Shortcuts. */
46
+ HasherCommon* common_;
47
+
41
48
  /* --- Dynamic size members --- */
42
49
 
43
50
  /* Number of entries in a particular bucket. */
44
- /* uint16_t num[bucket_size]; */
51
+ uint16_t* num_; /* uint16_t[bucket_size]; */
45
52
 
46
53
  /* Buckets containing block_size_ of backward references. */
47
- /* uint32_t* buckets[bucket_size * block_size]; */
54
+ uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */
48
55
  } HashLongestMatch;
49
56
 
50
- static BROTLI_INLINE HashLongestMatch* FN(Self)(HasherHandle handle) {
51
- return (HashLongestMatch*)&(GetHasherCommon(handle)[1]);
52
- }
53
-
54
- static BROTLI_INLINE uint16_t* FN(Num)(HashLongestMatch* self) {
55
- return (uint16_t*)(&self[1]);
56
- }
57
-
58
- static BROTLI_INLINE uint32_t* FN(Buckets)(HashLongestMatch* self) {
59
- return (uint32_t*)(&FN(Num)(self)[self->bucket_size_]);
57
+ static BROTLI_INLINE uint16_t* FN(Num)(void* extra) {
58
+ return (uint16_t*)extra;
60
59
  }
61
60
 
62
61
  static void FN(Initialize)(
63
- HasherHandle handle, const BrotliEncoderParams* params) {
64
- HasherCommon* common = GetHasherCommon(handle);
65
- HashLongestMatch* self = FN(Self)(handle);
62
+ HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,
63
+ const BrotliEncoderParams* params) {
64
+ self->common_ = common;
65
+
66
66
  BROTLI_UNUSED(params);
67
67
  self->hash_shift_ = 32 - common->params.bucket_bits;
68
68
  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;
69
69
  self->block_size_ = (size_t)1 << common->params.block_bits;
70
70
  self->block_mask_ = (uint32_t)(self->block_size_ - 1);
71
+ self->num_ = (uint16_t*)common->extra;
72
+ self->buckets_ = (uint32_t*)(&self->num_[self->bucket_size_]);
73
+ self->block_bits_ = common->params.block_bits;
74
+ self->num_last_distances_to_check_ =
75
+ common->params.num_last_distances_to_check;
71
76
  }
72
77
 
73
- static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
74
- size_t input_size, const uint8_t* data) {
75
- HashLongestMatch* self = FN(Self)(handle);
76
- uint16_t* num = FN(Num)(self);
78
+ static void FN(Prepare)(
79
+ HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
80
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
81
+ uint16_t* BROTLI_RESTRICT num = self->num_;
77
82
  /* Partial preparation is 100 times slower (per socket). */
78
83
  size_t partial_prepare_threshold = self->bucket_size_ >> 6;
79
84
  if (one_shot && input_size <= partial_prepare_threshold) {
@@ -94,49 +99,49 @@ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
94
99
  size_t block_size = (size_t)1 << params->hasher.block_bits;
95
100
  BROTLI_UNUSED(one_shot);
96
101
  BROTLI_UNUSED(input_size);
97
- return sizeof(HashLongestMatch) + bucket_size * (2 + 4 * block_size);
102
+ return sizeof(uint16_t) * bucket_size +
103
+ sizeof(uint32_t) * bucket_size * block_size;
98
104
  }
99
105
 
100
106
  /* Look at 4 bytes at &data[ix & mask].
101
107
  Compute a hash from these, and store the value of ix at that position. */
102
- static BROTLI_INLINE void FN(Store)(HasherHandle handle, const uint8_t* data,
108
+ static BROTLI_INLINE void FN(Store)(
109
+ HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
103
110
  const size_t mask, const size_t ix) {
104
- HashLongestMatch* self = FN(Self)(handle);
105
- uint16_t* num = FN(Num)(self);
106
111
  const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_shift_);
107
- const size_t minor_ix = num[key] & self->block_mask_;
108
- const size_t offset =
109
- minor_ix + (key << GetHasherCommon(handle)->params.block_bits);
110
- FN(Buckets)(self)[offset] = (uint32_t)ix;
111
- ++num[key];
112
+ const size_t minor_ix = self->num_[key] & self->block_mask_;
113
+ const size_t offset = minor_ix + (key << self->block_bits_);
114
+ self->buckets_[offset] = (uint32_t)ix;
115
+ ++self->num_[key];
112
116
  }
113
117
 
114
- static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle,
115
- const uint8_t* data, const size_t mask, const size_t ix_start,
116
- const size_t ix_end) {
118
+ static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,
119
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask,
120
+ const size_t ix_start, const size_t ix_end) {
117
121
  size_t i;
118
122
  for (i = ix_start; i < ix_end; ++i) {
119
- FN(Store)(handle, data, mask, i);
123
+ FN(Store)(self, data, mask, i);
120
124
  }
121
125
  }
122
126
 
123
- static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle,
127
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
128
+ HashLongestMatch* BROTLI_RESTRICT self,
124
129
  size_t num_bytes, size_t position, const uint8_t* ringbuffer,
125
130
  size_t ringbuffer_mask) {
126
131
  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
127
132
  /* Prepare the hashes for three last bytes of the last write.
128
133
  These could not be calculated before, since they require knowledge
129
134
  of both the previous and the current block. */
130
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 3);
131
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 2);
132
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 1);
135
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);
136
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);
137
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);
133
138
  }
134
139
  }
135
140
 
136
141
  static BROTLI_INLINE void FN(PrepareDistanceCache)(
137
- HasherHandle handle, int* BROTLI_RESTRICT distance_cache) {
138
- PrepareDistanceCache(distance_cache,
139
- GetHasherCommon(handle)->params.num_last_distances_to_check);
142
+ HashLongestMatch* BROTLI_RESTRICT self,
143
+ int* BROTLI_RESTRICT distance_cache) {
144
+ PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);
140
145
  }
141
146
 
142
147
  /* Find a longest backward match of &data[cur_ix] up to the length of
@@ -150,17 +155,16 @@ static BROTLI_INLINE void FN(PrepareDistanceCache)(
150
155
  Does not look for matches further away than max_backward.
151
156
  Writes the best match into |out|.
152
157
  |out|->score is updated only if a better match is found. */
153
- static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
158
+ static BROTLI_INLINE void FN(FindLongestMatch)(
159
+ HashLongestMatch* BROTLI_RESTRICT self,
154
160
  const BrotliEncoderDictionary* dictionary,
155
161
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
156
162
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
157
163
  const size_t max_length, const size_t max_backward,
158
- const size_t gap, const size_t max_distance,
164
+ const size_t dictionary_distance, const size_t max_distance,
159
165
  HasherSearchResult* BROTLI_RESTRICT out) {
160
- HasherCommon* common = GetHasherCommon(handle);
161
- HashLongestMatch* self = FN(Self)(handle);
162
- uint16_t* num = FN(Num)(self);
163
- uint32_t* buckets = FN(Buckets)(self);
166
+ uint16_t* BROTLI_RESTRICT num = self->num_;
167
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
164
168
  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
165
169
  /* Don't accept a short copy from far away. */
166
170
  score_t min_score = out->score;
@@ -170,7 +174,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
170
174
  out->len = 0;
171
175
  out->len_code_delta = 0;
172
176
  /* Try last distance first. */
173
- for (i = 0; i < (size_t)common->params.num_last_distances_to_check; ++i) {
177
+ for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
174
178
  const size_t backward = (size_t)distance_cache[i];
175
179
  size_t prev_ix = (size_t)(cur_ix - backward);
176
180
  if (prev_ix >= cur_ix) {
@@ -211,8 +215,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
211
215
  {
212
216
  const uint32_t key =
213
217
  FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);
214
- uint32_t* BROTLI_RESTRICT bucket =
215
- &buckets[key << common->params.block_bits];
218
+ uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
216
219
  const size_t down =
217
220
  (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0u;
218
221
  for (i = num[key]; i > down;) {
@@ -251,7 +254,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
251
254
  }
252
255
  if (min_score == out->score) {
253
256
  SearchInStaticDictionary(dictionary,
254
- handle, &data[cur_ix_masked], max_length, max_backward + gap,
257
+ self->common_, &data[cur_ix_masked], max_length, dictionary_distance,
255
258
  max_distance, out, BROTLI_FALSE);
256
259
  }
257
260
  }
@@ -5,15 +5,16 @@
5
5
  See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6
6
  */
7
7
 
8
- /* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP, HASH_LEN,
8
+ /* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN,
9
9
  USE_DICTIONARY
10
10
  */
11
11
 
12
12
  #define HashLongestMatchQuickly HASHER()
13
13
 
14
14
  #define BUCKET_SIZE (1 << BUCKET_BITS)
15
-
16
- #define HASH_MAP_SIZE (4 << BUCKET_BITS)
15
+ #define BUCKET_MASK (BUCKET_SIZE - 1)
16
+ #define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS)
17
+ #define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3)
17
18
 
18
19
  static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }
19
20
  static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }
@@ -32,39 +33,50 @@ static uint32_t FN(HashBytes)(const uint8_t* data) {
32
33
  /* A (forgetful) hash table to the data seen by the compressor, to
33
34
  help create backward references to previous data.
34
35
 
35
- This is a hash map of fixed size (BUCKET_SIZE). Starting from the
36
- given index, BUCKET_SWEEP buckets are used to store values of a key. */
36
+ This is a hash map of fixed size (BUCKET_SIZE). */
37
37
  typedef struct HashLongestMatchQuickly {
38
- uint32_t buckets_[BUCKET_SIZE + BUCKET_SWEEP];
39
- } HashLongestMatchQuickly;
38
+ /* Shortcuts. */
39
+ HasherCommon* common;
40
40
 
41
- static BROTLI_INLINE HashLongestMatchQuickly* FN(Self)(HasherHandle handle) {
42
- return (HashLongestMatchQuickly*)&(GetHasherCommon(handle)[1]);
43
- }
41
+ /* --- Dynamic size members --- */
42
+
43
+ uint32_t* buckets_; /* uint32_t[BUCKET_SIZE]; */
44
+ } HashLongestMatchQuickly;
44
45
 
45
46
  static void FN(Initialize)(
46
- HasherHandle handle, const BrotliEncoderParams* params) {
47
- BROTLI_UNUSED(handle);
47
+ HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self,
48
+ const BrotliEncoderParams* params) {
49
+ self->common = common;
50
+
48
51
  BROTLI_UNUSED(params);
52
+ self->buckets_ = (uint32_t*)common->extra;
49
53
  }
50
54
 
51
- static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
52
- size_t input_size, const uint8_t* data) {
53
- HashLongestMatchQuickly* self = FN(Self)(handle);
55
+ static void FN(Prepare)(
56
+ HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
57
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
58
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
54
59
  /* Partial preparation is 100 times slower (per socket). */
55
- size_t partial_prepare_threshold = HASH_MAP_SIZE >> 7;
60
+ size_t partial_prepare_threshold = BUCKET_SIZE >> 5;
56
61
  if (one_shot && input_size <= partial_prepare_threshold) {
57
62
  size_t i;
58
63
  for (i = 0; i < input_size; ++i) {
59
64
  const uint32_t key = FN(HashBytes)(&data[i]);
60
- memset(&self->buckets_[key], 0, BUCKET_SWEEP * sizeof(self->buckets_[0]));
65
+ if (BUCKET_SWEEP == 1) {
66
+ buckets[key] = 0;
67
+ } else {
68
+ uint32_t j;
69
+ for (j = 0; j < BUCKET_SWEEP; ++j) {
70
+ buckets[(key + (j << 3)) & BUCKET_MASK] = 0;
71
+ }
72
+ }
61
73
  }
62
74
  } else {
63
75
  /* It is not strictly necessary to fill this buffer here, but
64
76
  not filling will make the results of the compression stochastic
65
77
  (but correct). This is because random data would cause the
66
78
  system to find accidentally good backward references here and there. */
67
- memset(&self->buckets_[0], 0, sizeof(self->buckets_));
79
+ memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE);
68
80
  }
69
81
  }
70
82
 
@@ -74,45 +86,53 @@ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
74
86
  BROTLI_UNUSED(params);
75
87
  BROTLI_UNUSED(one_shot);
76
88
  BROTLI_UNUSED(input_size);
77
- return sizeof(HashLongestMatchQuickly);
89
+ return sizeof(uint32_t) * BUCKET_SIZE;
78
90
  }
79
91
 
80
92
  /* Look at 5 bytes at &data[ix & mask].
81
93
  Compute a hash from these, and store the value somewhere within
82
94
  [ix .. ix+3]. */
83
- static BROTLI_INLINE void FN(Store)(HasherHandle handle,
84
- const uint8_t* data, const size_t mask, const size_t ix) {
95
+ static BROTLI_INLINE void FN(Store)(
96
+ HashLongestMatchQuickly* BROTLI_RESTRICT self,
97
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
85
98
  const uint32_t key = FN(HashBytes)(&data[ix & mask]);
86
- /* Wiggle the value with the bucket sweep range. */
87
- const uint32_t off = (ix >> 3) % BUCKET_SWEEP;
88
- FN(Self)(handle)->buckets_[key + off] = (uint32_t)ix;
99
+ if (BUCKET_SWEEP == 1) {
100
+ self->buckets_[key] = (uint32_t)ix;
101
+ } else {
102
+ /* Wiggle the value with the bucket sweep range. */
103
+ const uint32_t off = ix & BUCKET_SWEEP_MASK;
104
+ self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix;
105
+ }
89
106
  }
90
107
 
91
- static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle,
92
- const uint8_t* data, const size_t mask, const size_t ix_start,
93
- const size_t ix_end) {
108
+ static BROTLI_INLINE void FN(StoreRange)(
109
+ HashLongestMatchQuickly* BROTLI_RESTRICT self,
110
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask,
111
+ const size_t ix_start, const size_t ix_end) {
94
112
  size_t i;
95
113
  for (i = ix_start; i < ix_end; ++i) {
96
- FN(Store)(handle, data, mask, i);
114
+ FN(Store)(self, data, mask, i);
97
115
  }
98
116
  }
99
117
 
100
118
  static BROTLI_INLINE void FN(StitchToPreviousBlock)(
101
- HasherHandle handle, size_t num_bytes, size_t position,
119
+ HashLongestMatchQuickly* BROTLI_RESTRICT self,
120
+ size_t num_bytes, size_t position,
102
121
  const uint8_t* ringbuffer, size_t ringbuffer_mask) {
103
122
  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
104
123
  /* Prepare the hashes for three last bytes of the last write.
105
124
  These could not be calculated before, since they require knowledge
106
125
  of both the previous and the current block. */
107
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 3);
108
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 2);
109
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 1);
126
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);
127
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);
128
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);
110
129
  }
111
130
  }
112
131
 
113
132
  static BROTLI_INLINE void FN(PrepareDistanceCache)(
114
- HasherHandle handle, int* BROTLI_RESTRICT distance_cache) {
115
- BROTLI_UNUSED(handle);
133
+ HashLongestMatchQuickly* BROTLI_RESTRICT self,
134
+ int* BROTLI_RESTRICT distance_cache) {
135
+ BROTLI_UNUSED(self);
116
136
  BROTLI_UNUSED(distance_cache);
117
137
  }
118
138
 
@@ -125,17 +145,19 @@ static BROTLI_INLINE void FN(PrepareDistanceCache)(
125
145
  Writes the best match into |out|.
126
146
  |out|->score is updated only if a better match is found. */
127
147
  static BROTLI_INLINE void FN(FindLongestMatch)(
128
- HasherHandle handle, const BrotliEncoderDictionary* dictionary,
148
+ HashLongestMatchQuickly* BROTLI_RESTRICT self,
149
+ const BrotliEncoderDictionary* dictionary,
129
150
  const uint8_t* BROTLI_RESTRICT data,
130
151
  const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,
131
152
  const size_t cur_ix, const size_t max_length, const size_t max_backward,
132
- const size_t gap, const size_t max_distance,
153
+ const size_t dictionary_distance, const size_t max_distance,
133
154
  HasherSearchResult* BROTLI_RESTRICT out) {
134
- HashLongestMatchQuickly* self = FN(Self)(handle);
155
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
135
156
  const size_t best_len_in = out->len;
136
157
  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
137
- const uint32_t key = FN(HashBytes)(&data[cur_ix_masked]);
138
158
  int compare_char = data[cur_ix_masked + best_len_in];
159
+ size_t key = FN(HashBytes)(&data[cur_ix_masked]);
160
+ size_t key_out;
139
161
  score_t min_score = out->score;
140
162
  score_t best_score = out->score;
141
163
  size_t best_len = best_len_in;
@@ -145,21 +167,21 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
145
167
  if (prev_ix < cur_ix) {
146
168
  prev_ix &= (uint32_t)ring_buffer_mask;
147
169
  if (compare_char == data[prev_ix + best_len]) {
148
- size_t len = FindMatchLengthWithLimit(&data[prev_ix],
149
- &data[cur_ix_masked],
150
- max_length);
170
+ const size_t len = FindMatchLengthWithLimit(
171
+ &data[prev_ix], &data[cur_ix_masked], max_length);
151
172
  if (len >= 4) {
152
173
  const score_t score = BackwardReferenceScoreUsingLastDistance(len);
153
174
  if (best_score < score) {
154
- best_score = score;
155
- best_len = len;
156
175
  out->len = len;
157
176
  out->distance = cached_backward;
158
- out->score = best_score;
159
- compare_char = data[cur_ix_masked + best_len];
177
+ out->score = score;
160
178
  if (BUCKET_SWEEP == 1) {
161
- self->buckets_[key] = (uint32_t)cur_ix;
179
+ buckets[key] = (uint32_t)cur_ix;
162
180
  return;
181
+ } else {
182
+ best_len = len;
183
+ best_score = score;
184
+ compare_char = data[cur_ix_masked + len];
163
185
  }
164
186
  }
165
187
  }
@@ -169,8 +191,8 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
169
191
  size_t backward;
170
192
  size_t len;
171
193
  /* Only one to look for, don't bother to prepare for a loop. */
172
- prev_ix = self->buckets_[key];
173
- self->buckets_[key] = (uint32_t)cur_ix;
194
+ prev_ix = buckets[key];
195
+ buckets[key] = (uint32_t)cur_ix;
174
196
  backward = cur_ix - prev_ix;
175
197
  prev_ix &= (uint32_t)ring_buffer_mask;
176
198
  if (compare_char != data[prev_ix + best_len_in]) {
@@ -192,12 +214,17 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
192
214
  }
193
215
  }
194
216
  } else {
195
- uint32_t* bucket = self->buckets_ + key;
196
- int i;
197
- prev_ix = *bucket++;
198
- for (i = 0; i < BUCKET_SWEEP; ++i, prev_ix = *bucket++) {
199
- const size_t backward = cur_ix - prev_ix;
217
+ size_t keys[BUCKET_SWEEP];
218
+ size_t i;
219
+ for (i = 0; i < BUCKET_SWEEP; ++i) {
220
+ keys[i] = (key + (i << 3)) & BUCKET_MASK;
221
+ }
222
+ key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3];
223
+ for (i = 0; i < BUCKET_SWEEP; ++i) {
200
224
  size_t len;
225
+ size_t backward;
226
+ prev_ix = buckets[keys[i]];
227
+ backward = cur_ix - prev_ix;
201
228
  prev_ix &= (uint32_t)ring_buffer_mask;
202
229
  if (compare_char != data[prev_ix + best_len]) {
203
230
  continue;
@@ -211,25 +238,29 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
211
238
  if (len >= 4) {
212
239
  const score_t score = BackwardReferenceScore(len, backward);
213
240
  if (best_score < score) {
214
- best_score = score;
215
241
  best_len = len;
216
- out->len = best_len;
217
- out->distance = backward;
242
+ out->len = len;
243
+ compare_char = data[cur_ix_masked + len];
244
+ best_score = score;
218
245
  out->score = score;
219
- compare_char = data[cur_ix_masked + best_len];
246
+ out->distance = backward;
220
247
  }
221
248
  }
222
249
  }
223
250
  }
224
251
  if (USE_DICTIONARY && min_score == out->score) {
225
252
  SearchInStaticDictionary(dictionary,
226
- handle, &data[cur_ix_masked], max_length, max_backward + gap,
253
+ self->common, &data[cur_ix_masked], max_length, dictionary_distance,
227
254
  max_distance, out, BROTLI_TRUE);
228
255
  }
229
- self->buckets_[key + ((cur_ix >> 3) % BUCKET_SWEEP)] = (uint32_t)cur_ix;
256
+ if (BUCKET_SWEEP != 1) {
257
+ buckets[key_out] = (uint32_t)cur_ix;
258
+ }
230
259
  }
231
260
 
232
- #undef HASH_MAP_SIZE
261
+ #undef BUCKET_SWEEP_MASK
262
+ #undef BUCKET_SWEEP
263
+ #undef BUCKET_MASK
233
264
  #undef BUCKET_SIZE
234
265
 
235
266
  #undef HashLongestMatchQuickly