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.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +37 -0
- data/.github/workflows/publish.yml +24 -0
- data/.gitmodules +1 -1
- data/Gemfile +6 -3
- data/README.md +2 -2
- data/Rakefile +16 -9
- data/brotli.gemspec +7 -13
- data/ext/brotli/brotli.c +210 -31
- data/ext/brotli/buffer.c +1 -7
- data/ext/brotli/buffer.h +1 -1
- data/ext/brotli/extconf.rb +25 -17
- data/lib/brotli/version.rb +1 -1
- data/test/brotli_test.rb +107 -0
- data/test/brotli_writer_test.rb +36 -0
- data/test/test_helper.rb +8 -0
- data/vendor/brotli/c/common/constants.c +15 -0
- data/vendor/brotli/c/common/constants.h +137 -0
- data/vendor/brotli/c/common/context.c +156 -0
- data/vendor/brotli/c/common/context.h +4 -152
- data/vendor/brotli/c/common/dictionary.bin.br +0 -0
- data/vendor/brotli/c/common/dictionary.c +14 -3
- data/vendor/brotli/c/common/platform.c +23 -0
- data/vendor/brotli/c/common/platform.h +95 -122
- data/vendor/brotli/c/common/shared_dictionary.c +521 -0
- data/vendor/brotli/c/common/shared_dictionary_internal.h +75 -0
- data/vendor/brotli/c/common/transform.c +60 -4
- data/vendor/brotli/c/common/transform.h +5 -0
- data/vendor/brotli/c/common/version.h +31 -6
- data/vendor/brotli/c/dec/bit_reader.c +34 -4
- data/vendor/brotli/c/dec/bit_reader.h +221 -107
- data/vendor/brotli/c/dec/decode.c +772 -403
- data/vendor/brotli/c/dec/huffman.c +7 -4
- data/vendor/brotli/c/dec/huffman.h +8 -13
- data/vendor/brotli/c/dec/prefix.h +1 -18
- data/vendor/brotli/c/dec/state.c +40 -21
- data/vendor/brotli/c/dec/state.h +201 -59
- data/vendor/brotli/c/enc/backward_references.c +88 -25
- data/vendor/brotli/c/enc/backward_references.h +10 -8
- data/vendor/brotli/c/enc/backward_references_hq.c +194 -80
- data/vendor/brotli/c/enc/backward_references_hq.h +17 -13
- data/vendor/brotli/c/enc/backward_references_inc.h +52 -16
- data/vendor/brotli/c/enc/bit_cost.c +8 -7
- data/vendor/brotli/c/enc/bit_cost.h +5 -4
- data/vendor/brotli/c/enc/block_splitter.c +40 -17
- data/vendor/brotli/c/enc/block_splitter.h +5 -4
- data/vendor/brotli/c/enc/block_splitter_inc.h +99 -49
- data/vendor/brotli/c/enc/brotli_bit_stream.c +142 -137
- data/vendor/brotli/c/enc/brotli_bit_stream.h +11 -6
- data/vendor/brotli/c/enc/cluster.c +10 -9
- data/vendor/brotli/c/enc/cluster.h +7 -6
- data/vendor/brotli/c/enc/cluster_inc.h +30 -22
- data/vendor/brotli/c/enc/command.c +28 -0
- data/vendor/brotli/c/enc/command.h +17 -16
- data/vendor/brotli/c/enc/compound_dictionary.c +207 -0
- data/vendor/brotli/c/enc/compound_dictionary.h +74 -0
- data/vendor/brotli/c/enc/compress_fragment.c +93 -83
- data/vendor/brotli/c/enc/compress_fragment.h +32 -7
- data/vendor/brotli/c/enc/compress_fragment_two_pass.c +100 -88
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
- data/vendor/brotli/c/enc/dictionary_hash.c +1829 -1101
- data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
- data/vendor/brotli/c/enc/encode.c +550 -416
- data/vendor/brotli/c/enc/encoder_dict.c +613 -5
- data/vendor/brotli/c/enc/encoder_dict.h +120 -4
- data/vendor/brotli/c/enc/entropy_encode.c +5 -2
- data/vendor/brotli/c/enc/entropy_encode.h +4 -3
- data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
- data/vendor/brotli/c/enc/fast_log.c +105 -0
- data/vendor/brotli/c/enc/fast_log.h +21 -101
- data/vendor/brotli/c/enc/find_match_length.h +17 -25
- data/vendor/brotli/c/enc/hash.h +350 -120
- data/vendor/brotli/c/enc/hash_composite_inc.h +71 -67
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +92 -51
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +79 -84
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -54
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +93 -62
- data/vendor/brotli/c/enc/hash_rolling_inc.h +25 -29
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +42 -40
- data/vendor/brotli/c/enc/histogram.c +4 -4
- data/vendor/brotli/c/enc/histogram.h +7 -6
- data/vendor/brotli/c/enc/literal_cost.c +20 -15
- data/vendor/brotli/c/enc/literal_cost.h +4 -2
- data/vendor/brotli/c/enc/memory.c +29 -5
- data/vendor/brotli/c/enc/memory.h +43 -14
- data/vendor/brotli/c/enc/metablock.c +95 -85
- data/vendor/brotli/c/enc/metablock.h +9 -8
- data/vendor/brotli/c/enc/metablock_inc.h +9 -7
- data/vendor/brotli/c/enc/params.h +7 -4
- data/vendor/brotli/c/enc/prefix.h +3 -2
- data/vendor/brotli/c/enc/quality.h +40 -3
- data/vendor/brotli/c/enc/ringbuffer.h +8 -4
- data/vendor/brotli/c/enc/state.h +104 -0
- data/vendor/brotli/c/enc/static_dict.c +60 -4
- data/vendor/brotli/c/enc/static_dict.h +3 -2
- data/vendor/brotli/c/enc/static_dict_lut.h +2 -0
- data/vendor/brotli/c/enc/utf8_util.c +2 -2
- data/vendor/brotli/c/enc/utf8_util.h +2 -1
- data/vendor/brotli/c/enc/write_bits.h +29 -26
- data/vendor/brotli/c/include/brotli/decode.h +67 -2
- data/vendor/brotli/c/include/brotli/encode.h +77 -3
- data/vendor/brotli/c/include/brotli/port.h +34 -3
- data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
- metadata +23 -97
- data/.travis.yml +0 -31
- data/docs/Brotli/Error.html +0 -124
- data/docs/Brotli.html +0 -485
- data/docs/_index.html +0 -122
- data/docs/class_list.html +0 -51
- data/docs/css/common.css +0 -1
- data/docs/css/full_list.css +0 -58
- data/docs/css/style.css +0 -496
- data/docs/file.README.html +0 -127
- data/docs/file_list.html +0 -56
- data/docs/frames.html +0 -17
- data/docs/index.html +0 -127
- data/docs/js/app.js +0 -292
- data/docs/js/full_list.js +0 -216
- data/docs/js/jquery.js +0 -4
- data/docs/method_list.html +0 -67
- data/docs/top-level-namespace.html +0 -110
- data/spec/brotli_spec.rb +0 -88
- data/spec/inflate_spec.rb +0 -75
- 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 "
|
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
|
16
|
-
#include "
|
17
|
-
#include "
|
18
|
-
#include "
|
19
|
-
#include "
|
20
|
-
#include "
|
21
|
-
#include "
|
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(
|
29
|
-
uint32_t npostfix, uint32_t ndirect) {
|
30
|
-
|
31
|
-
uint32_t
|
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
|
-
|
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 (
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
47
|
-
|
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->
|
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
|
-
|
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(
|
117
|
+
HistogramAddDistance(tmp, dist_prefix & 0x3FF);
|
122
118
|
extra_bits += dist_prefix >> 10;
|
123
119
|
}
|
124
120
|
}
|
125
121
|
|
126
|
-
*cost = BrotliPopulationCostDistance(
|
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
|
-
|
155
|
-
|
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
|
-
|
164
|
-
|
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
|
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
|
-
&
|
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
|
185
|
+
params->dist = orig_params;
|
187
186
|
}
|
188
187
|
}
|
189
|
-
|
190
|
-
|
188
|
+
BROTLI_FREE(m, tmp);
|
189
|
+
RecomputeDistancePrefixes(cmds, num_commands, &orig_params, ¶ms->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 "
|
290
|
+
#include "metablock_inc.h" /* NOLINT(build/include) */
|
292
291
|
#undef FN
|
293
292
|
|
294
293
|
#define FN(X) X ## Command
|
295
|
-
#include "
|
294
|
+
#include "metablock_inc.h" /* NOLINT(build/include) */
|
296
295
|
#undef FN
|
297
296
|
|
298
297
|
#define FN(X) X ## Distance
|
299
|
-
#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
|
-
|
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,
|
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,
|
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(
|
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(
|
616
|
-
|
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,
|
637
|
-
prev_byte2, literal_context_lut, 1, NULL, commands,
|
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,
|
640
|
-
prev_byte2, literal_context_lut, num_contexts,
|
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
|
16
|
-
#include "
|
17
|
-
#include "
|
18
|
-
#include "
|
19
|
-
#include "
|
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(
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
17
|
-
#include "
|
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_;
|