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
data/vendor/brotli/c/enc/hash.h
CHANGED
@@ -10,50 +10,51 @@
|
|
10
10
|
#ifndef BROTLI_ENC_HASH_H_
|
11
11
|
#define BROTLI_ENC_HASH_H_
|
12
12
|
|
13
|
+
#include <stdlib.h> /* exit */
|
13
14
|
#include <string.h> /* memcmp, memset */
|
14
15
|
|
16
|
+
#include <brotli/types.h>
|
17
|
+
|
15
18
|
#include "../common/constants.h"
|
16
19
|
#include "../common/dictionary.h"
|
17
20
|
#include "../common/platform.h"
|
18
|
-
#include
|
19
|
-
#include "
|
20
|
-
#include "
|
21
|
-
#include "
|
22
|
-
#include "
|
23
|
-
#include "
|
24
|
-
#include "
|
21
|
+
#include "compound_dictionary.h"
|
22
|
+
#include "encoder_dict.h"
|
23
|
+
#include "fast_log.h"
|
24
|
+
#include "find_match_length.h"
|
25
|
+
#include "memory.h"
|
26
|
+
#include "quality.h"
|
27
|
+
#include "static_dict.h"
|
25
28
|
|
26
29
|
#if defined(__cplusplus) || defined(c_plusplus)
|
27
30
|
extern "C" {
|
28
31
|
#endif
|
29
32
|
|
30
|
-
/* Pointer to hasher data.
|
31
|
-
*
|
32
|
-
* Excluding initialization and destruction, hasher can be passed as
|
33
|
-
* HasherHandle by value.
|
34
|
-
*
|
35
|
-
* Typically hasher data consists of 3 sections:
|
36
|
-
* * HasherCommon structure
|
37
|
-
* * private structured hasher data, depending on hasher type
|
38
|
-
* * private dynamic hasher data, depending on hasher type and parameters
|
39
|
-
*
|
40
|
-
* Using "define" instead of "typedef", because on MSVC __restrict does not work
|
41
|
-
* on typedef pointer types. */
|
42
|
-
#define HasherHandle uint8_t*
|
43
|
-
|
44
33
|
typedef struct {
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
34
|
+
/**
|
35
|
+
* Dynamically allocated areas; regular hasher uses one or two allocations;
|
36
|
+
* "composite" hasher uses up to 4 allocations.
|
37
|
+
*/
|
38
|
+
void* extra[4];
|
39
|
+
|
40
|
+
/**
|
41
|
+
* False before the fisrt invocation of HasherSetup (where "extra" memory)
|
42
|
+
* is allocated.
|
43
|
+
*/
|
44
|
+
BROTLI_BOOL is_setup_;
|
49
45
|
|
50
46
|
size_t dict_num_lookups;
|
51
47
|
size_t dict_num_matches;
|
52
|
-
} HasherCommon;
|
53
48
|
|
54
|
-
|
55
|
-
|
56
|
-
|
49
|
+
BrotliHasherParams params;
|
50
|
+
|
51
|
+
/**
|
52
|
+
* False if hasher needs to be "prepared" before use (before the first
|
53
|
+
* invocation of HasherSetup or after HasherReset). "preparation" is hasher
|
54
|
+
* data initialization (using input ringbuffer).
|
55
|
+
*/
|
56
|
+
BROTLI_BOOL is_prepared_;
|
57
|
+
} HasherCommon;
|
57
58
|
|
58
59
|
#define score_t size_t
|
59
60
|
|
@@ -77,8 +78,7 @@ typedef struct HasherSearchResult {
|
|
77
78
|
for this use.
|
78
79
|
* The number has been tuned heuristically against compression benchmarks. */
|
79
80
|
static const uint32_t kHashMul32 = 0x1E35A7BD;
|
80
|
-
static const uint64_t kHashMul64 =
|
81
|
-
static const uint64_t kHashMul64Long =
|
81
|
+
static const uint64_t kHashMul64 =
|
82
82
|
BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);
|
83
83
|
|
84
84
|
static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {
|
@@ -149,17 +149,13 @@ static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
|
|
149
149
|
}
|
150
150
|
|
151
151
|
static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
|
152
|
-
const BrotliEncoderDictionary* dictionary, size_t
|
152
|
+
const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,
|
153
153
|
const uint8_t* data, size_t max_length, size_t max_backward,
|
154
154
|
size_t max_distance, HasherSearchResult* out) {
|
155
|
-
size_t len;
|
156
|
-
size_t word_idx;
|
157
155
|
size_t offset;
|
158
156
|
size_t matchlen;
|
159
157
|
size_t backward;
|
160
158
|
score_t score;
|
161
|
-
len = item & 0x1F;
|
162
|
-
word_idx = item >> 5;
|
163
159
|
offset = dictionary->words->offsets_by_length[len] + len * word_idx;
|
164
160
|
if (len > max_length) {
|
165
161
|
return BROTLI_FALSE;
|
@@ -193,25 +189,24 @@ static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
|
|
193
189
|
|
194
190
|
static BROTLI_INLINE void SearchInStaticDictionary(
|
195
191
|
const BrotliEncoderDictionary* dictionary,
|
196
|
-
|
192
|
+
HasherCommon* common, const uint8_t* data, size_t max_length,
|
197
193
|
size_t max_backward, size_t max_distance,
|
198
194
|
HasherSearchResult* out, BROTLI_BOOL shallow) {
|
199
195
|
size_t key;
|
200
196
|
size_t i;
|
201
|
-
|
202
|
-
if (self->dict_num_matches < (self->dict_num_lookups >> 7)) {
|
197
|
+
if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {
|
203
198
|
return;
|
204
199
|
}
|
205
200
|
key = Hash14(data) << 1;
|
206
201
|
for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {
|
207
|
-
|
208
|
-
|
209
|
-
if (item != 0) {
|
202
|
+
common->dict_num_lookups++;
|
203
|
+
if (dictionary->hash_table_lengths[key] != 0) {
|
210
204
|
BROTLI_BOOL item_matches = TestStaticDictionaryItem(
|
211
|
-
dictionary,
|
205
|
+
dictionary, dictionary->hash_table_lengths[key],
|
206
|
+
dictionary->hash_table_words[key], data,
|
212
207
|
max_length, max_backward, max_distance, out);
|
213
208
|
if (item_matches) {
|
214
|
-
|
209
|
+
common->dict_num_matches++;
|
215
210
|
}
|
216
211
|
}
|
217
212
|
}
|
@@ -252,7 +247,7 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
252
247
|
#define BUCKET_BITS 17
|
253
248
|
#define MAX_TREE_SEARCH_DEPTH 64
|
254
249
|
#define MAX_TREE_COMP_LENGTH 128
|
255
|
-
#include "
|
250
|
+
#include "hash_to_binary_tree_inc.h" /* NOLINT(build/include) */
|
256
251
|
#undef MAX_TREE_SEARCH_DEPTH
|
257
252
|
#undef MAX_TREE_COMP_LENGTH
|
258
253
|
#undef BUCKET_BITS
|
@@ -260,46 +255,46 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
260
255
|
/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */
|
261
256
|
#define MAX_NUM_MATCHES_H10 128
|
262
257
|
|
263
|
-
/* For
|
258
|
+
/* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression
|
264
259
|
a little faster (0.5% - 1%) and it compresses 0.15% better on small text
|
265
260
|
and HTML inputs. */
|
266
261
|
|
267
262
|
#define HASHER() H2
|
268
263
|
#define BUCKET_BITS 16
|
269
|
-
#define
|
264
|
+
#define BUCKET_SWEEP_BITS 0
|
270
265
|
#define HASH_LEN 5
|
271
266
|
#define USE_DICTIONARY 1
|
272
|
-
#include "
|
273
|
-
#undef
|
267
|
+
#include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
268
|
+
#undef BUCKET_SWEEP_BITS
|
274
269
|
#undef USE_DICTIONARY
|
275
270
|
#undef HASHER
|
276
271
|
|
277
272
|
#define HASHER() H3
|
278
|
-
#define
|
273
|
+
#define BUCKET_SWEEP_BITS 1
|
279
274
|
#define USE_DICTIONARY 0
|
280
|
-
#include "
|
275
|
+
#include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
281
276
|
#undef USE_DICTIONARY
|
282
|
-
#undef
|
277
|
+
#undef BUCKET_SWEEP_BITS
|
283
278
|
#undef BUCKET_BITS
|
284
279
|
#undef HASHER
|
285
280
|
|
286
281
|
#define HASHER() H4
|
287
282
|
#define BUCKET_BITS 17
|
288
|
-
#define
|
283
|
+
#define BUCKET_SWEEP_BITS 2
|
289
284
|
#define USE_DICTIONARY 1
|
290
|
-
#include "
|
285
|
+
#include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
291
286
|
#undef USE_DICTIONARY
|
292
287
|
#undef HASH_LEN
|
293
|
-
#undef
|
288
|
+
#undef BUCKET_SWEEP_BITS
|
294
289
|
#undef BUCKET_BITS
|
295
290
|
#undef HASHER
|
296
291
|
|
297
292
|
#define HASHER() H5
|
298
|
-
#include "
|
293
|
+
#include "hash_longest_match_inc.h" /* NOLINT(build/include) */
|
299
294
|
#undef HASHER
|
300
295
|
|
301
296
|
#define HASHER() H6
|
302
|
-
#include "
|
297
|
+
#include "hash_longest_match64_inc.h" /* NOLINT(build/include) */
|
303
298
|
#undef HASHER
|
304
299
|
|
305
300
|
#define BUCKET_BITS 15
|
@@ -308,13 +303,13 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
308
303
|
#define NUM_BANKS 1
|
309
304
|
#define BANK_BITS 16
|
310
305
|
#define HASHER() H40
|
311
|
-
#include "
|
306
|
+
#include "hash_forgetful_chain_inc.h" /* NOLINT(build/include) */
|
312
307
|
#undef HASHER
|
313
308
|
#undef NUM_LAST_DISTANCES_TO_CHECK
|
314
309
|
|
315
310
|
#define NUM_LAST_DISTANCES_TO_CHECK 10
|
316
311
|
#define HASHER() H41
|
317
|
-
#include "
|
312
|
+
#include "hash_forgetful_chain_inc.h" /* NOLINT(build/include) */
|
318
313
|
#undef HASHER
|
319
314
|
#undef NUM_LAST_DISTANCES_TO_CHECK
|
320
315
|
#undef NUM_BANKS
|
@@ -324,7 +319,7 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
324
319
|
#define NUM_BANKS 512
|
325
320
|
#define BANK_BITS 9
|
326
321
|
#define HASHER() H42
|
327
|
-
#include "
|
322
|
+
#include "hash_forgetful_chain_inc.h" /* NOLINT(build/include) */
|
328
323
|
#undef HASHER
|
329
324
|
#undef NUM_LAST_DISTANCES_TO_CHECK
|
330
325
|
#undef NUM_BANKS
|
@@ -334,13 +329,13 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
334
329
|
|
335
330
|
#define HASHER() H54
|
336
331
|
#define BUCKET_BITS 20
|
337
|
-
#define
|
332
|
+
#define BUCKET_SWEEP_BITS 2
|
338
333
|
#define HASH_LEN 7
|
339
334
|
#define USE_DICTIONARY 0
|
340
|
-
#include "
|
335
|
+
#include "hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
341
336
|
#undef USE_DICTIONARY
|
342
337
|
#undef HASH_LEN
|
343
|
-
#undef
|
338
|
+
#undef BUCKET_SWEEP_BITS
|
344
339
|
#undef BUCKET_BITS
|
345
340
|
#undef HASHER
|
346
341
|
|
@@ -351,14 +346,14 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
351
346
|
#define JUMP 4
|
352
347
|
#define NUMBUCKETS 16777216
|
353
348
|
#define MASK ((NUMBUCKETS * 64) - 1)
|
354
|
-
#include "
|
349
|
+
#include "hash_rolling_inc.h" /* NOLINT(build/include) */
|
355
350
|
#undef JUMP
|
356
351
|
#undef HASHER
|
357
352
|
|
358
353
|
|
359
354
|
#define HASHER() HROLLING
|
360
355
|
#define JUMP 1
|
361
|
-
#include "
|
356
|
+
#include "hash_rolling_inc.h" /* NOLINT(build/include) */
|
362
357
|
#undef MASK
|
363
358
|
#undef NUMBUCKETS
|
364
359
|
#undef JUMP
|
@@ -368,7 +363,7 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
368
363
|
#define HASHER() H35
|
369
364
|
#define HASHER_A H3
|
370
365
|
#define HASHER_B HROLLING_FAST
|
371
|
-
#include "
|
366
|
+
#include "hash_composite_inc.h" /* NOLINT(build/include) */
|
372
367
|
#undef HASHER_A
|
373
368
|
#undef HASHER_B
|
374
369
|
#undef HASHER
|
@@ -376,7 +371,7 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
376
371
|
#define HASHER() H55
|
377
372
|
#define HASHER_A H54
|
378
373
|
#define HASHER_B HROLLING_FAST
|
379
|
-
#include "
|
374
|
+
#include "hash_composite_inc.h" /* NOLINT(build/include) */
|
380
375
|
#undef HASHER_A
|
381
376
|
#undef HASHER_B
|
382
377
|
#undef HASHER
|
@@ -384,7 +379,7 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
384
379
|
#define HASHER() H65
|
385
380
|
#define HASHER_A H6
|
386
381
|
#define HASHER_B HROLLING
|
387
|
-
#include "
|
382
|
+
#include "hash_composite_inc.h" /* NOLINT(build/include) */
|
388
383
|
#undef HASHER_A
|
389
384
|
#undef HASHER_B
|
390
385
|
#undef HASHER
|
@@ -393,97 +388,116 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
393
388
|
#undef CAT
|
394
389
|
#undef EXPAND_CAT
|
395
390
|
|
396
|
-
#define
|
397
|
-
|
391
|
+
#define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
|
392
|
+
#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)
|
393
|
+
#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)
|
398
394
|
#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
|
399
395
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
396
|
+
typedef struct {
|
397
|
+
HasherCommon common;
|
398
|
+
|
399
|
+
union {
|
400
|
+
#define MEMBER_(N) \
|
401
|
+
H ## N _H ## N;
|
402
|
+
FOR_ALL_HASHERS(MEMBER_)
|
403
|
+
#undef MEMBER_
|
404
|
+
} privat;
|
405
|
+
} Hasher;
|
406
|
+
|
407
|
+
/* MUST be invoked before any other method. */
|
408
|
+
static BROTLI_INLINE void HasherInit(Hasher* hasher) {
|
409
|
+
hasher->common.is_setup_ = BROTLI_FALSE;
|
410
|
+
hasher->common.extra[0] = NULL;
|
411
|
+
hasher->common.extra[1] = NULL;
|
412
|
+
hasher->common.extra[2] = NULL;
|
413
|
+
hasher->common.extra[3] = NULL;
|
414
|
+
}
|
415
|
+
|
416
|
+
static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {
|
417
|
+
if (hasher->common.extra[0] != NULL) BROTLI_FREE(m, hasher->common.extra[0]);
|
418
|
+
if (hasher->common.extra[1] != NULL) BROTLI_FREE(m, hasher->common.extra[1]);
|
419
|
+
if (hasher->common.extra[2] != NULL) BROTLI_FREE(m, hasher->common.extra[2]);
|
420
|
+
if (hasher->common.extra[3] != NULL) BROTLI_FREE(m, hasher->common.extra[3]);
|
404
421
|
}
|
405
422
|
|
406
|
-
static BROTLI_INLINE void HasherReset(
|
407
|
-
|
408
|
-
GetHasherCommon(handle)->is_prepared_ = BROTLI_FALSE;
|
423
|
+
static BROTLI_INLINE void HasherReset(Hasher* hasher) {
|
424
|
+
hasher->common.is_prepared_ = BROTLI_FALSE;
|
409
425
|
}
|
410
426
|
|
411
|
-
static BROTLI_INLINE
|
412
|
-
BROTLI_BOOL one_shot, const size_t input_size) {
|
413
|
-
size_t result = sizeof(HasherCommon);
|
427
|
+
static BROTLI_INLINE void HasherSize(const BrotliEncoderParams* params,
|
428
|
+
BROTLI_BOOL one_shot, const size_t input_size, size_t* alloc_size) {
|
414
429
|
switch (params->hasher.type) {
|
415
|
-
#define SIZE_(N)
|
416
|
-
case N:
|
417
|
-
|
430
|
+
#define SIZE_(N) \
|
431
|
+
case N: \
|
432
|
+
HashMemAllocInBytesH ## N(params, one_shot, input_size, alloc_size); \
|
418
433
|
break;
|
419
434
|
FOR_ALL_HASHERS(SIZE_)
|
420
435
|
#undef SIZE_
|
421
436
|
default:
|
422
437
|
break;
|
423
438
|
}
|
424
|
-
return result;
|
425
439
|
}
|
426
440
|
|
427
|
-
static BROTLI_INLINE void HasherSetup(MemoryManager* m,
|
441
|
+
static BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,
|
428
442
|
BrotliEncoderParams* params, const uint8_t* data, size_t position,
|
429
443
|
size_t input_size, BROTLI_BOOL is_last) {
|
430
|
-
HasherHandle self = NULL;
|
431
|
-
HasherCommon* common = NULL;
|
432
444
|
BROTLI_BOOL one_shot = (position == 0 && is_last);
|
433
|
-
if (
|
434
|
-
size_t alloc_size;
|
445
|
+
if (!hasher->common.is_setup_) {
|
446
|
+
size_t alloc_size[4] = {0};
|
447
|
+
size_t i;
|
435
448
|
ChooseHasher(params, ¶ms->hasher);
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
449
|
+
hasher->common.params = params->hasher;
|
450
|
+
hasher->common.dict_num_lookups = 0;
|
451
|
+
hasher->common.dict_num_matches = 0;
|
452
|
+
HasherSize(params, one_shot, input_size, alloc_size);
|
453
|
+
for (i = 0; i < 4; ++i) {
|
454
|
+
if (alloc_size[i] == 0) continue;
|
455
|
+
hasher->common.extra[i] = BROTLI_ALLOC(m, uint8_t, alloc_size[i]);
|
456
|
+
if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra[i])) return;
|
457
|
+
}
|
458
|
+
switch (hasher->common.params.type) {
|
459
|
+
#define INITIALIZE_(N) \
|
460
|
+
case N: \
|
461
|
+
InitializeH ## N(&hasher->common, \
|
462
|
+
&hasher->privat._H ## N, params); \
|
446
463
|
break;
|
447
464
|
FOR_ALL_HASHERS(INITIALIZE_);
|
448
465
|
#undef INITIALIZE_
|
449
466
|
default:
|
450
467
|
break;
|
451
468
|
}
|
452
|
-
HasherReset(
|
469
|
+
HasherReset(hasher);
|
470
|
+
hasher->common.is_setup_ = BROTLI_TRUE;
|
453
471
|
}
|
454
472
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
473
|
+
if (!hasher->common.is_prepared_) {
|
474
|
+
switch (hasher->common.params.type) {
|
475
|
+
#define PREPARE_(N) \
|
476
|
+
case N: \
|
477
|
+
PrepareH ## N( \
|
478
|
+
&hasher->privat._H ## N, \
|
479
|
+
one_shot, input_size, data); \
|
462
480
|
break;
|
463
481
|
FOR_ALL_HASHERS(PREPARE_)
|
464
482
|
#undef PREPARE_
|
465
483
|
default: break;
|
466
484
|
}
|
467
|
-
|
468
|
-
common->dict_num_lookups = 0;
|
469
|
-
common->dict_num_matches = 0;
|
470
|
-
}
|
471
|
-
common->is_prepared_ = BROTLI_TRUE;
|
485
|
+
hasher->common.is_prepared_ = BROTLI_TRUE;
|
472
486
|
}
|
473
487
|
}
|
474
488
|
|
475
489
|
static BROTLI_INLINE void InitOrStitchToPreviousBlock(
|
476
|
-
MemoryManager* m,
|
490
|
+
MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,
|
477
491
|
BrotliEncoderParams* params, size_t position, size_t input_size,
|
478
492
|
BROTLI_BOOL is_last) {
|
479
|
-
|
480
|
-
HasherSetup(m, handle, params, data, position, input_size, is_last);
|
493
|
+
HasherSetup(m, hasher, params, data, position, input_size, is_last);
|
481
494
|
if (BROTLI_IS_OOM(m)) return;
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
495
|
+
switch (hasher->common.params.type) {
|
496
|
+
#define INIT_(N) \
|
497
|
+
case N: \
|
498
|
+
StitchToPreviousBlockH ## N( \
|
499
|
+
&hasher->privat._H ## N, \
|
500
|
+
input_size, position, data, mask); \
|
487
501
|
break;
|
488
502
|
FOR_ALL_HASHERS(INIT_)
|
489
503
|
#undef INIT_
|
@@ -491,6 +505,222 @@ static BROTLI_INLINE void InitOrStitchToPreviousBlock(
|
|
491
505
|
}
|
492
506
|
}
|
493
507
|
|
508
|
+
/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget
|
509
|
+
to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */
|
510
|
+
static BROTLI_INLINE void FindCompoundDictionaryMatch(
|
511
|
+
const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data,
|
512
|
+
const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,
|
513
|
+
const size_t cur_ix, const size_t max_length, const size_t distance_offset,
|
514
|
+
const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {
|
515
|
+
const uint32_t source_size = self->source_size;
|
516
|
+
const size_t boundary = distance_offset - source_size;
|
517
|
+
const uint32_t hash_bits = self->hash_bits;
|
518
|
+
const uint32_t bucket_bits = self->bucket_bits;
|
519
|
+
const uint32_t slot_bits = self->slot_bits;
|
520
|
+
|
521
|
+
const uint32_t hash_shift = 64u - bucket_bits;
|
522
|
+
const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits);
|
523
|
+
const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);
|
524
|
+
|
525
|
+
const uint32_t* slot_offsets = (uint32_t*)(&self[1]);
|
526
|
+
const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]);
|
527
|
+
const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]);
|
528
|
+
const uint8_t* source = NULL;
|
529
|
+
|
530
|
+
const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
|
531
|
+
score_t best_score = out->score;
|
532
|
+
size_t best_len = out->len;
|
533
|
+
size_t i;
|
534
|
+
const uint64_t h =
|
535
|
+
(BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) *
|
536
|
+
kPreparedDictionaryHashMul64Long;
|
537
|
+
const uint32_t key = (uint32_t)(h >> hash_shift);
|
538
|
+
const uint32_t slot = key & slot_mask;
|
539
|
+
const uint32_t head = heads[key];
|
540
|
+
const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head];
|
541
|
+
uint32_t item = (head == 0xFFFF) ? 1 : 0;
|
542
|
+
|
543
|
+
const void* tail = (void*)&items[self->num_items];
|
544
|
+
if (self->magic == kPreparedDictionaryMagic) {
|
545
|
+
source = (const uint8_t*)tail;
|
546
|
+
} else {
|
547
|
+
/* kLeanPreparedDictionaryMagic */
|
548
|
+
source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);
|
549
|
+
}
|
550
|
+
|
551
|
+
for (i = 0; i < 4; ++i) {
|
552
|
+
const size_t distance = (size_t)distance_cache[i];
|
553
|
+
size_t offset;
|
554
|
+
size_t limit;
|
555
|
+
size_t len;
|
556
|
+
if (distance <= boundary || distance > distance_offset) continue;
|
557
|
+
offset = distance_offset - distance;
|
558
|
+
limit = source_size - offset;
|
559
|
+
limit = limit > max_length ? max_length : limit;
|
560
|
+
len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked],
|
561
|
+
limit);
|
562
|
+
if (len >= 2) {
|
563
|
+
score_t score = BackwardReferenceScoreUsingLastDistance(len);
|
564
|
+
if (best_score < score) {
|
565
|
+
if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);
|
566
|
+
if (best_score < score) {
|
567
|
+
best_score = score;
|
568
|
+
if (len > best_len) best_len = len;
|
569
|
+
out->len = len;
|
570
|
+
out->len_code_delta = 0;
|
571
|
+
out->distance = distance;
|
572
|
+
out->score = best_score;
|
573
|
+
}
|
574
|
+
}
|
575
|
+
}
|
576
|
+
}
|
577
|
+
while (item == 0) {
|
578
|
+
size_t offset;
|
579
|
+
size_t distance;
|
580
|
+
size_t limit;
|
581
|
+
item = *chain;
|
582
|
+
chain++;
|
583
|
+
offset = item & 0x7FFFFFFF;
|
584
|
+
item &= 0x80000000;
|
585
|
+
distance = distance_offset - offset;
|
586
|
+
limit = source_size - offset;
|
587
|
+
limit = (limit > max_length) ? max_length : limit;
|
588
|
+
if (distance > max_distance) continue;
|
589
|
+
if (cur_ix_masked + best_len > ring_buffer_mask ||
|
590
|
+
best_len >= limit ||
|
591
|
+
data[cur_ix_masked + best_len] != source[offset + best_len]) {
|
592
|
+
continue;
|
593
|
+
}
|
594
|
+
{
|
595
|
+
const size_t len = FindMatchLengthWithLimit(&source[offset],
|
596
|
+
&data[cur_ix_masked],
|
597
|
+
limit);
|
598
|
+
if (len >= 4) {
|
599
|
+
score_t score = BackwardReferenceScore(len, distance);
|
600
|
+
if (best_score < score) {
|
601
|
+
best_score = score;
|
602
|
+
best_len = len;
|
603
|
+
out->len = best_len;
|
604
|
+
out->len_code_delta = 0;
|
605
|
+
out->distance = distance;
|
606
|
+
out->score = best_score;
|
607
|
+
}
|
608
|
+
}
|
609
|
+
}
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget
|
614
|
+
to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */
|
615
|
+
static BROTLI_INLINE size_t FindAllCompoundDictionaryMatches(
|
616
|
+
const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data,
|
617
|
+
const size_t ring_buffer_mask, const size_t cur_ix, const size_t min_length,
|
618
|
+
const size_t max_length, const size_t distance_offset,
|
619
|
+
const size_t max_distance, BackwardMatch* matches, size_t match_limit) {
|
620
|
+
const uint32_t source_size = self->source_size;
|
621
|
+
const uint32_t hash_bits = self->hash_bits;
|
622
|
+
const uint32_t bucket_bits = self->bucket_bits;
|
623
|
+
const uint32_t slot_bits = self->slot_bits;
|
624
|
+
|
625
|
+
const uint32_t hash_shift = 64u - bucket_bits;
|
626
|
+
const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits);
|
627
|
+
const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);
|
628
|
+
|
629
|
+
const uint32_t* slot_offsets = (uint32_t*)(&self[1]);
|
630
|
+
const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]);
|
631
|
+
const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]);
|
632
|
+
const uint8_t* source = NULL;
|
633
|
+
|
634
|
+
const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
|
635
|
+
size_t best_len = min_length;
|
636
|
+
const uint64_t h =
|
637
|
+
(BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) *
|
638
|
+
kPreparedDictionaryHashMul64Long;
|
639
|
+
const uint32_t key = (uint32_t)(h >> hash_shift);
|
640
|
+
const uint32_t slot = key & slot_mask;
|
641
|
+
const uint32_t head = heads[key];
|
642
|
+
const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head];
|
643
|
+
uint32_t item = (head == 0xFFFF) ? 1 : 0;
|
644
|
+
size_t found = 0;
|
645
|
+
|
646
|
+
const void* tail = (void*)&items[self->num_items];
|
647
|
+
if (self->magic == kPreparedDictionaryMagic) {
|
648
|
+
source = (const uint8_t*)tail;
|
649
|
+
} else {
|
650
|
+
/* kLeanPreparedDictionaryMagic */
|
651
|
+
source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);
|
652
|
+
}
|
653
|
+
|
654
|
+
while (item == 0) {
|
655
|
+
size_t offset;
|
656
|
+
size_t distance;
|
657
|
+
size_t limit;
|
658
|
+
size_t len;
|
659
|
+
item = *chain;
|
660
|
+
chain++;
|
661
|
+
offset = item & 0x7FFFFFFF;
|
662
|
+
item &= 0x80000000;
|
663
|
+
distance = distance_offset - offset;
|
664
|
+
limit = source_size - offset;
|
665
|
+
limit = (limit > max_length) ? max_length : limit;
|
666
|
+
if (distance > max_distance) continue;
|
667
|
+
if (cur_ix_masked + best_len > ring_buffer_mask ||
|
668
|
+
best_len >= limit ||
|
669
|
+
data[cur_ix_masked + best_len] != source[offset + best_len]) {
|
670
|
+
continue;
|
671
|
+
}
|
672
|
+
len = FindMatchLengthWithLimit(
|
673
|
+
&source[offset], &data[cur_ix_masked], limit);
|
674
|
+
if (len > best_len) {
|
675
|
+
best_len = len;
|
676
|
+
InitBackwardMatch(matches++, distance, len);
|
677
|
+
found++;
|
678
|
+
if (found == match_limit) break;
|
679
|
+
}
|
680
|
+
}
|
681
|
+
return found;
|
682
|
+
}
|
683
|
+
|
684
|
+
static BROTLI_INLINE void LookupCompoundDictionaryMatch(
|
685
|
+
const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,
|
686
|
+
const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,
|
687
|
+
const size_t cur_ix, const size_t max_length,
|
688
|
+
const size_t max_ring_buffer_distance, const size_t max_distance,
|
689
|
+
HasherSearchResult* sr) {
|
690
|
+
size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;
|
691
|
+
size_t d;
|
692
|
+
for (d = 0; d < addon->num_chunks; ++d) {
|
693
|
+
/* Only one prepared dictionary type is currently supported. */
|
694
|
+
FindCompoundDictionaryMatch(
|
695
|
+
(const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask,
|
696
|
+
distance_cache, cur_ix, max_length,
|
697
|
+
base_offset - addon->chunk_offsets[d], max_distance, sr);
|
698
|
+
}
|
699
|
+
}
|
700
|
+
|
701
|
+
static BROTLI_INLINE size_t LookupAllCompoundDictionaryMatches(
|
702
|
+
const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,
|
703
|
+
const size_t ring_buffer_mask, const size_t cur_ix, size_t min_length,
|
704
|
+
const size_t max_length, const size_t max_ring_buffer_distance,
|
705
|
+
const size_t max_distance, BackwardMatch* matches,
|
706
|
+
size_t match_limit) {
|
707
|
+
size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;
|
708
|
+
size_t d;
|
709
|
+
size_t total_found = 0;
|
710
|
+
for (d = 0; d < addon->num_chunks; ++d) {
|
711
|
+
/* Only one prepared dictionary type is currently supported. */
|
712
|
+
total_found += FindAllCompoundDictionaryMatches(
|
713
|
+
(const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask,
|
714
|
+
cur_ix, min_length, max_length, base_offset - addon->chunk_offsets[d],
|
715
|
+
max_distance, matches + total_found, match_limit - total_found);
|
716
|
+
if (total_found == match_limit) break;
|
717
|
+
if (total_found > 0) {
|
718
|
+
min_length = BackwardMatchLength(&matches[total_found - 1]);
|
719
|
+
}
|
720
|
+
}
|
721
|
+
return total_found;
|
722
|
+
}
|
723
|
+
|
494
724
|
#if defined(__cplusplus) || defined(c_plusplus)
|
495
725
|
} /* extern "C" */
|
496
726
|
#endif
|