brotli 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -3
  4. data/brotli.gemspec +1 -1
  5. data/ext/brotli/brotli.c +4 -4
  6. data/ext/brotli/brotli.h +2 -2
  7. data/ext/brotli/extconf.rb +9 -16
  8. data/lib/brotli/version.rb +1 -1
  9. data/vendor/brotli/{common → c/common}/constants.h +11 -1
  10. data/vendor/brotli/c/common/dictionary.bin +432 -0
  11. data/vendor/brotli/c/common/dictionary.c +5905 -0
  12. data/vendor/brotli/c/common/dictionary.h +64 -0
  13. data/vendor/brotli/c/common/version.h +19 -0
  14. data/vendor/brotli/{dec → c/dec}/bit_reader.c +2 -2
  15. data/vendor/brotli/{dec → c/dec}/bit_reader.h +11 -34
  16. data/vendor/brotli/{dec → c/dec}/context.h +1 -1
  17. data/vendor/brotli/{dec → c/dec}/decode.c +389 -356
  18. data/vendor/brotli/{dec → c/dec}/huffman.c +24 -23
  19. data/vendor/brotli/{dec → c/dec}/huffman.h +1 -1
  20. data/vendor/brotli/{dec → c/dec}/port.h +19 -10
  21. data/vendor/brotli/{dec → c/dec}/prefix.h +1 -1
  22. data/vendor/brotli/{dec → c/dec}/state.c +23 -19
  23. data/vendor/brotli/{dec → c/dec}/state.h +18 -17
  24. data/vendor/brotli/{dec → c/dec}/transform.h +2 -2
  25. data/vendor/brotli/c/enc/backward_references.c +134 -0
  26. data/vendor/brotli/c/enc/backward_references.h +39 -0
  27. data/vendor/brotli/{enc/backward_references.c → c/enc/backward_references_hq.c} +144 -232
  28. data/vendor/brotli/{enc/backward_references.h → c/enc/backward_references_hq.h} +28 -31
  29. data/vendor/brotli/{enc → c/enc}/backward_references_inc.h +37 -31
  30. data/vendor/brotli/{enc → c/enc}/bit_cost.c +1 -1
  31. data/vendor/brotli/{enc → c/enc}/bit_cost.h +1 -1
  32. data/vendor/brotli/{enc → c/enc}/bit_cost_inc.h +0 -0
  33. data/vendor/brotli/{enc → c/enc}/block_encoder_inc.h +0 -0
  34. data/vendor/brotli/{enc → c/enc}/block_splitter.c +2 -4
  35. data/vendor/brotli/{enc → c/enc}/block_splitter.h +1 -1
  36. data/vendor/brotli/{enc → c/enc}/block_splitter_inc.h +6 -7
  37. data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.c +22 -26
  38. data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.h +1 -5
  39. data/vendor/brotli/{enc → c/enc}/cluster.c +1 -1
  40. data/vendor/brotli/{enc → c/enc}/cluster.h +1 -1
  41. data/vendor/brotli/{enc → c/enc}/cluster_inc.h +2 -0
  42. data/vendor/brotli/{enc → c/enc}/command.h +34 -17
  43. data/vendor/brotli/{enc → c/enc}/compress_fragment.c +97 -53
  44. data/vendor/brotli/{enc → c/enc}/compress_fragment.h +5 -2
  45. data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.c +106 -51
  46. data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.h +5 -2
  47. data/vendor/brotli/{enc → c/enc}/context.h +3 -3
  48. data/vendor/brotli/c/enc/dictionary_hash.c +1120 -0
  49. data/vendor/brotli/c/enc/dictionary_hash.h +24 -0
  50. data/vendor/brotli/{enc → c/enc}/encode.c +442 -240
  51. data/vendor/brotli/{enc → c/enc}/entropy_encode.c +9 -9
  52. data/vendor/brotli/{enc → c/enc}/entropy_encode.h +4 -4
  53. data/vendor/brotli/{enc → c/enc}/entropy_encode_static.h +4 -4
  54. data/vendor/brotli/{enc → c/enc}/fast_log.h +3 -3
  55. data/vendor/brotli/{enc → c/enc}/find_match_length.h +8 -8
  56. data/vendor/brotli/c/enc/hash.h +446 -0
  57. data/vendor/brotli/{enc → c/enc}/hash_forgetful_chain_inc.h +72 -68
  58. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +266 -0
  59. data/vendor/brotli/c/enc/hash_longest_match_inc.h +258 -0
  60. data/vendor/brotli/{enc → c/enc}/hash_longest_match_quickly_inc.h +81 -77
  61. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +326 -0
  62. data/vendor/brotli/{enc → c/enc}/histogram.c +4 -2
  63. data/vendor/brotli/{enc → c/enc}/histogram.h +1 -1
  64. data/vendor/brotli/{enc → c/enc}/histogram_inc.h +0 -0
  65. data/vendor/brotli/{enc → c/enc}/literal_cost.c +4 -7
  66. data/vendor/brotli/{enc → c/enc}/literal_cost.h +2 -2
  67. data/vendor/brotli/{enc → c/enc}/memory.c +1 -1
  68. data/vendor/brotli/{enc → c/enc}/memory.h +3 -2
  69. data/vendor/brotli/{enc → c/enc}/metablock.c +136 -123
  70. data/vendor/brotli/{enc → c/enc}/metablock.h +2 -12
  71. data/vendor/brotli/{enc → c/enc}/metablock_inc.h +0 -0
  72. data/vendor/brotli/{enc → c/enc}/port.h +49 -33
  73. data/vendor/brotli/{enc → c/enc}/prefix.h +4 -2
  74. data/vendor/brotli/{enc → c/enc}/quality.h +47 -17
  75. data/vendor/brotli/{enc → c/enc}/ringbuffer.h +6 -6
  76. data/vendor/brotli/{enc → c/enc}/static_dict.c +26 -22
  77. data/vendor/brotli/{enc → c/enc}/static_dict.h +3 -1
  78. data/vendor/brotli/c/enc/static_dict_lut.h +5864 -0
  79. data/vendor/brotli/{enc → c/enc}/utf8_util.c +1 -1
  80. data/vendor/brotli/{enc → c/enc}/utf8_util.h +2 -2
  81. data/vendor/brotli/{enc → c/enc}/write_bits.h +3 -3
  82. data/vendor/brotli/c/include/brotli/decode.h +339 -0
  83. data/vendor/brotli/c/include/brotli/encode.h +402 -0
  84. data/vendor/brotli/c/include/brotli/port.h +146 -0
  85. data/vendor/brotli/c/include/brotli/types.h +90 -0
  86. metadata +80 -79
  87. data/vendor/brotli/common/dictionary.c +0 -9474
  88. data/vendor/brotli/common/dictionary.h +0 -29
  89. data/vendor/brotli/common/port.h +0 -107
  90. data/vendor/brotli/common/types.h +0 -58
  91. data/vendor/brotli/dec/decode.h +0 -188
  92. data/vendor/brotli/enc/compressor.cc +0 -139
  93. data/vendor/brotli/enc/compressor.h +0 -161
  94. data/vendor/brotli/enc/dictionary_hash.h +0 -4121
  95. data/vendor/brotli/enc/encode.h +0 -221
  96. data/vendor/brotli/enc/encode_parallel.cc +0 -289
  97. data/vendor/brotli/enc/encode_parallel.h +0 -27
  98. data/vendor/brotli/enc/hash.h +0 -717
  99. data/vendor/brotli/enc/hash_longest_match_inc.h +0 -241
  100. data/vendor/brotli/enc/static_dict_lut.h +0 -11241
  101. data/vendor/brotli/enc/streams.cc +0 -114
  102. data/vendor/brotli/enc/streams.h +0 -121
@@ -0,0 +1,326 @@
1
+ /* NOLINT(build/header_guard) */
2
+ /* Copyright 2016 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, BUCKET_BITS, MAX_TREE_COMP_LENGTH,
9
+ MAX_TREE_SEARCH_DEPTH */
10
+
11
+ /* A (forgetful) hash table where each hash bucket contains a binary tree of
12
+ sequences whose first 4 bytes share the same hash code.
13
+ Each sequence is MAX_TREE_COMP_LENGTH long and is identified by its starting
14
+ position in the input data. The binary tree is sorted by the lexicographic
15
+ order of the sequences, and it is also a max-heap with respect to the
16
+ starting positions. */
17
+
18
+ #define HashToBinaryTree HASHER()
19
+
20
+ #define BUCKET_SIZE (1 << BUCKET_BITS)
21
+
22
+ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }
23
+ static BROTLI_INLINE size_t FN(StoreLookahead)(void) {
24
+ return MAX_TREE_COMP_LENGTH;
25
+ }
26
+
27
+ static uint32_t FN(HashBytes)(const uint8_t *data) {
28
+ uint32_t h = BROTLI_UNALIGNED_LOAD32(data) * kHashMul32;
29
+ /* The higher bits contain more mixture from the multiplication,
30
+ so we take our results from there. */
31
+ return h >> (32 - BUCKET_BITS);
32
+ }
33
+
34
+ typedef struct HashToBinaryTree {
35
+ /* The window size minus 1 */
36
+ size_t window_mask_;
37
+
38
+ /* Hash table that maps the 4-byte hashes of the sequence to the last
39
+ position where this hash was found, which is the root of the binary
40
+ tree of sequences that share this hash bucket. */
41
+ uint32_t buckets_[BUCKET_SIZE];
42
+
43
+ /* A position used to mark a non-existent sequence, i.e. a tree is empty if
44
+ its root is at invalid_pos_ and a node is a leaf if both its children
45
+ are at invalid_pos_. */
46
+ uint32_t invalid_pos_;
47
+
48
+ /* --- Dynamic size members --- */
49
+
50
+ /* The union of the binary trees of each hash bucket. The root of the tree
51
+ corresponding to a hash is a sequence starting at buckets_[hash] and
52
+ the left and right children of a sequence starting at pos are
53
+ forest_[2 * pos] and forest_[2 * pos + 1]. */
54
+ /* uint32_t forest[2 * num_nodes] */
55
+ } HashToBinaryTree;
56
+
57
+ static BROTLI_INLINE HashToBinaryTree* FN(Self)(HasherHandle handle) {
58
+ return (HashToBinaryTree*)&(GetHasherCommon(handle)[1]);
59
+ }
60
+
61
+ static BROTLI_INLINE uint32_t* FN(Forest)(HashToBinaryTree* self) {
62
+ return (uint32_t*)(&self[1]);
63
+ }
64
+
65
+ static void FN(Initialize)(
66
+ HasherHandle handle, const BrotliEncoderParams* params) {
67
+ HashToBinaryTree* self = FN(Self)(handle);
68
+ self->window_mask_ = (1u << params->lgwin) - 1u;
69
+ self->invalid_pos_ = (uint32_t)(0 - self->window_mask_);
70
+ }
71
+
72
+ static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
73
+ size_t input_size, const uint8_t* data) {
74
+ HashToBinaryTree* self = FN(Self)(handle);
75
+ uint32_t invalid_pos = self->invalid_pos_;
76
+ uint32_t i;
77
+ BROTLI_UNUSED(data);
78
+ BROTLI_UNUSED(one_shot);
79
+ BROTLI_UNUSED(input_size);
80
+ for (i = 0; i < BUCKET_SIZE; i++) {
81
+ self->buckets_[i] = invalid_pos;
82
+ }
83
+ }
84
+
85
+ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
86
+ const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
87
+ size_t input_size) {
88
+ size_t num_nodes = (size_t)1 << params->lgwin;
89
+ if (one_shot && input_size < num_nodes) {
90
+ num_nodes = input_size;
91
+ }
92
+ return sizeof(HashToBinaryTree) + 2 * sizeof(uint32_t) * num_nodes;
93
+ }
94
+
95
+ static BROTLI_INLINE size_t FN(LeftChildIndex)(HashToBinaryTree* self,
96
+ const size_t pos) {
97
+ return 2 * (pos & self->window_mask_);
98
+ }
99
+
100
+ static BROTLI_INLINE size_t FN(RightChildIndex)(HashToBinaryTree* self,
101
+ const size_t pos) {
102
+ return 2 * (pos & self->window_mask_) + 1;
103
+ }
104
+
105
+ /* Stores the hash of the next 4 bytes and in a single tree-traversal, the
106
+ hash bucket's binary tree is searched for matches and is re-rooted at the
107
+ current position.
108
+
109
+ If less than MAX_TREE_COMP_LENGTH data is available, the hash bucket of the
110
+ current position is searched for matches, but the state of the hash table
111
+ is not changed, since we can not know the final sorting order of the
112
+ current (incomplete) sequence.
113
+
114
+ This function must be called with increasing cur_ix positions. */
115
+ static BROTLI_INLINE BackwardMatch* FN(StoreAndFindMatches)(
116
+ HashToBinaryTree* self, const uint8_t* const BROTLI_RESTRICT data,
117
+ const size_t cur_ix, const size_t ring_buffer_mask, const size_t max_length,
118
+ const size_t max_backward, size_t* const BROTLI_RESTRICT best_len,
119
+ BackwardMatch* BROTLI_RESTRICT matches) {
120
+ const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
121
+ const size_t max_comp_len =
122
+ BROTLI_MIN(size_t, max_length, MAX_TREE_COMP_LENGTH);
123
+ const BROTLI_BOOL should_reroot_tree =
124
+ TO_BROTLI_BOOL(max_length >= MAX_TREE_COMP_LENGTH);
125
+ const uint32_t key = FN(HashBytes)(&data[cur_ix_masked]);
126
+ uint32_t* forest = FN(Forest)(self);
127
+ size_t prev_ix = self->buckets_[key];
128
+ /* The forest index of the rightmost node of the left subtree of the new
129
+ root, updated as we traverse and re-root the tree of the hash bucket. */
130
+ size_t node_left = FN(LeftChildIndex)(self, cur_ix);
131
+ /* The forest index of the leftmost node of the right subtree of the new
132
+ root, updated as we traverse and re-root the tree of the hash bucket. */
133
+ size_t node_right = FN(RightChildIndex)(self, cur_ix);
134
+ /* The match length of the rightmost node of the left subtree of the new
135
+ root, updated as we traverse and re-root the tree of the hash bucket. */
136
+ size_t best_len_left = 0;
137
+ /* The match length of the leftmost node of the right subtree of the new
138
+ root, updated as we traverse and re-root the tree of the hash bucket. */
139
+ size_t best_len_right = 0;
140
+ size_t depth_remaining;
141
+ if (should_reroot_tree) {
142
+ self->buckets_[key] = (uint32_t)cur_ix;
143
+ }
144
+ for (depth_remaining = MAX_TREE_SEARCH_DEPTH; ; --depth_remaining) {
145
+ const size_t backward = cur_ix - prev_ix;
146
+ const size_t prev_ix_masked = prev_ix & ring_buffer_mask;
147
+ if (backward == 0 || backward > max_backward || depth_remaining == 0) {
148
+ if (should_reroot_tree) {
149
+ forest[node_left] = self->invalid_pos_;
150
+ forest[node_right] = self->invalid_pos_;
151
+ }
152
+ break;
153
+ }
154
+ {
155
+ const size_t cur_len = BROTLI_MIN(size_t, best_len_left, best_len_right);
156
+ size_t len;
157
+ assert(cur_len <= MAX_TREE_COMP_LENGTH);
158
+ len = cur_len +
159
+ FindMatchLengthWithLimit(&data[cur_ix_masked + cur_len],
160
+ &data[prev_ix_masked + cur_len],
161
+ max_length - cur_len);
162
+ assert(0 == memcmp(&data[cur_ix_masked], &data[prev_ix_masked], len));
163
+ if (matches && len > *best_len) {
164
+ *best_len = len;
165
+ InitBackwardMatch(matches++, backward, len);
166
+ }
167
+ if (len >= max_comp_len) {
168
+ if (should_reroot_tree) {
169
+ forest[node_left] = forest[FN(LeftChildIndex)(self, prev_ix)];
170
+ forest[node_right] = forest[FN(RightChildIndex)(self, prev_ix)];
171
+ }
172
+ break;
173
+ }
174
+ if (data[cur_ix_masked + len] > data[prev_ix_masked + len]) {
175
+ best_len_left = len;
176
+ if (should_reroot_tree) {
177
+ forest[node_left] = (uint32_t)prev_ix;
178
+ }
179
+ node_left = FN(RightChildIndex)(self, prev_ix);
180
+ prev_ix = forest[node_left];
181
+ } else {
182
+ best_len_right = len;
183
+ if (should_reroot_tree) {
184
+ forest[node_right] = (uint32_t)prev_ix;
185
+ }
186
+ node_right = FN(LeftChildIndex)(self, prev_ix);
187
+ prev_ix = forest[node_right];
188
+ }
189
+ }
190
+ }
191
+ return matches;
192
+ }
193
+
194
+ /* Finds all backward matches of &data[cur_ix & ring_buffer_mask] up to the
195
+ length of max_length and stores the position cur_ix in the hash table.
196
+
197
+ Sets *num_matches to the number of matches found, and stores the found
198
+ matches in matches[0] to matches[*num_matches - 1]. The matches will be
199
+ sorted by strictly increasing length and (non-strictly) increasing
200
+ distance. */
201
+ static BROTLI_INLINE size_t FN(FindAllMatches)(HasherHandle handle,
202
+ const BrotliDictionary* dictionary, const uint8_t* data,
203
+ const size_t ring_buffer_mask, const size_t cur_ix,
204
+ const size_t max_length, const size_t max_backward, const size_t gap,
205
+ const BrotliEncoderParams* params, BackwardMatch* matches) {
206
+ BackwardMatch* const orig_matches = matches;
207
+ const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
208
+ size_t best_len = 1;
209
+ const size_t short_match_max_backward =
210
+ params->quality != HQ_ZOPFLIFICATION_QUALITY ? 16 : 64;
211
+ size_t stop = cur_ix - short_match_max_backward;
212
+ uint32_t dict_matches[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1];
213
+ size_t i;
214
+ if (cur_ix < short_match_max_backward) { stop = 0; }
215
+ for (i = cur_ix - 1; i > stop && best_len <= 2; --i) {
216
+ size_t prev_ix = i;
217
+ const size_t backward = cur_ix - prev_ix;
218
+ if (BROTLI_PREDICT_FALSE(backward > max_backward)) {
219
+ break;
220
+ }
221
+ prev_ix &= ring_buffer_mask;
222
+ if (data[cur_ix_masked] != data[prev_ix] ||
223
+ data[cur_ix_masked + 1] != data[prev_ix + 1]) {
224
+ continue;
225
+ }
226
+ {
227
+ const size_t len =
228
+ FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked],
229
+ max_length);
230
+ if (len > best_len) {
231
+ best_len = len;
232
+ InitBackwardMatch(matches++, backward, len);
233
+ }
234
+ }
235
+ }
236
+ if (best_len < max_length) {
237
+ matches = FN(StoreAndFindMatches)(FN(Self)(handle), data, cur_ix,
238
+ ring_buffer_mask, max_length, max_backward, &best_len, matches);
239
+ }
240
+ for (i = 0; i <= BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN; ++i) {
241
+ dict_matches[i] = kInvalidMatch;
242
+ }
243
+ {
244
+ size_t minlen = BROTLI_MAX(size_t, 4, best_len + 1);
245
+ if (BrotliFindAllStaticDictionaryMatches(dictionary,
246
+ &data[cur_ix_masked], minlen, max_length, &dict_matches[0])) {
247
+ size_t maxlen = BROTLI_MIN(
248
+ size_t, BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN, max_length);
249
+ size_t l;
250
+ for (l = minlen; l <= maxlen; ++l) {
251
+ uint32_t dict_id = dict_matches[l];
252
+ if (dict_id < kInvalidMatch) {
253
+ size_t distance = max_backward + gap + (dict_id >> 5) + 1;
254
+ if (distance < BROTLI_MAX_DISTANCE) {
255
+ InitDictionaryBackwardMatch(matches++, distance, l, dict_id & 31);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+ return (size_t)(matches - orig_matches);
262
+ }
263
+
264
+ /* Stores the hash of the next 4 bytes and re-roots the binary tree at the
265
+ current sequence, without returning any matches.
266
+ REQUIRES: ix + MAX_TREE_COMP_LENGTH <= end-of-current-block */
267
+ static BROTLI_INLINE void FN(Store)(HasherHandle handle, const uint8_t *data,
268
+ const size_t mask, const size_t ix) {
269
+ HashToBinaryTree* self = FN(Self)(handle);
270
+ /* Maximum distance is window size - 16, see section 9.1. of the spec. */
271
+ const size_t max_backward = self->window_mask_ - BROTLI_WINDOW_GAP + 1;
272
+ FN(StoreAndFindMatches)(self, data, ix, mask, MAX_TREE_COMP_LENGTH,
273
+ max_backward, NULL, NULL);
274
+ }
275
+
276
+ static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle,
277
+ const uint8_t *data, const size_t mask, const size_t ix_start,
278
+ const size_t ix_end) {
279
+ size_t i = ix_start;
280
+ size_t j = ix_start;
281
+ if (ix_start + 63 <= ix_end) {
282
+ i = ix_end - 63;
283
+ }
284
+ if (ix_start + 512 <= i) {
285
+ for (; j < i; j += 8) {
286
+ FN(Store)(handle, data, mask, j);
287
+ }
288
+ }
289
+ for (; i < ix_end; ++i) {
290
+ FN(Store)(handle, data, mask, i);
291
+ }
292
+ }
293
+
294
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle,
295
+ size_t num_bytes, size_t position, const uint8_t* ringbuffer,
296
+ size_t ringbuffer_mask) {
297
+ HashToBinaryTree* self = FN(Self)(handle);
298
+ if (num_bytes >= FN(HashTypeLength)() - 1 &&
299
+ position >= MAX_TREE_COMP_LENGTH) {
300
+ /* Store the last `MAX_TREE_COMP_LENGTH - 1` positions in the hasher.
301
+ These could not be calculated before, since they require knowledge
302
+ of both the previous and the current block. */
303
+ const size_t i_start = position - MAX_TREE_COMP_LENGTH + 1;
304
+ const size_t i_end = BROTLI_MIN(size_t, position, i_start + num_bytes);
305
+ size_t i;
306
+ for (i = i_start; i < i_end; ++i) {
307
+ /* Maximum distance is window size - 16, see section 9.1. of the spec.
308
+ Furthermore, we have to make sure that we don't look further back
309
+ from the start of the next block than the window size, otherwise we
310
+ could access already overwritten areas of the ring-buffer. */
311
+ const size_t max_backward =
312
+ self->window_mask_ - BROTLI_MAX(size_t,
313
+ BROTLI_WINDOW_GAP - 1,
314
+ position - i);
315
+ /* We know that i + MAX_TREE_COMP_LENGTH <= position + num_bytes, i.e. the
316
+ end of the current block and that we have at least
317
+ MAX_TREE_COMP_LENGTH tail in the ring-buffer. */
318
+ FN(StoreAndFindMatches)(self, ringbuffer, i, ringbuffer_mask,
319
+ MAX_TREE_COMP_LENGTH, max_backward, NULL, NULL);
320
+ }
321
+ }
322
+ }
323
+
324
+ #undef BUCKET_SIZE
325
+
326
+ #undef HashToBinaryTree
@@ -66,8 +66,10 @@ void BrotliBuildHistogramsWithContext(
66
66
  for (j = cmd->insert_len_; j != 0; --j) {
67
67
  size_t context;
68
68
  BlockSplitIteratorNext(&literal_it);
69
- context = (literal_it.type_ << BROTLI_LITERAL_CONTEXT_BITS) +
70
- Context(prev_byte, prev_byte2, context_modes[literal_it.type_]);
69
+ context = context_modes ?
70
+ ((literal_it.type_ << BROTLI_LITERAL_CONTEXT_BITS) +
71
+ Context(prev_byte, prev_byte2, context_modes[literal_it.type_])) :
72
+ literal_it.type_;
71
73
  HistogramAddLiteral(&literal_histograms[context],
72
74
  ringbuffer[pos & mask]);
73
75
  prev_byte2 = prev_byte;
@@ -12,7 +12,7 @@
12
12
  #include <string.h> /* memset */
13
13
 
14
14
  #include "../common/constants.h"
15
- #include "../common/types.h"
15
+ #include <brotli/types.h>
16
16
  #include "./block_splitter.h"
17
17
  #include "./command.h"
18
18
  #include "./context.h"
@@ -9,7 +9,7 @@
9
9
 
10
10
  #include "./literal_cost.h"
11
11
 
12
- #include "../common/types.h"
12
+ #include <brotli/types.h>
13
13
  #include "./fast_log.h"
14
14
  #include "./port.h"
15
15
  #include "./utf8_util.h"
@@ -38,12 +38,10 @@ static size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask,
38
38
  size_t counts[3] = { 0 };
39
39
  size_t max_utf8 = 1; /* should be 2, but 1 compresses better. */
40
40
  size_t last_c = 0;
41
- size_t utf8_pos = 0;
42
41
  size_t i;
43
42
  for (i = 0; i < len; ++i) {
44
43
  size_t c = data[(pos + i) & mask];
45
- utf8_pos = UTF8Position(last_c, c, 2);
46
- ++counts[utf8_pos];
44
+ ++counts[UTF8Position(last_c, c, 2)];
47
45
  last_c = c;
48
46
  }
49
47
  if (counts[2] < 500) {
@@ -57,15 +55,14 @@ static size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask,
57
55
 
58
56
  static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,
59
57
  const uint8_t *data, float *cost) {
60
- /* max_utf8 is 0 (normal ascii single byte modeling),
61
- 1 (for 2-byte utf-8 modeling), or 2 (for 3-byte utf-8 modeling). */
58
+ /* max_utf8 is 0 (normal ASCII single byte modeling),
59
+ 1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */
62
60
  const size_t max_utf8 = DecideMultiByteStatsLevel(pos, len, mask, data);
63
61
  size_t histogram[3][256] = { { 0 } };
64
62
  size_t window_half = 495;
65
63
  size_t in_window = BROTLI_MIN(size_t, window_half, len);
66
64
  size_t in_window_utf8[3] = { 0 };
67
65
 
68
-
69
66
  size_t i;
70
67
  { /* Bootstrap histograms. */
71
68
  size_t last_c = 0;
@@ -10,7 +10,7 @@
10
10
  #ifndef BROTLI_ENC_LITERAL_COST_H_
11
11
  #define BROTLI_ENC_LITERAL_COST_H_
12
12
 
13
- #include "../common/types.h"
13
+ #include <brotli/types.h>
14
14
  #include "./port.h"
15
15
 
16
16
  #if defined(__cplusplus) || defined(c_plusplus)
@@ -18,7 +18,7 @@ extern "C" {
18
18
  #endif
19
19
 
20
20
  /* Estimates how many bits the literals in the interval [pos, pos + len) in the
21
- ringbuffer (data, mask) will take entropy coded and writes these estimates
21
+ ring-buffer (data, mask) will take entropy coded and writes these estimates
22
22
  to the cost[0..len) array. */
23
23
  BROTLI_INTERNAL void BrotliEstimateBitCostsForLiterals(
24
24
  size_t pos, size_t len, size_t mask, const uint8_t *data, float *cost);
@@ -13,7 +13,7 @@
13
13
  #include <stdlib.h> /* exit, free, malloc */
14
14
  #include <string.h> /* memcpy */
15
15
 
16
- #include "../common/types.h"
16
+ #include <brotli/types.h>
17
17
  #include "./port.h"
18
18
 
19
19
  #if defined(__cplusplus) || defined(c_plusplus)
@@ -9,7 +9,7 @@
9
9
  #ifndef BROTLI_ENC_MEMORY_H_
10
10
  #define BROTLI_ENC_MEMORY_H_
11
11
 
12
- #include "../common/types.h"
12
+ #include <brotli/types.h>
13
13
  #include "./port.h"
14
14
 
15
15
  #if defined(__cplusplus) || defined(c_plusplus)
@@ -39,7 +39,8 @@ BROTLI_INTERNAL void BrotliInitMemoryManager(
39
39
  void* opaque);
40
40
 
41
41
  BROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n);
42
- #define BROTLI_ALLOC(M, T, N) ((T*)BrotliAllocate((M), (N) * sizeof(T)))
42
+ #define BROTLI_ALLOC(M, T, N) \
43
+ ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL)
43
44
 
44
45
  BROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p);
45
46
  #define BROTLI_FREE(M, P) { \
@@ -10,7 +10,7 @@
10
10
  #include "./metablock.h"
11
11
 
12
12
  #include "../common/constants.h"
13
- #include "../common/types.h"
13
+ #include <brotli/types.h>
14
14
  #include "./bit_cost.h"
15
15
  #include "./block_splitter.h"
16
16
  #include "./cluster.h"
@@ -40,10 +40,11 @@ void BrotliBuildMetaBlock(MemoryManager* m,
40
40
  static const size_t kMaxNumberOfHistograms = 256;
41
41
  HistogramDistance* distance_histograms;
42
42
  HistogramLiteral* literal_histograms;
43
- ContextType* literal_context_modes;
44
- size_t num_literal_contexts;
45
- size_t num_distance_contexts;
43
+ ContextType* literal_context_modes = NULL;
44
+ size_t literal_histograms_size;
45
+ size_t distance_histograms_size;
46
46
  size_t i;
47
+ size_t literal_context_multiplier = 1;
47
48
 
48
49
  BrotliSplitBlock(m, cmds, num_commands,
49
50
  ringbuffer, pos, mask, params,
@@ -52,20 +53,29 @@ void BrotliBuildMetaBlock(MemoryManager* m,
52
53
  &mb->distance_split);
53
54
  if (BROTLI_IS_OOM(m)) return;
54
55
 
55
- literal_context_modes =
56
- BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types);
57
- if (BROTLI_IS_OOM(m)) return;
58
- for (i = 0; i < mb->literal_split.num_types; ++i) {
59
- literal_context_modes[i] = literal_context_mode;
56
+ if (!params->disable_literal_context_modeling) {
57
+ literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS;
58
+ literal_context_modes =
59
+ BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types);
60
+ if (BROTLI_IS_OOM(m)) return;
61
+ for (i = 0; i < mb->literal_split.num_types; ++i) {
62
+ literal_context_modes[i] = literal_context_mode;
63
+ }
60
64
  }
61
65
 
62
- num_literal_contexts =
63
- mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
64
- num_distance_contexts =
66
+ literal_histograms_size =
67
+ mb->literal_split.num_types * literal_context_multiplier;
68
+ literal_histograms =
69
+ BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size);
70
+ if (BROTLI_IS_OOM(m)) return;
71
+ ClearHistogramsLiteral(literal_histograms, literal_histograms_size);
72
+
73
+ distance_histograms_size =
65
74
  mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
66
- literal_histograms = BROTLI_ALLOC(m, HistogramLiteral, num_literal_contexts);
75
+ distance_histograms =
76
+ BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size);
67
77
  if (BROTLI_IS_OOM(m)) return;
68
- ClearHistogramsLiteral(literal_histograms, num_literal_contexts);
78
+ ClearHistogramsDistance(distance_histograms, distance_histograms_size);
69
79
 
70
80
  assert(mb->command_histograms == 0);
71
81
  mb->command_histograms_size = mb->command_split.num_types;
@@ -73,10 +83,7 @@ void BrotliBuildMetaBlock(MemoryManager* m,
73
83
  BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size);
74
84
  if (BROTLI_IS_OOM(m)) return;
75
85
  ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size);
76
- distance_histograms =
77
- BROTLI_ALLOC(m, HistogramDistance, num_distance_contexts);
78
- if (BROTLI_IS_OOM(m)) return;
79
- ClearHistogramsDistance(distance_histograms, num_distance_contexts);
86
+
80
87
  BrotliBuildHistogramsWithContext(cmds, num_commands,
81
88
  &mb->literal_split, &mb->command_split, &mb->distance_split,
82
89
  ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes,
@@ -89,31 +96,44 @@ void BrotliBuildMetaBlock(MemoryManager* m,
89
96
  mb->literal_context_map =
90
97
  BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);
91
98
  if (BROTLI_IS_OOM(m)) return;
99
+
92
100
  assert(mb->literal_histograms == 0);
93
101
  mb->literal_histograms_size = mb->literal_context_map_size;
94
102
  mb->literal_histograms =
95
103
  BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size);
96
104
  if (BROTLI_IS_OOM(m)) return;
97
- BrotliClusterHistogramsLiteral(m, literal_histograms,
98
- mb->literal_context_map_size,
99
- kMaxNumberOfHistograms,
100
- mb->literal_histograms,
101
- &mb->literal_histograms_size,
102
- mb->literal_context_map);
105
+
106
+ BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size,
107
+ kMaxNumberOfHistograms, mb->literal_histograms,
108
+ &mb->literal_histograms_size, mb->literal_context_map);
103
109
  if (BROTLI_IS_OOM(m)) return;
104
110
  BROTLI_FREE(m, literal_histograms);
105
111
 
112
+ if (params->disable_literal_context_modeling) {
113
+ /* Distribute assignment to all contexts. */
114
+ for (i = mb->literal_split.num_types; i != 0;) {
115
+ size_t j = 0;
116
+ i--;
117
+ for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS); j++) {
118
+ mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =
119
+ mb->literal_context_map[i];
120
+ }
121
+ }
122
+ }
123
+
106
124
  assert(mb->distance_context_map == 0);
107
125
  mb->distance_context_map_size =
108
126
  mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
109
127
  mb->distance_context_map =
110
128
  BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size);
111
129
  if (BROTLI_IS_OOM(m)) return;
130
+
112
131
  assert(mb->distance_histograms == 0);
113
132
  mb->distance_histograms_size = mb->distance_context_map_size;
114
133
  mb->distance_histograms =
115
134
  BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size);
116
135
  if (BROTLI_IS_OOM(m)) return;
136
+
117
137
  BrotliClusterHistogramsDistance(m, distance_histograms,
118
138
  mb->distance_context_map_size,
119
139
  kMaxNumberOfHistograms,
@@ -136,53 +156,7 @@ void BrotliBuildMetaBlock(MemoryManager* m,
136
156
  #include "./metablock_inc.h" /* NOLINT(build/include) */
137
157
  #undef FN
138
158
 
139
- void BrotliBuildMetaBlockGreedy(MemoryManager* m,
140
- const uint8_t* ringbuffer,
141
- size_t pos,
142
- size_t mask,
143
- const Command *commands,
144
- size_t n_commands,
145
- MetaBlockSplit* mb) {
146
- BlockSplitterLiteral lit_blocks;
147
- BlockSplitterCommand cmd_blocks;
148
- BlockSplitterDistance dist_blocks;
149
- size_t num_literals = 0;
150
- size_t i;
151
- for (i = 0; i < n_commands; ++i) {
152
- num_literals += commands[i].insert_len_;
153
- }
154
-
155
- InitBlockSplitterLiteral(m, &lit_blocks, 256, 512, 400.0, num_literals,
156
- &mb->literal_split, &mb->literal_histograms,
157
- &mb->literal_histograms_size);
158
- if (BROTLI_IS_OOM(m)) return;
159
- InitBlockSplitterCommand(m, &cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, 1024,
160
- 500.0, n_commands, &mb->command_split, &mb->command_histograms,
161
- &mb->command_histograms_size);
162
- if (BROTLI_IS_OOM(m)) return;
163
- InitBlockSplitterDistance(m, &dist_blocks, 64, 512, 100.0, n_commands,
164
- &mb->distance_split, &mb->distance_histograms,
165
- &mb->distance_histograms_size);
166
- if (BROTLI_IS_OOM(m)) return;
167
-
168
- for (i = 0; i < n_commands; ++i) {
169
- const Command cmd = commands[i];
170
- size_t j;
171
- BlockSplitterAddSymbolCommand(&cmd_blocks, cmd.cmd_prefix_);
172
- for (j = cmd.insert_len_; j != 0; --j) {
173
- BlockSplitterAddSymbolLiteral(&lit_blocks, ringbuffer[pos & mask]);
174
- ++pos;
175
- }
176
- pos += CommandCopyLen(&cmd);
177
- if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {
178
- BlockSplitterAddSymbolDistance(&dist_blocks, cmd.dist_prefix_);
179
- }
180
- }
181
-
182
- BlockSplitterFinishBlockLiteral(&lit_blocks, /* is_final = */ BROTLI_TRUE);
183
- BlockSplitterFinishBlockCommand(&cmd_blocks, /* is_final = */ BROTLI_TRUE);
184
- BlockSplitterFinishBlockDistance(&dist_blocks, /* is_final = */ BROTLI_TRUE);
185
- }
159
+ #define BROTLI_MAX_STATIC_CONTEXTS 13
186
160
 
187
161
  /* Greedy block splitter for one block category (literal, command or distance).
188
162
  Gathers histograms for all context buckets. */
@@ -214,7 +188,7 @@ typedef struct ContextBlockSplitter {
214
188
  /* Offset of the histograms of the previous two block types. */
215
189
  size_t last_histogram_ix_[2];
216
190
  /* Entropy of the previous two block types. */
217
- double* last_entropy_;
191
+ double last_entropy_[2 * BROTLI_MAX_STATIC_CONTEXTS];
218
192
  /* The number of times we merged the current block with the last one. */
219
193
  size_t merge_last_count_;
220
194
  } ContextBlockSplitter;
@@ -226,6 +200,7 @@ static void InitContextBlockSplitter(
226
200
  size_t* histograms_size) {
227
201
  size_t max_num_blocks = num_symbols / min_block_size + 1;
228
202
  size_t max_num_types;
203
+ assert(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS);
229
204
 
230
205
  self->alphabet_size_ = alphabet_size;
231
206
  self->num_contexts_ = num_contexts;
@@ -250,29 +225,23 @@ static void InitContextBlockSplitter(
250
225
  split->lengths, split->lengths_alloc_size, max_num_blocks);
251
226
  if (BROTLI_IS_OOM(m)) return;
252
227
  split->num_blocks = max_num_blocks;
253
- self->last_entropy_ = BROTLI_ALLOC(m, double, 2 * num_contexts);
254
228
  if (BROTLI_IS_OOM(m)) return;
255
229
  assert(*histograms == 0);
256
230
  *histograms_size = max_num_types * num_contexts;
257
231
  *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size);
258
232
  self->histograms_ = *histograms;
259
233
  if (BROTLI_IS_OOM(m)) return;
260
- /* Clear only current historgram. */
234
+ /* Clear only current histogram. */
261
235
  ClearHistogramsLiteral(&self->histograms_[0], num_contexts);
262
236
  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;
263
237
  }
264
238
 
265
- static void CleanupContextBlockSplitter(
266
- MemoryManager* m, ContextBlockSplitter* self) {
267
- BROTLI_FREE(m, self->last_entropy_);
268
- }
269
-
270
239
  /* Does either of three things:
271
240
  (1) emits the current block with a new block type;
272
241
  (2) emits the current block with the type of the second last block;
273
242
  (3) merges the current block with the last block. */
274
243
  static void ContextBlockSplitterFinishBlock(
275
- MemoryManager* m, ContextBlockSplitter* self, BROTLI_BOOL is_final) {
244
+ ContextBlockSplitter* self, MemoryManager* m, BROTLI_BOOL is_final) {
276
245
  BlockSplit* split = self->split_;
277
246
  const size_t num_contexts = self->num_contexts_;
278
247
  double* last_entropy = self->last_entropy_;
@@ -305,10 +274,10 @@ static void ContextBlockSplitterFinishBlock(
305
274
  respective set of histograms for the last and second last block types.
306
275
  Decide over the split based on the total reduction of entropy across
307
276
  all contexts. */
308
- double* entropy = BROTLI_ALLOC(m, double, num_contexts);
277
+ double entropy[BROTLI_MAX_STATIC_CONTEXTS];
309
278
  HistogramLiteral* combined_histo =
310
279
  BROTLI_ALLOC(m, HistogramLiteral, 2 * num_contexts);
311
- double* combined_entropy = BROTLI_ALLOC(m, double, 2 * num_contexts);
280
+ double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS];
312
281
  double diff[2] = { 0.0 };
313
282
  size_t i;
314
283
  if (BROTLI_IS_OOM(m)) return;
@@ -383,9 +352,7 @@ static void ContextBlockSplitterFinishBlock(
383
352
  self->target_block_size_ += self->min_block_size_;
384
353
  }
385
354
  }
386
- BROTLI_FREE(m, combined_entropy);
387
355
  BROTLI_FREE(m, combined_histo);
388
- BROTLI_FREE(m, entropy);
389
356
  }
390
357
  if (is_final) {
391
358
  *self->histograms_size_ = split->num_types * num_contexts;
@@ -395,30 +362,49 @@ static void ContextBlockSplitterFinishBlock(
395
362
 
396
363
  /* Adds the next symbol to the current block type and context. When the
397
364
  current block reaches the target size, decides on merging the block. */
398
- static void ContextBlockSplitterAddSymbol(MemoryManager* m,
399
- ContextBlockSplitter* self, size_t symbol, size_t context) {
365
+ static void ContextBlockSplitterAddSymbol(
366
+ ContextBlockSplitter* self, MemoryManager* m,
367
+ size_t symbol, size_t context) {
400
368
  HistogramAddLiteral(&self->histograms_[self->curr_histogram_ix_ + context],
401
369
  symbol);
402
370
  ++self->block_size_;
403
371
  if (self->block_size_ == self->target_block_size_) {
404
- ContextBlockSplitterFinishBlock(m, self, /* is_final = */ BROTLI_FALSE);
372
+ ContextBlockSplitterFinishBlock(self, m, /* is_final = */ BROTLI_FALSE);
405
373
  if (BROTLI_IS_OOM(m)) return;
406
374
  }
407
375
  }
408
376
 
409
- void BrotliBuildMetaBlockGreedyWithContexts(MemoryManager* m,
410
- const uint8_t* ringbuffer,
411
- size_t pos,
412
- size_t mask,
413
- uint8_t prev_byte,
414
- uint8_t prev_byte2,
415
- ContextType literal_context_mode,
416
- size_t num_contexts,
417
- const uint32_t* static_context_map,
418
- const Command *commands,
419
- size_t n_commands,
420
- MetaBlockSplit* mb) {
421
- ContextBlockSplitter lit_blocks;
377
+ static void MapStaticContexts(MemoryManager* m,
378
+ size_t num_contexts,
379
+ const uint32_t* static_context_map,
380
+ MetaBlockSplit* mb) {
381
+ size_t i;
382
+ assert(mb->literal_context_map == 0);
383
+ mb->literal_context_map_size =
384
+ mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
385
+ mb->literal_context_map =
386
+ BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);
387
+ if (BROTLI_IS_OOM(m)) return;
388
+
389
+ for (i = 0; i < mb->literal_split.num_types; ++i) {
390
+ uint32_t offset = (uint32_t)(i * num_contexts);
391
+ size_t j;
392
+ for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) {
393
+ mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =
394
+ offset + static_context_map[j];
395
+ }
396
+ }
397
+ }
398
+
399
+ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
400
+ MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,
401
+ uint8_t prev_byte, uint8_t prev_byte2, ContextType literal_context_mode,
402
+ const size_t num_contexts, const uint32_t* static_context_map,
403
+ const Command *commands, size_t n_commands, MetaBlockSplit* mb) {
404
+ union {
405
+ BlockSplitterLiteral plain;
406
+ ContextBlockSplitter ctx;
407
+ } lit_blocks;
422
408
  BlockSplitterCommand cmd_blocks;
423
409
  BlockSplitterDistance dist_blocks;
424
410
  size_t num_literals = 0;
@@ -427,9 +413,15 @@ void BrotliBuildMetaBlockGreedyWithContexts(MemoryManager* m,
427
413
  num_literals += commands[i].insert_len_;
428
414
  }
429
415
 
430
- InitContextBlockSplitter(m, &lit_blocks, 256, num_contexts, 512, 400.0,
431
- num_literals, &mb->literal_split, &mb->literal_histograms,
432
- &mb->literal_histograms_size);
416
+ if (num_contexts == 1) {
417
+ InitBlockSplitterLiteral(m, &lit_blocks.plain, 256, 512, 400.0,
418
+ num_literals, &mb->literal_split, &mb->literal_histograms,
419
+ &mb->literal_histograms_size);
420
+ } else {
421
+ InitContextBlockSplitter(m, &lit_blocks.ctx, 256, num_contexts, 512, 400.0,
422
+ num_literals, &mb->literal_split, &mb->literal_histograms,
423
+ &mb->literal_histograms_size);
424
+ }
433
425
  if (BROTLI_IS_OOM(m)) return;
434
426
  InitBlockSplitterCommand(m, &cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, 1024,
435
427
  500.0, n_commands, &mb->command_split, &mb->command_histograms,
@@ -445,12 +437,16 @@ void BrotliBuildMetaBlockGreedyWithContexts(MemoryManager* m,
445
437
  size_t j;
446
438
  BlockSplitterAddSymbolCommand(&cmd_blocks, cmd.cmd_prefix_);
447
439
  for (j = cmd.insert_len_; j != 0; --j) {
448
- size_t context = Context(prev_byte, prev_byte2, literal_context_mode);
449
440
  uint8_t literal = ringbuffer[pos & mask];
450
- ContextBlockSplitterAddSymbol(
451
- m, &lit_blocks, literal, static_context_map[context]);
441
+ if (num_contexts == 1) {
442
+ BlockSplitterAddSymbolLiteral(&lit_blocks.plain, literal);
443
+ } else {
444
+ size_t context = Context(prev_byte, prev_byte2, literal_context_mode);
445
+ ContextBlockSplitterAddSymbol(&lit_blocks.ctx, m, literal,
446
+ static_context_map[context]);
447
+ if (BROTLI_IS_OOM(m)) return;
448
+ }
452
449
  prev_byte2 = prev_byte;
453
- if (BROTLI_IS_OOM(m)) return;
454
450
  prev_byte = literal;
455
451
  ++pos;
456
452
  }
@@ -464,25 +460,41 @@ void BrotliBuildMetaBlockGreedyWithContexts(MemoryManager* m,
464
460
  }
465
461
  }
466
462
 
467
- ContextBlockSplitterFinishBlock(m, &lit_blocks, /* is_final = */ BROTLI_TRUE);
468
- if (BROTLI_IS_OOM(m)) return;
469
- CleanupContextBlockSplitter(m, &lit_blocks);
463
+ if (num_contexts == 1) {
464
+ BlockSplitterFinishBlockLiteral(
465
+ &lit_blocks.plain, /* is_final = */ BROTLI_TRUE);
466
+ } else {
467
+ ContextBlockSplitterFinishBlock(
468
+ &lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);
469
+ if (BROTLI_IS_OOM(m)) return;
470
+ }
470
471
  BlockSplitterFinishBlockCommand(&cmd_blocks, /* is_final = */ BROTLI_TRUE);
471
472
  BlockSplitterFinishBlockDistance(&dist_blocks, /* is_final = */ BROTLI_TRUE);
472
473
 
473
- assert(mb->literal_context_map == 0);
474
- mb->literal_context_map_size =
475
- mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
476
- mb->literal_context_map =
477
- BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);
478
- if (BROTLI_IS_OOM(m)) return;
474
+ if (num_contexts > 1) {
475
+ MapStaticContexts(m, num_contexts, static_context_map, mb);
476
+ }
477
+ }
479
478
 
480
- for (i = 0; i < mb->literal_split.num_types; ++i) {
481
- size_t j;
482
- for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) {
483
- mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =
484
- (uint32_t)(i * num_contexts) + static_context_map[j];
485
- }
479
+ void BrotliBuildMetaBlockGreedy(MemoryManager* m,
480
+ const uint8_t* ringbuffer,
481
+ size_t pos,
482
+ size_t mask,
483
+ uint8_t prev_byte,
484
+ uint8_t prev_byte2,
485
+ ContextType literal_context_mode,
486
+ size_t num_contexts,
487
+ const uint32_t* static_context_map,
488
+ const Command* commands,
489
+ size_t n_commands,
490
+ MetaBlockSplit* mb) {
491
+ if (num_contexts == 1) {
492
+ BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
493
+ prev_byte2, literal_context_mode, 1, NULL, commands, n_commands, mb);
494
+ } else {
495
+ BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
496
+ prev_byte2, literal_context_mode, num_contexts, static_context_map,
497
+ commands, n_commands, mb);
486
498
  }
487
499
  }
488
500
 
@@ -502,7 +514,8 @@ void BrotliOptimizeHistograms(size_t num_direct_distance_codes,
502
514
  good_for_rle);
503
515
  }
504
516
  num_distance_codes = BROTLI_NUM_DISTANCE_SHORT_CODES +
505
- num_direct_distance_codes + (48u << distance_postfix_bits);
517
+ num_direct_distance_codes +
518
+ ((2 * BROTLI_MAX_DISTANCE_BITS) << distance_postfix_bits);
506
519
  for (i = 0; i < mb->distance_histograms_size; ++i) {
507
520
  BrotliOptimizeHuffmanCountsForRle(num_distance_codes,
508
521
  mb->distance_histograms[i].data_,