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
@@ -28,20 +28,25 @@ static BROTLI_INLINE size_t FN(StoreLookahead)(void) {
28
28
  }
29
29
 
30
30
  typedef struct HashComposite {
31
- HasherHandle ha;
32
- HasherHandle hb;
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;
33
40
  const BrotliEncoderParams* params;
34
41
  } HashComposite;
35
42
 
36
- static BROTLI_INLINE HashComposite* FN(Self)(HasherHandle handle) {
37
- return (HashComposite*)&(GetHasherCommon(handle)[1]);
38
- }
43
+ static void FN(Initialize)(HasherCommon* common,
44
+ HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {
45
+ self->common = common;
46
+ self->extra = common->extra;
39
47
 
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;
48
+ self->hb_common = *self->common;
49
+ self->fresh = BROTLI_TRUE;
45
50
  self->params = params;
46
51
  /* TODO: Initialize of the hashers is defered to Prepare (and params
47
52
  remembered here) because we don't get the one_shot and input_size params
@@ -49,87 +54,71 @@ static void FN(Initialize)(
49
54
  those params to all hashers FN(Initialize) */
50
55
  }
51
56
 
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);
57
+ static 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);
75
67
  }
76
- FN_A(Prepare)(self->ha, one_shot, input_size, data);
77
- FN_B(Prepare)(self->hb, one_shot, input_size, data);
68
+ FN_A(Prepare)(&self->ha, one_shot, input_size, data);
69
+ FN_B(Prepare)(&self->hb, one_shot, input_size, data);
78
70
  }
79
71
 
80
72
  static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
81
73
  const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
82
74
  size_t input_size) {
83
- return sizeof(HashComposite) + 2 * sizeof(HasherCommon) +
84
- FN_A(HashMemAllocInBytes)(params, one_shot, input_size) +
75
+ return FN_A(HashMemAllocInBytes)(params, one_shot, input_size) +
85
76
  FN_B(HashMemAllocInBytes)(params, one_shot, input_size);
86
77
  }
87
78
 
88
- static BROTLI_INLINE void FN(Store)(HasherHandle BROTLI_RESTRICT handle,
79
+ static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,
89
80
  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);
81
+ FN_A(Store)(&self->ha, data, mask, ix);
82
+ FN_B(Store)(&self->hb, data, mask, ix);
93
83
  }
94
84
 
95
- static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle,
96
- const uint8_t* data, const size_t mask, const size_t ix_start,
85
+ static 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,
97
88
  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);
89
+ FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);
90
+ FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);
101
91
  }
102
92
 
103
- static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle,
93
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
94
+ HashComposite* BROTLI_RESTRICT self,
104
95
  size_t num_bytes, size_t position, const uint8_t* ringbuffer,
105
96
  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);
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);
111
101
  }
112
102
 
113
103
  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);
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);
118
107
  }
119
108
 
120
- static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
109
+ static BROTLI_INLINE void FN(FindLongestMatch)(
110
+ HashComposite* BROTLI_RESTRICT self,
121
111
  const BrotliEncoderDictionary* dictionary,
122
112
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
123
113
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
124
114
  const size_t max_length, const size_t max_backward,
125
- const size_t gap, const size_t max_distance,
115
+ const size_t dictionary_distance, const size_t max_distance,
126
116
  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,
117
+ FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,
118
+ distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
130
119
  max_distance, out);
131
- FN_B(FindLongestMatch)(self->hb, dictionary, data, ring_buffer_mask,
132
- distance_cache, cur_ix, max_length, max_backward, gap,
120
+ FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,
121
+ distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
133
122
  max_distance, out);
134
123
  }
135
124
 
@@ -28,7 +28,7 @@ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }
28
28
  static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }
29
29
 
30
30
  /* HashBytes is the function that chooses the bucket to place the address in.*/
31
- static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* data) {
31
+ static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {
32
32
  const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
33
33
  /* The higher bits contain more mixture from the multiplication,
34
34
  so we take our results from there. */
@@ -45,28 +45,56 @@ typedef struct FN(Bank) {
45
45
  } FN(Bank);
46
46
 
47
47
  typedef struct HashForgetfulChain {
48
- uint32_t addr[BUCKET_SIZE];
49
- uint16_t head[BUCKET_SIZE];
50
- /* Truncated hash used for quick rejection of "distance cache" candidates. */
51
- uint8_t tiny_hash[65536];
52
- FN(Bank) banks[NUM_BANKS];
53
- uint16_t free_slot_idx[NUM_BANKS];
48
+ uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */
54
49
  size_t max_hops;
50
+
51
+ /* Shortcuts. */
52
+ void* extra;
53
+ HasherCommon* common;
54
+
55
+ /* --- Dynamic size members --- */
56
+
57
+ /* uint32_t addr[BUCKET_SIZE]; */
58
+
59
+ /* uint16_t head[BUCKET_SIZE]; */
60
+
61
+ /* Truncated hash used for quick rejection of "distance cache" candidates. */
62
+ /* uint8_t tiny_hash[65536];*/
63
+
64
+ /* FN(Bank) banks[NUM_BANKS]; */
55
65
  } HashForgetfulChain;
56
66
 
57
- static BROTLI_INLINE HashForgetfulChain* FN(Self)(HasherHandle handle) {
58
- return (HashForgetfulChain*)&(GetHasherCommon(handle)[1]);
67
+ static uint32_t* FN(Addr)(void* extra) {
68
+ return (uint32_t*)extra;
69
+ }
70
+
71
+ static uint16_t* FN(Head)(void* extra) {
72
+ return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]);
73
+ }
74
+
75
+ static uint8_t* FN(TinyHash)(void* extra) {
76
+ return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]);
77
+ }
78
+
79
+ static FN(Bank)* FN(Banks)(void* extra) {
80
+ return (FN(Bank)*)(&FN(TinyHash)(extra)[65536]);
59
81
  }
60
82
 
61
83
  static void FN(Initialize)(
62
- HasherHandle handle, const BrotliEncoderParams* params) {
63
- FN(Self)(handle)->max_hops =
64
- (params->quality > 6 ? 7u : 8u) << (params->quality - 4);
84
+ HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self,
85
+ const BrotliEncoderParams* params) {
86
+ self->common = common;
87
+ self->extra = common->extra;
88
+
89
+ self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4);
65
90
  }
66
91
 
67
- static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
68
- size_t input_size, const uint8_t* data) {
69
- HashForgetfulChain* self = FN(Self)(handle);
92
+ static void FN(Prepare)(
93
+ HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
94
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
95
+ uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra);
96
+ uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra);
97
+ uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra);
70
98
  /* Partial preparation is 100 times slower (per socket). */
71
99
  size_t partial_prepare_threshold = BUCKET_SIZE >> 6;
72
100
  if (one_shot && input_size <= partial_prepare_threshold) {
@@ -74,17 +102,17 @@ static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
74
102
  for (i = 0; i < input_size; ++i) {
75
103
  size_t bucket = FN(HashBytes)(&data[i]);
76
104
  /* See InitEmpty comment. */
77
- self->addr[bucket] = 0xCCCCCCCC;
78
- self->head[bucket] = 0xCCCC;
105
+ addr[bucket] = 0xCCCCCCCC;
106
+ head[bucket] = 0xCCCC;
79
107
  }
80
108
  } else {
81
109
  /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position
82
110
  processed by hasher never reaches 3GB + 64M; this makes all new chains
83
111
  to be terminated after the first node. */
84
- memset(self->addr, 0xCC, sizeof(self->addr));
85
- memset(self->head, 0, sizeof(self->head));
112
+ memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE);
113
+ memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE);
86
114
  }
87
- memset(self->tiny_hash, 0, sizeof(self->tiny_hash));
115
+ memset(tiny_hash, 0, sizeof(uint8_t) * 65536);
88
116
  memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx));
89
117
  }
90
118
 
@@ -94,51 +122,58 @@ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
94
122
  BROTLI_UNUSED(params);
95
123
  BROTLI_UNUSED(one_shot);
96
124
  BROTLI_UNUSED(input_size);
97
- return sizeof(HashForgetfulChain);
125
+ return sizeof(uint32_t) * BUCKET_SIZE + sizeof(uint16_t) * BUCKET_SIZE +
126
+ sizeof(uint8_t) * 65536 + sizeof(FN(Bank)) * NUM_BANKS;
98
127
  }
99
128
 
100
129
  /* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend
101
130
  node to corresponding chain; also update tiny_hash for current position. */
102
- static BROTLI_INLINE void FN(Store)(HasherHandle BROTLI_RESTRICT handle,
131
+ static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self,
103
132
  const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
104
- HashForgetfulChain* self = FN(Self)(handle);
133
+ uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra);
134
+ uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra);
135
+ uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra);
136
+ FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra);
105
137
  const size_t key = FN(HashBytes)(&data[ix & mask]);
106
138
  const size_t bank = key & (NUM_BANKS - 1);
107
139
  const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1);
108
- size_t delta = ix - self->addr[key];
109
- self->tiny_hash[(uint16_t)ix] = (uint8_t)key;
140
+ size_t delta = ix - addr[key];
141
+ tiny_hash[(uint16_t)ix] = (uint8_t)key;
110
142
  if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF;
111
- self->banks[bank].slots[idx].delta = (uint16_t)delta;
112
- self->banks[bank].slots[idx].next = self->head[key];
113
- self->addr[key] = (uint32_t)ix;
114
- self->head[key] = (uint16_t)idx;
143
+ banks[bank].slots[idx].delta = (uint16_t)delta;
144
+ banks[bank].slots[idx].next = head[key];
145
+ addr[key] = (uint32_t)ix;
146
+ head[key] = (uint16_t)idx;
115
147
  }
116
148
 
117
- static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle,
118
- const uint8_t* data, const size_t mask, const size_t ix_start,
119
- const size_t ix_end) {
149
+ static BROTLI_INLINE void FN(StoreRange)(
150
+ HashForgetfulChain* BROTLI_RESTRICT self,
151
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask,
152
+ const size_t ix_start, const size_t ix_end) {
120
153
  size_t i;
121
154
  for (i = ix_start; i < ix_end; ++i) {
122
- FN(Store)(handle, data, mask, i);
155
+ FN(Store)(self, data, mask, i);
123
156
  }
124
157
  }
125
158
 
126
- static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle,
159
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
160
+ HashForgetfulChain* BROTLI_RESTRICT self,
127
161
  size_t num_bytes, size_t position, const uint8_t* ringbuffer,
128
162
  size_t ring_buffer_mask) {
129
163
  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
130
164
  /* Prepare the hashes for three last bytes of the last write.
131
165
  These could not be calculated before, since they require knowledge
132
166
  of both the previous and the current block. */
133
- FN(Store)(handle, ringbuffer, ring_buffer_mask, position - 3);
134
- FN(Store)(handle, ringbuffer, ring_buffer_mask, position - 2);
135
- FN(Store)(handle, ringbuffer, ring_buffer_mask, position - 1);
167
+ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3);
168
+ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2);
169
+ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1);
136
170
  }
137
171
  }
138
172
 
139
173
  static BROTLI_INLINE void FN(PrepareDistanceCache)(
140
- HasherHandle handle, int* BROTLI_RESTRICT distance_cache) {
141
- BROTLI_UNUSED(handle);
174
+ HashForgetfulChain* BROTLI_RESTRICT self,
175
+ int* BROTLI_RESTRICT distance_cache) {
176
+ BROTLI_UNUSED(self);
142
177
  PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK);
143
178
  }
144
179
 
@@ -153,14 +188,18 @@ static BROTLI_INLINE void FN(PrepareDistanceCache)(
153
188
  Does not look for matches further away than max_backward.
154
189
  Writes the best match into |out|.
155
190
  |out|->score is updated only if a better match is found. */
156
- static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
191
+ static BROTLI_INLINE void FN(FindLongestMatch)(
192
+ HashForgetfulChain* BROTLI_RESTRICT self,
157
193
  const BrotliEncoderDictionary* dictionary,
158
194
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
159
195
  const int* BROTLI_RESTRICT distance_cache,
160
196
  const size_t cur_ix, const size_t max_length, const size_t max_backward,
161
- const size_t gap, const size_t max_distance,
197
+ const size_t dictionary_distance, const size_t max_distance,
162
198
  HasherSearchResult* BROTLI_RESTRICT out) {
163
- HashForgetfulChain* self = FN(Self)(handle);
199
+ uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra);
200
+ uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra);
201
+ uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra);
202
+ FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra);
164
203
  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
165
204
  /* Don't accept a short copy from far away. */
166
205
  score_t min_score = out->score;
@@ -176,7 +215,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
176
215
  const size_t backward = (size_t)distance_cache[i];
177
216
  size_t prev_ix = (cur_ix - backward);
178
217
  /* For distance code 0 we want to consider 2-byte matches. */
179
- if (i > 0 && self->tiny_hash[(uint16_t)prev_ix] != tiny_hash) continue;
218
+ if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue;
180
219
  if (prev_ix >= cur_ix || backward > max_backward) {
181
220
  continue;
182
221
  }
@@ -204,16 +243,16 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
204
243
  const size_t bank = key & (NUM_BANKS - 1);
205
244
  size_t backward = 0;
206
245
  size_t hops = self->max_hops;
207
- size_t delta = cur_ix - self->addr[key];
208
- size_t slot = self->head[key];
246
+ size_t delta = cur_ix - addr[key];
247
+ size_t slot = head[key];
209
248
  while (hops--) {
210
249
  size_t prev_ix;
211
250
  size_t last = slot;
212
251
  backward += delta;
213
252
  if (backward > max_backward || (CAPPED_CHAINS && !delta)) break;
214
253
  prev_ix = (cur_ix - backward) & ring_buffer_mask;
215
- slot = self->banks[bank].slots[last].next;
216
- delta = self->banks[bank].slots[last].delta;
254
+ slot = banks[bank].slots[last].next;
255
+ delta = banks[bank].slots[last].delta;
217
256
  if (cur_ix_masked + best_len > ring_buffer_mask ||
218
257
  prev_ix + best_len > ring_buffer_mask ||
219
258
  data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
@@ -238,11 +277,11 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
238
277
  }
239
278
  }
240
279
  }
241
- FN(Store)(handle, data, ring_buffer_mask, cur_ix);
280
+ FN(Store)(self, data, ring_buffer_mask, cur_ix);
242
281
  }
243
282
  if (out->score == min_score) {
244
283
  SearchInStaticDictionary(dictionary,
245
- handle, &data[cur_ix_masked], max_length, max_backward + gap,
284
+ self->common, &data[cur_ix_masked], max_length, dictionary_distance,
246
285
  max_distance, out, BROTLI_FALSE);
247
286
  }
248
287
  }
@@ -20,7 +20,7 @@ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }
20
20
  static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }
21
21
 
22
22
  /* HashBytes is the function that chooses the bucket to place the address in. */
23
- static BROTLI_INLINE uint32_t FN(HashBytes)(const uint8_t* data,
23
+ static BROTLI_INLINE uint32_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data,
24
24
  const uint64_t mask,
25
25
  const int shift) {
26
26
  const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(data) & mask) * kHashMul64Long;
@@ -42,43 +42,43 @@ typedef struct HashLongestMatch {
42
42
  /* Mask for accessing entries in a block (in a ring-buffer manner). */
43
43
  uint32_t block_mask_;
44
44
 
45
+ int block_bits_;
46
+ int num_last_distances_to_check_;
47
+
48
+ /* Shortcuts. */
49
+ HasherCommon* common_;
50
+
45
51
  /* --- Dynamic size members --- */
46
52
 
47
53
  /* Number of entries in a particular bucket. */
48
- /* uint16_t num[bucket_size]; */
54
+ uint16_t* num_; /* uint16_t[bucket_size]; */
49
55
 
50
56
  /* Buckets containing block_size_ of backward references. */
51
- /* uint32_t* buckets[bucket_size * block_size]; */
57
+ uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */
52
58
  } HashLongestMatch;
53
59
 
54
- static BROTLI_INLINE HashLongestMatch* FN(Self)(HasherHandle handle) {
55
- return (HashLongestMatch*)&(GetHasherCommon(handle)[1]);
56
- }
57
-
58
- static BROTLI_INLINE uint16_t* FN(Num)(HashLongestMatch* self) {
59
- return (uint16_t*)(&self[1]);
60
- }
61
-
62
- static BROTLI_INLINE uint32_t* FN(Buckets)(HashLongestMatch* self) {
63
- return (uint32_t*)(&FN(Num)(self)[self->bucket_size_]);
64
- }
65
-
66
60
  static void FN(Initialize)(
67
- HasherHandle handle, const BrotliEncoderParams* params) {
68
- HasherCommon* common = GetHasherCommon(handle);
69
- HashLongestMatch* self = FN(Self)(handle);
61
+ HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,
62
+ const BrotliEncoderParams* params) {
63
+ self->common_ = common;
64
+
70
65
  BROTLI_UNUSED(params);
71
66
  self->hash_shift_ = 64 - common->params.bucket_bits;
72
67
  self->hash_mask_ = (~((uint64_t)0U)) >> (64 - 8 * common->params.hash_len);
73
68
  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;
69
+ self->block_bits_ = common->params.block_bits;
74
70
  self->block_size_ = (size_t)1 << common->params.block_bits;
75
71
  self->block_mask_ = (uint32_t)(self->block_size_ - 1);
72
+ self->num_last_distances_to_check_ =
73
+ common->params.num_last_distances_to_check;
74
+ self->num_ = (uint16_t*)common->extra;
75
+ self->buckets_ = (uint32_t*)&self->num_[self->bucket_size_];
76
76
  }
77
77
 
78
- static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
79
- size_t input_size, const uint8_t* data) {
80
- HashLongestMatch* self = FN(Self)(handle);
81
- 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_;
82
82
  /* Partial preparation is 100 times slower (per socket). */
83
83
  size_t partial_prepare_threshold = self->bucket_size_ >> 6;
84
84
  if (one_shot && input_size <= partial_prepare_threshold) {
@@ -100,50 +100,52 @@ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
100
100
  size_t block_size = (size_t)1 << params->hasher.block_bits;
101
101
  BROTLI_UNUSED(one_shot);
102
102
  BROTLI_UNUSED(input_size);
103
- return sizeof(HashLongestMatch) + bucket_size * (2 + 4 * block_size);
103
+ return sizeof(uint16_t) * bucket_size +
104
+ sizeof(uint32_t) * bucket_size * block_size;
104
105
  }
105
106
 
106
107
  /* Look at 4 bytes at &data[ix & mask].
107
108
  Compute a hash from these, and store the value of ix at that position. */
108
- static BROTLI_INLINE void FN(Store)(HasherHandle handle, const uint8_t* data,
109
+ static BROTLI_INLINE void FN(Store)(
110
+ HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
109
111
  const size_t mask, const size_t ix) {
110
- HashLongestMatch* self = FN(Self)(handle);
111
- uint16_t* num = FN(Num)(self);
112
+ uint16_t* BROTLI_RESTRICT num = self->num_;
113
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
112
114
  const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_mask_,
113
115
  self->hash_shift_);
114
116
  const size_t minor_ix = num[key] & self->block_mask_;
115
- const size_t offset =
116
- minor_ix + (key << GetHasherCommon(handle)->params.block_bits);
117
- FN(Buckets)(self)[offset] = (uint32_t)ix;
117
+ const size_t offset = minor_ix + (key << self->block_bits_);
118
118
  ++num[key];
119
+ buckets[offset] = (uint32_t)ix;
119
120
  }
120
121
 
121
- static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle,
122
- const uint8_t* data, const size_t mask, const size_t ix_start,
123
- const size_t ix_end) {
122
+ static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,
123
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask,
124
+ const size_t ix_start, const size_t ix_end) {
124
125
  size_t i;
125
126
  for (i = ix_start; i < ix_end; ++i) {
126
- FN(Store)(handle, data, mask, i);
127
+ FN(Store)(self, data, mask, i);
127
128
  }
128
129
  }
129
130
 
130
- static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle,
131
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
132
+ HashLongestMatch* BROTLI_RESTRICT self,
131
133
  size_t num_bytes, size_t position, const uint8_t* ringbuffer,
132
134
  size_t ringbuffer_mask) {
133
135
  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
134
136
  /* Prepare the hashes for three last bytes of the last write.
135
137
  These could not be calculated before, since they require knowledge
136
138
  of both the previous and the current block. */
137
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 3);
138
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 2);
139
- FN(Store)(handle, ringbuffer, ringbuffer_mask, position - 1);
139
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);
140
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);
141
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);
140
142
  }
141
143
  }
142
144
 
143
145
  static BROTLI_INLINE void FN(PrepareDistanceCache)(
144
- HasherHandle handle, int* BROTLI_RESTRICT distance_cache) {
145
- PrepareDistanceCache(distance_cache,
146
- GetHasherCommon(handle)->params.num_last_distances_to_check);
146
+ HashLongestMatch* BROTLI_RESTRICT self,
147
+ int* BROTLI_RESTRICT distance_cache) {
148
+ PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);
147
149
  }
148
150
 
149
151
  /* Find a longest backward match of &data[cur_ix] up to the length of
@@ -157,17 +159,16 @@ static BROTLI_INLINE void FN(PrepareDistanceCache)(
157
159
  Does not look for matches further away than max_backward.
158
160
  Writes the best match into |out|.
159
161
  |out|->score is updated only if a better match is found. */
160
- static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
162
+ static BROTLI_INLINE void FN(FindLongestMatch)(
163
+ HashLongestMatch* BROTLI_RESTRICT self,
161
164
  const BrotliEncoderDictionary* dictionary,
162
165
  const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
163
166
  const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
164
167
  const size_t max_length, const size_t max_backward,
165
- const size_t gap, const size_t max_distance,
168
+ const size_t dictionary_distance, const size_t max_distance,
166
169
  HasherSearchResult* BROTLI_RESTRICT out) {
167
- HasherCommon* common = GetHasherCommon(handle);
168
- HashLongestMatch* self = FN(Self)(handle);
169
- uint16_t* num = FN(Num)(self);
170
- uint32_t* buckets = FN(Buckets)(self);
170
+ uint16_t* BROTLI_RESTRICT num = self->num_;
171
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
171
172
  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
172
173
  /* Don't accept a short copy from far away. */
173
174
  score_t min_score = out->score;
@@ -177,7 +178,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
177
178
  out->len = 0;
178
179
  out->len_code_delta = 0;
179
180
  /* Try last distance first. */
180
- for (i = 0; i < (size_t)common->params.num_last_distances_to_check; ++i) {
181
+ for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
181
182
  const size_t backward = (size_t)distance_cache[i];
182
183
  size_t prev_ix = (size_t)(cur_ix - backward);
183
184
  if (prev_ix >= cur_ix) {
@@ -218,8 +219,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
218
219
  {
219
220
  const uint32_t key = FN(HashBytes)(
220
221
  &data[cur_ix_masked], self->hash_mask_, self->hash_shift_);
221
- uint32_t* BROTLI_RESTRICT bucket =
222
- &buckets[key << common->params.block_bits];
222
+ uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
223
223
  const size_t down =
224
224
  (num[key] > self->block_size_) ?
225
225
  (num[key] - self->block_size_) : 0u;
@@ -259,7 +259,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
259
259
  }
260
260
  if (min_score == out->score) {
261
261
  SearchInStaticDictionary(dictionary,
262
- handle, &data[cur_ix_masked], max_length, max_backward + gap,
262
+ self->common_, &data[cur_ix_masked], max_length, dictionary_distance,
263
263
  max_distance, out, BROTLI_FALSE);
264
264
  }
265
265
  }