brotli 0.2.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +37 -0
  3. data/.github/workflows/publish.yml +24 -0
  4. data/.gitmodules +1 -1
  5. data/Gemfile +6 -3
  6. data/README.md +2 -2
  7. data/Rakefile +16 -9
  8. data/brotli.gemspec +7 -13
  9. data/ext/brotli/brotli.c +210 -31
  10. data/ext/brotli/buffer.c +1 -7
  11. data/ext/brotli/buffer.h +1 -1
  12. data/ext/brotli/extconf.rb +25 -17
  13. data/lib/brotli/version.rb +1 -1
  14. data/test/brotli_test.rb +107 -0
  15. data/test/brotli_writer_test.rb +36 -0
  16. data/test/test_helper.rb +8 -0
  17. data/vendor/brotli/c/common/constants.c +15 -0
  18. data/vendor/brotli/c/common/constants.h +137 -0
  19. data/vendor/brotli/c/common/context.c +156 -0
  20. data/vendor/brotli/c/common/context.h +4 -152
  21. data/vendor/brotli/c/common/dictionary.bin.br +0 -0
  22. data/vendor/brotli/c/common/dictionary.c +14 -3
  23. data/vendor/brotli/c/common/platform.c +23 -0
  24. data/vendor/brotli/c/common/platform.h +95 -122
  25. data/vendor/brotli/c/common/shared_dictionary.c +521 -0
  26. data/vendor/brotli/c/common/shared_dictionary_internal.h +75 -0
  27. data/vendor/brotli/c/common/transform.c +60 -4
  28. data/vendor/brotli/c/common/transform.h +5 -0
  29. data/vendor/brotli/c/common/version.h +31 -6
  30. data/vendor/brotli/c/dec/bit_reader.c +34 -4
  31. data/vendor/brotli/c/dec/bit_reader.h +221 -107
  32. data/vendor/brotli/c/dec/decode.c +772 -403
  33. data/vendor/brotli/c/dec/huffman.c +7 -4
  34. data/vendor/brotli/c/dec/huffman.h +8 -13
  35. data/vendor/brotli/c/dec/prefix.h +1 -18
  36. data/vendor/brotli/c/dec/state.c +40 -21
  37. data/vendor/brotli/c/dec/state.h +201 -59
  38. data/vendor/brotli/c/enc/backward_references.c +88 -25
  39. data/vendor/brotli/c/enc/backward_references.h +10 -8
  40. data/vendor/brotli/c/enc/backward_references_hq.c +194 -80
  41. data/vendor/brotli/c/enc/backward_references_hq.h +17 -13
  42. data/vendor/brotli/c/enc/backward_references_inc.h +52 -16
  43. data/vendor/brotli/c/enc/bit_cost.c +8 -7
  44. data/vendor/brotli/c/enc/bit_cost.h +5 -4
  45. data/vendor/brotli/c/enc/block_splitter.c +40 -17
  46. data/vendor/brotli/c/enc/block_splitter.h +5 -4
  47. data/vendor/brotli/c/enc/block_splitter_inc.h +99 -49
  48. data/vendor/brotli/c/enc/brotli_bit_stream.c +142 -137
  49. data/vendor/brotli/c/enc/brotli_bit_stream.h +11 -6
  50. data/vendor/brotli/c/enc/cluster.c +10 -9
  51. data/vendor/brotli/c/enc/cluster.h +7 -6
  52. data/vendor/brotli/c/enc/cluster_inc.h +30 -22
  53. data/vendor/brotli/c/enc/command.c +28 -0
  54. data/vendor/brotli/c/enc/command.h +17 -16
  55. data/vendor/brotli/c/enc/compound_dictionary.c +207 -0
  56. data/vendor/brotli/c/enc/compound_dictionary.h +74 -0
  57. data/vendor/brotli/c/enc/compress_fragment.c +93 -83
  58. data/vendor/brotli/c/enc/compress_fragment.h +32 -7
  59. data/vendor/brotli/c/enc/compress_fragment_two_pass.c +100 -88
  60. data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
  61. data/vendor/brotli/c/enc/dictionary_hash.c +1829 -1101
  62. data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
  63. data/vendor/brotli/c/enc/encode.c +550 -416
  64. data/vendor/brotli/c/enc/encoder_dict.c +613 -5
  65. data/vendor/brotli/c/enc/encoder_dict.h +120 -4
  66. data/vendor/brotli/c/enc/entropy_encode.c +5 -2
  67. data/vendor/brotli/c/enc/entropy_encode.h +4 -3
  68. data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
  69. data/vendor/brotli/c/enc/fast_log.c +105 -0
  70. data/vendor/brotli/c/enc/fast_log.h +21 -101
  71. data/vendor/brotli/c/enc/find_match_length.h +17 -25
  72. data/vendor/brotli/c/enc/hash.h +350 -120
  73. data/vendor/brotli/c/enc/hash_composite_inc.h +71 -67
  74. data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +92 -51
  75. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +79 -84
  76. data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -54
  77. data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +93 -62
  78. data/vendor/brotli/c/enc/hash_rolling_inc.h +25 -29
  79. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +42 -40
  80. data/vendor/brotli/c/enc/histogram.c +4 -4
  81. data/vendor/brotli/c/enc/histogram.h +7 -6
  82. data/vendor/brotli/c/enc/literal_cost.c +20 -15
  83. data/vendor/brotli/c/enc/literal_cost.h +4 -2
  84. data/vendor/brotli/c/enc/memory.c +29 -5
  85. data/vendor/brotli/c/enc/memory.h +43 -14
  86. data/vendor/brotli/c/enc/metablock.c +95 -85
  87. data/vendor/brotli/c/enc/metablock.h +9 -8
  88. data/vendor/brotli/c/enc/metablock_inc.h +9 -7
  89. data/vendor/brotli/c/enc/params.h +7 -4
  90. data/vendor/brotli/c/enc/prefix.h +3 -2
  91. data/vendor/brotli/c/enc/quality.h +40 -3
  92. data/vendor/brotli/c/enc/ringbuffer.h +8 -4
  93. data/vendor/brotli/c/enc/state.h +104 -0
  94. data/vendor/brotli/c/enc/static_dict.c +60 -4
  95. data/vendor/brotli/c/enc/static_dict.h +3 -2
  96. data/vendor/brotli/c/enc/static_dict_lut.h +2 -0
  97. data/vendor/brotli/c/enc/utf8_util.c +2 -2
  98. data/vendor/brotli/c/enc/utf8_util.h +2 -1
  99. data/vendor/brotli/c/enc/write_bits.h +29 -26
  100. data/vendor/brotli/c/include/brotli/decode.h +67 -2
  101. data/vendor/brotli/c/include/brotli/encode.h +77 -3
  102. data/vendor/brotli/c/include/brotli/port.h +34 -3
  103. data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
  104. metadata +23 -97
  105. data/.travis.yml +0 -31
  106. data/docs/Brotli/Error.html +0 -124
  107. data/docs/Brotli.html +0 -485
  108. data/docs/_index.html +0 -122
  109. data/docs/class_list.html +0 -51
  110. data/docs/css/common.css +0 -1
  111. data/docs/css/full_list.css +0 -58
  112. data/docs/css/style.css +0 -496
  113. data/docs/file.README.html +0 -127
  114. data/docs/file_list.html +0 -56
  115. data/docs/frames.html +0 -17
  116. data/docs/index.html +0 -127
  117. data/docs/js/app.js +0 -292
  118. data/docs/js/full_list.js +0 -216
  119. data/docs/js/jquery.js +0 -4
  120. data/docs/method_list.html +0 -67
  121. data/docs/top-level-namespace.html +0 -110
  122. data/spec/brotli_spec.rb +0 -88
  123. data/spec/inflate_spec.rb +0 -75
  124. data/spec/spec_helper.rb +0 -4
@@ -7,55 +7,51 @@
7
7
  /* Algorithms for distributing the literals and commands of a metablock between
8
8
  block types and contexts. */
9
9
 
10
- #include "./metablock.h"
10
+ #include "metablock.h"
11
+
12
+ #include <brotli/types.h>
11
13
 
12
14
  #include "../common/constants.h"
13
15
  #include "../common/context.h"
14
16
  #include "../common/platform.h"
15
- #include <brotli/types.h>
16
- #include "./bit_cost.h"
17
- #include "./block_splitter.h"
18
- #include "./cluster.h"
19
- #include "./entropy_encode.h"
20
- #include "./histogram.h"
21
- #include "./memory.h"
22
- #include "./quality.h"
17
+ #include "bit_cost.h"
18
+ #include "block_splitter.h"
19
+ #include "cluster.h"
20
+ #include "entropy_encode.h"
21
+ #include "histogram.h"
22
+ #include "memory.h"
23
+ #include "quality.h"
23
24
 
24
25
  #if defined(__cplusplus) || defined(c_plusplus)
25
26
  extern "C" {
26
27
  #endif
27
28
 
28
- void BrotliInitDistanceParams(BrotliEncoderParams* params,
29
- uint32_t npostfix, uint32_t ndirect) {
30
- BrotliDistanceParams* dist_params = &params->dist;
31
- uint32_t alphabet_size, max_distance;
29
+ void BrotliInitDistanceParams(BrotliDistanceParams* dist_params,
30
+ uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) {
31
+ uint32_t alphabet_size_max;
32
+ uint32_t alphabet_size_limit;
33
+ uint32_t max_distance;
32
34
 
33
35
  dist_params->distance_postfix_bits = npostfix;
34
36
  dist_params->num_direct_distance_codes = ndirect;
35
37
 
36
- alphabet_size = BROTLI_DISTANCE_ALPHABET_SIZE(
38
+ alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
37
39
  npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);
40
+ alphabet_size_limit = alphabet_size_max;
38
41
  max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) -
39
42
  (1U << (npostfix + 2));
40
43
 
41
- if (params->large_window) {
42
- static const uint32_t bound[BROTLI_MAX_NPOSTFIX + 1] = {0, 4, 12, 28};
43
- uint32_t postfix = 1U << npostfix;
44
- alphabet_size = BROTLI_DISTANCE_ALPHABET_SIZE(
44
+ if (large_window) {
45
+ BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
46
+ BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);
47
+ alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
45
48
  npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);
46
- /* The maximum distance is set so that no distance symbol used can encode
47
- a distance larger than BROTLI_MAX_ALLOWED_DISTANCE with all
48
- its extra bits set. */
49
- if (ndirect < bound[npostfix]) {
50
- max_distance = BROTLI_MAX_ALLOWED_DISTANCE - (bound[npostfix] - ndirect);
51
- } else if (ndirect >= bound[npostfix] + postfix) {
52
- max_distance = (3U << 29) - 4 + (ndirect - bound[npostfix]);
53
- } else {
54
- max_distance = BROTLI_MAX_ALLOWED_DISTANCE;
55
- }
49
+ alphabet_size_limit = limit.max_alphabet_size;
50
+ max_distance = limit.max_distance;
56
51
  }
57
52
 
58
- dist_params->alphabet_size = alphabet_size;
53
+ dist_params->alphabet_size_max = alphabet_size_max;
54
+ dist_params->alphabet_size_limit = alphabet_size_limit;
59
55
  dist_params->max_distance = max_distance;
60
56
  }
61
57
 
@@ -87,14 +83,14 @@ static BROTLI_BOOL ComputeDistanceCost(const Command* cmds,
87
83
  size_t num_commands,
88
84
  const BrotliDistanceParams* orig_params,
89
85
  const BrotliDistanceParams* new_params,
90
- double* cost) {
86
+ double* cost,
87
+ HistogramDistance* tmp) {
91
88
  size_t i;
92
89
  BROTLI_BOOL equal_params = BROTLI_FALSE;
93
90
  uint16_t dist_prefix;
94
91
  uint32_t dist_extra;
95
92
  double extra_bits = 0.0;
96
- HistogramDistance histo;
97
- HistogramClearDistance(&histo);
93
+ HistogramClearDistance(tmp);
98
94
 
99
95
  if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&
100
96
  orig_params->num_direct_distance_codes ==
@@ -118,12 +114,12 @@ static BROTLI_BOOL ComputeDistanceCost(const Command* cmds,
118
114
  &dist_prefix,
119
115
  &dist_extra);
120
116
  }
121
- HistogramAddDistance(&histo, dist_prefix & 0x3FF);
117
+ HistogramAddDistance(tmp, dist_prefix & 0x3FF);
122
118
  extra_bits += dist_prefix >> 10;
123
119
  }
124
120
  }
125
121
 
126
- *cost = BrotliPopulationCostDistance(&histo) + extra_bits;
122
+ *cost = BrotliPopulationCostDistance(tmp) + extra_bits;
127
123
  return BROTLI_TRUE;
128
124
  }
129
125
 
@@ -151,43 +147,46 @@ void BrotliBuildMetaBlock(MemoryManager* m,
151
147
  uint32_t ndirect_msb = 0;
152
148
  BROTLI_BOOL check_orig = BROTLI_TRUE;
153
149
  double best_dist_cost = 1e99;
154
- BrotliEncoderParams orig_params = *params;
155
- BrotliEncoderParams new_params = *params;
150
+ BrotliDistanceParams orig_params = params->dist;
151
+ BrotliDistanceParams new_params = params->dist;
152
+ HistogramDistance* tmp = BROTLI_ALLOC(m, HistogramDistance, 1);
153
+
154
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return;
156
155
 
157
156
  for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX; npostfix++) {
158
157
  for (; ndirect_msb < 16; ndirect_msb++) {
159
158
  uint32_t ndirect = ndirect_msb << npostfix;
160
159
  BROTLI_BOOL skip;
161
160
  double dist_cost;
162
- BrotliInitDistanceParams(&new_params, npostfix, ndirect);
163
- if (npostfix == orig_params.dist.distance_postfix_bits &&
164
- ndirect == orig_params.dist.num_direct_distance_codes) {
161
+ BrotliInitDistanceParams(&new_params, npostfix, ndirect,
162
+ params->large_window);
163
+ if (npostfix == orig_params.distance_postfix_bits &&
164
+ ndirect == orig_params.num_direct_distance_codes) {
165
165
  check_orig = BROTLI_FALSE;
166
166
  }
167
167
  skip = !ComputeDistanceCost(
168
- cmds, num_commands,
169
- &orig_params.dist, &new_params.dist, &dist_cost);
168
+ cmds, num_commands, &orig_params, &new_params, &dist_cost, tmp);
170
169
  if (skip || (dist_cost > best_dist_cost)) {
171
170
  break;
172
171
  }
173
172
  best_dist_cost = dist_cost;
174
- params->dist = new_params.dist;
173
+ params->dist = new_params;
175
174
  }
176
175
  if (ndirect_msb > 0) ndirect_msb--;
177
176
  ndirect_msb /= 2;
178
177
  }
179
178
  if (check_orig) {
180
179
  double dist_cost;
181
- ComputeDistanceCost(cmds, num_commands,
182
- &orig_params.dist, &orig_params.dist, &dist_cost);
180
+ ComputeDistanceCost(cmds, num_commands, &orig_params, &orig_params,
181
+ &dist_cost, tmp);
183
182
  if (dist_cost < best_dist_cost) {
184
183
  /* NB: currently unused; uncomment when more param tuning is added. */
185
184
  /* best_dist_cost = dist_cost; */
186
- params->dist = orig_params.dist;
185
+ params->dist = orig_params;
187
186
  }
188
187
  }
189
- RecomputeDistancePrefixes(cmds, num_commands,
190
- &orig_params.dist, &params->dist);
188
+ BROTLI_FREE(m, tmp);
189
+ RecomputeDistancePrefixes(cmds, num_commands, &orig_params, &params->dist);
191
190
 
192
191
  BrotliSplitBlock(m, cmds, num_commands,
193
192
  ringbuffer, pos, mask, params,
@@ -200,7 +199,7 @@ void BrotliBuildMetaBlock(MemoryManager* m,
200
199
  literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS;
201
200
  literal_context_modes =
202
201
  BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types);
203
- if (BROTLI_IS_OOM(m)) return;
202
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_context_modes)) return;
204
203
  for (i = 0; i < mb->literal_split.num_types; ++i) {
205
204
  literal_context_modes[i] = literal_context_mode;
206
205
  }
@@ -210,21 +209,21 @@ void BrotliBuildMetaBlock(MemoryManager* m,
210
209
  mb->literal_split.num_types * literal_context_multiplier;
211
210
  literal_histograms =
212
211
  BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size);
213
- if (BROTLI_IS_OOM(m)) return;
212
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_histograms)) return;
214
213
  ClearHistogramsLiteral(literal_histograms, literal_histograms_size);
215
214
 
216
215
  distance_histograms_size =
217
216
  mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
218
217
  distance_histograms =
219
218
  BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size);
220
- if (BROTLI_IS_OOM(m)) return;
219
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_histograms)) return;
221
220
  ClearHistogramsDistance(distance_histograms, distance_histograms_size);
222
221
 
223
222
  BROTLI_DCHECK(mb->command_histograms == 0);
224
223
  mb->command_histograms_size = mb->command_split.num_types;
225
224
  mb->command_histograms =
226
225
  BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size);
227
- if (BROTLI_IS_OOM(m)) return;
226
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->command_histograms)) return;
228
227
  ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size);
229
228
 
230
229
  BrotliBuildHistogramsWithContext(cmds, num_commands,
@@ -238,13 +237,13 @@ void BrotliBuildMetaBlock(MemoryManager* m,
238
237
  mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
239
238
  mb->literal_context_map =
240
239
  BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);
241
- if (BROTLI_IS_OOM(m)) return;
240
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return;
242
241
 
243
242
  BROTLI_DCHECK(mb->literal_histograms == 0);
244
243
  mb->literal_histograms_size = mb->literal_context_map_size;
245
244
  mb->literal_histograms =
246
245
  BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size);
247
- if (BROTLI_IS_OOM(m)) return;
246
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_histograms)) return;
248
247
 
249
248
  BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size,
250
249
  kMaxNumberOfHistograms, mb->literal_histograms,
@@ -269,13 +268,13 @@ void BrotliBuildMetaBlock(MemoryManager* m,
269
268
  mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;
270
269
  mb->distance_context_map =
271
270
  BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size);
272
- if (BROTLI_IS_OOM(m)) return;
271
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_context_map)) return;
273
272
 
274
273
  BROTLI_DCHECK(mb->distance_histograms == 0);
275
274
  mb->distance_histograms_size = mb->distance_context_map_size;
276
275
  mb->distance_histograms =
277
276
  BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size);
278
- if (BROTLI_IS_OOM(m)) return;
277
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_histograms)) return;
279
278
 
280
279
  BrotliClusterHistogramsDistance(m, distance_histograms,
281
280
  mb->distance_context_map_size,
@@ -288,15 +287,15 @@ void BrotliBuildMetaBlock(MemoryManager* m,
288
287
  }
289
288
 
290
289
  #define FN(X) X ## Literal
291
- #include "./metablock_inc.h" /* NOLINT(build/include) */
290
+ #include "metablock_inc.h" /* NOLINT(build/include) */
292
291
  #undef FN
293
292
 
294
293
  #define FN(X) X ## Command
295
- #include "./metablock_inc.h" /* NOLINT(build/include) */
294
+ #include "metablock_inc.h" /* NOLINT(build/include) */
296
295
  #undef FN
297
296
 
298
297
  #define FN(X) X ## Distance
299
- #include "./metablock_inc.h" /* NOLINT(build/include) */
298
+ #include "metablock_inc.h" /* NOLINT(build/include) */
300
299
  #undef FN
301
300
 
302
301
  #define BROTLI_MAX_STATIC_CONTEXTS 13
@@ -373,7 +372,7 @@ static void InitContextBlockSplitter(
373
372
  *histograms_size = max_num_types * num_contexts;
374
373
  *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size);
375
374
  self->histograms_ = *histograms;
376
- if (BROTLI_IS_OOM(m)) return;
375
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return;
377
376
  /* Clear only current histogram. */
378
377
  ClearHistogramsLiteral(&self->histograms_[0], num_contexts);
379
378
  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;
@@ -423,7 +422,7 @@ static void ContextBlockSplitterFinishBlock(
423
422
  double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS];
424
423
  double diff[2] = { 0.0 };
425
424
  size_t i;
426
- if (BROTLI_IS_OOM(m)) return;
425
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(combined_histo)) return;
427
426
  for (i = 0; i < num_contexts; ++i) {
428
427
  size_t curr_histo_ix = self->curr_histogram_ix_ + i;
429
428
  size_t j;
@@ -527,7 +526,7 @@ static void MapStaticContexts(MemoryManager* m,
527
526
  mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;
528
527
  mb->literal_context_map =
529
528
  BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);
530
- if (BROTLI_IS_OOM(m)) return;
529
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return;
531
530
 
532
531
  for (i = 0; i < mb->literal_split.num_types; ++i) {
533
532
  uint32_t offset = (uint32_t)(i * num_contexts);
@@ -539,17 +538,21 @@ static void MapStaticContexts(MemoryManager* m,
539
538
  }
540
539
  }
541
540
 
542
- static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
543
- MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,
544
- uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,
545
- const size_t num_contexts, const uint32_t* static_context_map,
546
- const Command* commands, size_t n_commands, MetaBlockSplit* mb) {
541
+ typedef struct GreedyMetablockArena {
547
542
  union {
548
543
  BlockSplitterLiteral plain;
549
544
  ContextBlockSplitter ctx;
550
545
  } lit_blocks;
551
546
  BlockSplitterCommand cmd_blocks;
552
547
  BlockSplitterDistance dist_blocks;
548
+ } GreedyMetablockArena;
549
+
550
+ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
551
+ MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer,
552
+ size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2,
553
+ ContextLut literal_context_lut, const size_t num_contexts,
554
+ const uint32_t* static_context_map, const Command* commands,
555
+ size_t n_commands, MetaBlockSplit* mb) {
553
556
  size_t num_literals = 0;
554
557
  size_t i;
555
558
  for (i = 0; i < n_commands; ++i) {
@@ -557,20 +560,20 @@ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
557
560
  }
558
561
 
559
562
  if (num_contexts == 1) {
560
- InitBlockSplitterLiteral(m, &lit_blocks.plain, 256, 512, 400.0,
563
+ InitBlockSplitterLiteral(m, &arena->lit_blocks.plain, 256, 512, 400.0,
561
564
  num_literals, &mb->literal_split, &mb->literal_histograms,
562
565
  &mb->literal_histograms_size);
563
566
  } else {
564
- InitContextBlockSplitter(m, &lit_blocks.ctx, 256, num_contexts, 512, 400.0,
565
- num_literals, &mb->literal_split, &mb->literal_histograms,
567
+ InitContextBlockSplitter(m, &arena->lit_blocks.ctx, 256, num_contexts, 512,
568
+ 400.0, num_literals, &mb->literal_split, &mb->literal_histograms,
566
569
  &mb->literal_histograms_size);
567
570
  }
568
571
  if (BROTLI_IS_OOM(m)) return;
569
- InitBlockSplitterCommand(m, &cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, 1024,
570
- 500.0, n_commands, &mb->command_split, &mb->command_histograms,
572
+ InitBlockSplitterCommand(m, &arena->cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS,
573
+ 1024, 500.0, n_commands, &mb->command_split, &mb->command_histograms,
571
574
  &mb->command_histograms_size);
572
575
  if (BROTLI_IS_OOM(m)) return;
573
- InitBlockSplitterDistance(m, &dist_blocks, 64, 512, 100.0, n_commands,
576
+ InitBlockSplitterDistance(m, &arena->dist_blocks, 64, 512, 100.0, n_commands,
574
577
  &mb->distance_split, &mb->distance_histograms,
575
578
  &mb->distance_histograms_size);
576
579
  if (BROTLI_IS_OOM(m)) return;
@@ -578,15 +581,15 @@ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
578
581
  for (i = 0; i < n_commands; ++i) {
579
582
  const Command cmd = commands[i];
580
583
  size_t j;
581
- BlockSplitterAddSymbolCommand(&cmd_blocks, cmd.cmd_prefix_);
584
+ BlockSplitterAddSymbolCommand(&arena->cmd_blocks, cmd.cmd_prefix_);
582
585
  for (j = cmd.insert_len_; j != 0; --j) {
583
586
  uint8_t literal = ringbuffer[pos & mask];
584
587
  if (num_contexts == 1) {
585
- BlockSplitterAddSymbolLiteral(&lit_blocks.plain, literal);
588
+ BlockSplitterAddSymbolLiteral(&arena->lit_blocks.plain, literal);
586
589
  } else {
587
590
  size_t context =
588
591
  BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);
589
- ContextBlockSplitterAddSymbol(&lit_blocks.ctx, m, literal,
592
+ ContextBlockSplitterAddSymbol(&arena->lit_blocks.ctx, m, literal,
590
593
  static_context_map[context]);
591
594
  if (BROTLI_IS_OOM(m)) return;
592
595
  }
@@ -599,21 +602,24 @@ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
599
602
  prev_byte2 = ringbuffer[(pos - 2) & mask];
600
603
  prev_byte = ringbuffer[(pos - 1) & mask];
601
604
  if (cmd.cmd_prefix_ >= 128) {
602
- BlockSplitterAddSymbolDistance(&dist_blocks, cmd.dist_prefix_ & 0x3FF);
605
+ BlockSplitterAddSymbolDistance(
606
+ &arena->dist_blocks, cmd.dist_prefix_ & 0x3FF);
603
607
  }
604
608
  }
605
609
  }
606
610
 
607
611
  if (num_contexts == 1) {
608
612
  BlockSplitterFinishBlockLiteral(
609
- &lit_blocks.plain, /* is_final = */ BROTLI_TRUE);
613
+ &arena->lit_blocks.plain, /* is_final = */ BROTLI_TRUE);
610
614
  } else {
611
615
  ContextBlockSplitterFinishBlock(
612
- &lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);
616
+ &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);
613
617
  if (BROTLI_IS_OOM(m)) return;
614
618
  }
615
- BlockSplitterFinishBlockCommand(&cmd_blocks, /* is_final = */ BROTLI_TRUE);
616
- BlockSplitterFinishBlockDistance(&dist_blocks, /* is_final = */ BROTLI_TRUE);
619
+ BlockSplitterFinishBlockCommand(
620
+ &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE);
621
+ BlockSplitterFinishBlockDistance(
622
+ &arena->dist_blocks, /* is_final = */ BROTLI_TRUE);
617
623
 
618
624
  if (num_contexts > 1) {
619
625
  MapStaticContexts(m, num_contexts, static_context_map, mb);
@@ -632,14 +638,18 @@ void BrotliBuildMetaBlockGreedy(MemoryManager* m,
632
638
  const Command* commands,
633
639
  size_t n_commands,
634
640
  MetaBlockSplit* mb) {
641
+ GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1);
642
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
635
643
  if (num_contexts == 1) {
636
- BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
637
- prev_byte2, literal_context_lut, 1, NULL, commands, n_commands, mb);
644
+ BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,
645
+ prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands,
646
+ n_commands, mb);
638
647
  } else {
639
- BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
640
- prev_byte2, literal_context_lut, num_contexts, static_context_map,
641
- commands, n_commands, mb);
648
+ BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,
649
+ prev_byte, prev_byte2, literal_context_lut, num_contexts,
650
+ static_context_map, commands, n_commands, mb);
642
651
  }
652
+ BROTLI_FREE(m, arena);
643
653
  }
644
654
 
645
655
  void BrotliOptimizeHistograms(uint32_t num_distance_codes,
@@ -10,14 +10,15 @@
10
10
  #ifndef BROTLI_ENC_METABLOCK_H_
11
11
  #define BROTLI_ENC_METABLOCK_H_
12
12
 
13
+ #include <brotli/types.h>
14
+
13
15
  #include "../common/context.h"
14
16
  #include "../common/platform.h"
15
- #include <brotli/types.h>
16
- #include "./block_splitter.h"
17
- #include "./command.h"
18
- #include "./histogram.h"
19
- #include "./memory.h"
20
- #include "./quality.h"
17
+ #include "block_splitter.h"
18
+ #include "command.h"
19
+ #include "histogram.h"
20
+ #include "memory.h"
21
+ #include "quality.h"
21
22
 
22
23
  #if defined(__cplusplus) || defined(c_plusplus)
23
24
  extern "C" {
@@ -95,8 +96,8 @@ BROTLI_INTERNAL void BrotliBuildMetaBlockGreedy(
95
96
  BROTLI_INTERNAL void BrotliOptimizeHistograms(uint32_t num_distance_codes,
96
97
  MetaBlockSplit* mb);
97
98
 
98
- BROTLI_INTERNAL void BrotliInitDistanceParams(BrotliEncoderParams* params,
99
- uint32_t npostfix, uint32_t ndirect);
99
+ BROTLI_INTERNAL void BrotliInitDistanceParams(BrotliDistanceParams* params,
100
+ uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window);
100
101
 
101
102
  #if defined(__cplusplus) || defined(c_plusplus)
102
103
  } /* extern "C" */
@@ -27,6 +27,9 @@ typedef struct FN(BlockSplitter) {
27
27
  HistogramType* histograms_; /* not owned */
28
28
  size_t* histograms_size_; /* not owned */
29
29
 
30
+ /* Temporary storage for BlockSplitterFinishBlock. */
31
+ HistogramType combined_histo[2];
32
+
30
33
  /* The number of symbols that we want to collect before deciding on whether
31
34
  or not to merge the block with a previous one or emit a new block. */
32
35
  size_t target_block_size_;
@@ -71,7 +74,7 @@ static void FN(InitBlockSplitter)(
71
74
  *histograms_size = max_num_types;
72
75
  *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size);
73
76
  self->histograms_ = *histograms;
74
- if (BROTLI_IS_OOM(m)) return;
77
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return;
75
78
  /* Clear only current histogram. */
76
79
  FN(HistogramClear)(&self->histograms_[0]);
77
80
  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;
@@ -104,17 +107,16 @@ static void FN(BlockSplitterFinishBlock)(
104
107
  } else if (self->block_size_ > 0) {
105
108
  double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_,
106
109
  self->alphabet_size_);
107
- HistogramType combined_histo[2];
108
110
  double combined_entropy[2];
109
111
  double diff[2];
110
112
  size_t j;
111
113
  for (j = 0; j < 2; ++j) {
112
114
  size_t last_histogram_ix = self->last_histogram_ix_[j];
113
- combined_histo[j] = histograms[self->curr_histogram_ix_];
114
- FN(HistogramAddHistogram)(&combined_histo[j],
115
+ self->combined_histo[j] = histograms[self->curr_histogram_ix_];
116
+ FN(HistogramAddHistogram)(&self->combined_histo[j],
115
117
  &histograms[last_histogram_ix]);
116
118
  combined_entropy[j] = BitsEntropy(
117
- &combined_histo[j].data_[0], self->alphabet_size_);
119
+ &self->combined_histo[j].data_[0], self->alphabet_size_);
118
120
  diff[j] = combined_entropy[j] - entropy - last_entropy[j];
119
121
  }
120
122
 
@@ -141,7 +143,7 @@ static void FN(BlockSplitterFinishBlock)(
141
143
  split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;
142
144
  split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];
143
145
  BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1);
144
- histograms[self->last_histogram_ix_[0]] = combined_histo[1];
146
+ histograms[self->last_histogram_ix_[0]] = self->combined_histo[1];
145
147
  last_entropy[1] = last_entropy[0];
146
148
  last_entropy[0] = combined_entropy[1];
147
149
  ++self->num_blocks_;
@@ -152,7 +154,7 @@ static void FN(BlockSplitterFinishBlock)(
152
154
  } else {
153
155
  /* Combine this block with last block. */
154
156
  split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;
155
- histograms[self->last_histogram_ix_[0]] = combined_histo[0];
157
+ histograms[self->last_histogram_ix_[0]] = self->combined_histo[0];
156
158
  last_entropy[0] = combined_entropy[0];
157
159
  if (split->num_types == 1) {
158
160
  last_entropy[1] = last_entropy[0];
@@ -10,20 +10,21 @@
10
10
  #define BROTLI_ENC_PARAMS_H_
11
11
 
12
12
  #include <brotli/encode.h>
13
- #include "./encoder_dict.h"
13
+
14
+ #include "encoder_dict.h"
14
15
 
15
16
  typedef struct BrotliHasherParams {
16
17
  int type;
17
18
  int bucket_bits;
18
19
  int block_bits;
19
- int hash_len;
20
20
  int num_last_distances_to_check;
21
21
  } BrotliHasherParams;
22
22
 
23
23
  typedef struct BrotliDistanceParams {
24
24
  uint32_t distance_postfix_bits;
25
25
  uint32_t num_direct_distance_codes;
26
- uint32_t alphabet_size;
26
+ uint32_t alphabet_size_max;
27
+ uint32_t alphabet_size_limit;
27
28
  size_t max_distance;
28
29
  } BrotliDistanceParams;
29
30
 
@@ -33,12 +34,14 @@ typedef struct BrotliEncoderParams {
33
34
  int quality;
34
35
  int lgwin;
35
36
  int lgblock;
37
+ size_t stream_offset;
36
38
  size_t size_hint;
37
39
  BROTLI_BOOL disable_literal_context_modeling;
38
40
  BROTLI_BOOL large_window;
39
41
  BrotliHasherParams hasher;
40
42
  BrotliDistanceParams dist;
41
- BrotliEncoderDictionary dictionary;
43
+ /* TODO(eustas): rename to BrotliShared... */
44
+ SharedEncoderDictionary dictionary;
42
45
  } BrotliEncoderParams;
43
46
 
44
47
  #endif /* BROTLI_ENC_PARAMS_H_ */
@@ -10,10 +10,11 @@
10
10
  #ifndef BROTLI_ENC_PREFIX_H_
11
11
  #define BROTLI_ENC_PREFIX_H_
12
12
 
13
+ #include <brotli/types.h>
14
+
13
15
  #include "../common/constants.h"
14
16
  #include "../common/platform.h"
15
- #include <brotli/types.h>
16
- #include "./fast_log.h"
17
+ #include "fast_log.h"
17
18
 
18
19
  #if defined(__cplusplus) || defined(c_plusplus)
19
20
  extern "C" {
@@ -10,9 +10,10 @@
10
10
  #ifndef BROTLI_ENC_QUALITY_H_
11
11
  #define BROTLI_ENC_QUALITY_H_
12
12
 
13
- #include "../common/platform.h"
14
13
  #include <brotli/encode.h>
15
- #include "./params.h"
14
+
15
+ #include "../common/platform.h"
16
+ #include "params.h"
16
17
 
17
18
  #define FAST_ONE_PASS_COMPRESSION_QUALITY 0
18
19
  #define FAST_TWO_PASS_COMPRESSION_QUALITY 1
@@ -118,6 +119,41 @@ static BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch(
118
119
  return params->quality < 9 ? 64 : 512;
119
120
  }
120
121
 
122
+ /* Quality to hasher mapping:
123
+
124
+ - q02: h02 (longest_match_quickly), b16, l5
125
+
126
+ - q03: h03 (longest_match_quickly), b17, l5
127
+
128
+ - q04: h04 (longest_match_quickly), b17, l5
129
+ - q04: h54 (longest_match_quickly), b20, l7 | for large files
130
+
131
+ - q05: h05 (longest_match ), b14, l4
132
+ - q05: h06 (longest_match64 ), b15, l5 | for large files
133
+ - q05: h40 (forgetful_chain ), b15, l4 | for small window
134
+
135
+ - q06: h05 (longest_match ), b14, l4
136
+ - q06: h06 (longest_match64 ), b15, l5 | for large files
137
+ - q06: h40 (forgetful_chain ), b15, l4 | for small window
138
+
139
+ - q07: h05 (longest_match ), b15, l4
140
+ - q07: h06 (longest_match64 ), b15, l5 | for large files
141
+ - q07: h41 (forgetful_chain ), b15, l4 | for small window
142
+
143
+ - q08: h05 (longest_match ), b15, l4
144
+ - q08: h06 (longest_match64 ), b15, l5 | for large files
145
+ - q08: h41 (forgetful_chain ), b15, l4 | for small window
146
+
147
+ - q09: h05 (longest_match ), b15, l4
148
+ - q09: h06 (longest_match64 ), b15, l5 | for large files
149
+ - q09: h42 (forgetful_chain ), b15, l4 | for small window
150
+
151
+ - q10: t10 (to_binary_tree ), b17, l128
152
+
153
+ - q11: t10 (to_binary_tree ), b17, l128
154
+
155
+ Where "q" is quality, "h" is hasher type, "b" is bucket bits,
156
+ "l" is source len. */
121
157
  static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
122
158
  BrotliHasherParams* hparams) {
123
159
  if (params->quality > 9) {
@@ -132,10 +168,11 @@ static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
132
168
  hparams->type = 6;
133
169
  hparams->block_bits = params->quality - 1;
134
170
  hparams->bucket_bits = 15;
135
- hparams->hash_len = 5;
136
171
  hparams->num_last_distances_to_check =
137
172
  params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;
138
173
  } else {
174
+ /* TODO(eustas): often previous setting (H6) is faster and denser; consider
175
+ adding an option to use it. */
139
176
  hparams->type = 5;
140
177
  hparams->block_bits = params->quality - 1;
141
178
  hparams->bucket_bits = params->quality < 7 ? 14 : 15;
@@ -11,10 +11,11 @@
11
11
 
12
12
  #include <string.h> /* memcpy */
13
13
 
14
- #include "../common/platform.h"
15
14
  #include <brotli/types.h>
16
- #include "./memory.h"
17
- #include "./quality.h"
15
+
16
+ #include "../common/platform.h"
17
+ #include "memory.h"
18
+ #include "quality.h"
18
19
 
19
20
  #if defined(__cplusplus) || defined(c_plusplus)
20
21
  extern "C" {
@@ -75,7 +76,7 @@ static BROTLI_INLINE void RingBufferInitBuffer(
75
76
  uint8_t* new_data = BROTLI_ALLOC(
76
77
  m, uint8_t, 2 + buflen + kSlackForEightByteHashingEverywhere);
77
78
  size_t i;
78
- if (BROTLI_IS_OOM(m)) return;
79
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_data)) return;
79
80
  if (rb->data_) {
80
81
  memcpy(new_data, rb->data_,
81
82
  2 + rb->cur_size_ + kSlackForEightByteHashingEverywhere);
@@ -125,6 +126,9 @@ static BROTLI_INLINE void RingBufferWrite(
125
126
  later when we copy the last two bytes to the first two positions. */
126
127
  rb->buffer_[rb->size_ - 2] = 0;
127
128
  rb->buffer_[rb->size_ - 1] = 0;
129
+ /* Initialize tail; might be touched by "best_len++" optimization when
130
+ ring buffer is "full". */
131
+ rb->buffer_[rb->size_] = 241;
128
132
  }
129
133
  {
130
134
  const size_t masked_pos = rb->pos_ & rb->mask_;