brotli 0.2.0 → 0.4.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 +5 -5
- data/.github/workflows/main.yml +34 -0
- data/.github/workflows/publish.yml +34 -0
- data/Gemfile +6 -2
- data/Rakefile +18 -6
- data/bin/before_install.sh +9 -0
- data/brotli.gemspec +7 -13
- data/ext/brotli/brotli.c +209 -11
- data/ext/brotli/buffer.c +1 -7
- data/ext/brotli/buffer.h +1 -1
- data/ext/brotli/extconf.rb +45 -26
- data/lib/brotli/version.rb +1 -1
- data/smoke.sh +1 -1
- data/test/brotli_test.rb +104 -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 +149 -6
- data/vendor/brotli/c/{dec/context.h → common/context.c} +91 -186
- data/vendor/brotli/c/common/context.h +113 -0
- data/vendor/brotli/c/common/dictionary.bin +0 -0
- data/vendor/brotli/c/common/dictionary.bin.br +0 -0
- data/vendor/brotli/c/common/dictionary.c +11 -2
- data/vendor/brotli/c/common/dictionary.h +4 -4
- data/vendor/brotli/c/common/platform.c +22 -0
- data/vendor/brotli/c/common/platform.h +594 -0
- data/vendor/brotli/c/common/transform.c +291 -0
- data/vendor/brotli/c/common/transform.h +85 -0
- data/vendor/brotli/c/common/version.h +8 -1
- data/vendor/brotli/c/dec/bit_reader.c +29 -1
- data/vendor/brotli/c/dec/bit_reader.h +91 -100
- data/vendor/brotli/c/dec/decode.c +665 -437
- data/vendor/brotli/c/dec/huffman.c +65 -84
- data/vendor/brotli/c/dec/huffman.h +67 -14
- data/vendor/brotli/c/dec/prefix.h +1 -20
- data/vendor/brotli/c/dec/state.c +32 -45
- data/vendor/brotli/c/dec/state.h +173 -55
- data/vendor/brotli/c/enc/backward_references.c +27 -16
- data/vendor/brotli/c/enc/backward_references.h +7 -7
- data/vendor/brotli/c/enc/backward_references_hq.c +155 -116
- data/vendor/brotli/c/enc/backward_references_hq.h +22 -23
- data/vendor/brotli/c/enc/backward_references_inc.h +32 -22
- data/vendor/brotli/c/enc/bit_cost.c +1 -1
- data/vendor/brotli/c/enc/bit_cost.h +5 -5
- data/vendor/brotli/c/enc/block_encoder_inc.h +7 -6
- data/vendor/brotli/c/enc/block_splitter.c +5 -6
- data/vendor/brotli/c/enc/block_splitter.h +1 -1
- data/vendor/brotli/c/enc/block_splitter_inc.h +26 -17
- data/vendor/brotli/c/enc/brotli_bit_stream.c +107 -123
- data/vendor/brotli/c/enc/brotli_bit_stream.h +19 -38
- data/vendor/brotli/c/enc/cluster.c +1 -1
- data/vendor/brotli/c/enc/cluster.h +1 -1
- data/vendor/brotli/c/enc/cluster_inc.h +6 -3
- data/vendor/brotli/c/enc/command.c +28 -0
- data/vendor/brotli/c/enc/command.h +52 -42
- data/vendor/brotli/c/enc/compress_fragment.c +21 -22
- data/vendor/brotli/c/enc/compress_fragment.h +1 -1
- data/vendor/brotli/c/enc/compress_fragment_two_pass.c +102 -69
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +1 -1
- data/vendor/brotli/c/enc/dictionary_hash.c +1827 -1101
- data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
- data/vendor/brotli/c/enc/encode.c +358 -195
- data/vendor/brotli/c/enc/encoder_dict.c +33 -0
- data/vendor/brotli/c/enc/encoder_dict.h +43 -0
- data/vendor/brotli/c/enc/entropy_encode.c +16 -14
- data/vendor/brotli/c/enc/entropy_encode.h +7 -7
- data/vendor/brotli/c/enc/entropy_encode_static.h +3 -3
- data/vendor/brotli/c/enc/fast_log.c +105 -0
- data/vendor/brotli/c/enc/fast_log.h +20 -99
- data/vendor/brotli/c/enc/find_match_length.h +5 -6
- data/vendor/brotli/c/enc/hash.h +145 -103
- data/vendor/brotli/c/enc/hash_composite_inc.h +125 -0
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +93 -53
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +54 -53
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +58 -54
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +95 -63
- data/vendor/brotli/c/enc/hash_rolling_inc.h +212 -0
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +46 -43
- data/vendor/brotli/c/enc/histogram.c +9 -6
- data/vendor/brotli/c/enc/histogram.h +6 -3
- data/vendor/brotli/c/enc/histogram_inc.h +1 -1
- data/vendor/brotli/c/enc/literal_cost.c +5 -5
- data/vendor/brotli/c/enc/literal_cost.h +2 -2
- data/vendor/brotli/c/enc/memory.c +5 -16
- data/vendor/brotli/c/enc/memory.h +52 -1
- data/vendor/brotli/c/enc/metablock.c +171 -36
- data/vendor/brotli/c/enc/metablock.h +13 -8
- data/vendor/brotli/c/enc/metablock_inc.h +2 -2
- data/vendor/brotli/c/enc/params.h +46 -0
- data/vendor/brotli/c/enc/prefix.h +3 -4
- data/vendor/brotli/c/enc/quality.h +29 -24
- data/vendor/brotli/c/enc/ringbuffer.h +19 -12
- data/vendor/brotli/c/enc/static_dict.c +49 -45
- data/vendor/brotli/c/enc/static_dict.h +4 -3
- data/vendor/brotli/c/enc/static_dict_lut.h +1 -1
- data/vendor/brotli/c/enc/utf8_util.c +21 -21
- data/vendor/brotli/c/enc/utf8_util.h +1 -1
- data/vendor/brotli/c/enc/write_bits.h +35 -38
- data/vendor/brotli/c/include/brotli/decode.h +13 -8
- data/vendor/brotli/c/include/brotli/encode.h +54 -8
- data/vendor/brotli/c/include/brotli/port.h +225 -83
- data/vendor/brotli/c/include/brotli/types.h +0 -7
- metadata +28 -87
- data/.travis.yml +0 -30
- 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/dec/port.h +0 -168
- data/vendor/brotli/c/dec/transform.h +0 -300
- data/vendor/brotli/c/enc/context.h +0 -184
- data/vendor/brotli/c/enc/port.h +0 -184
@@ -9,16 +9,15 @@
|
|
9
9
|
#ifndef BROTLI_ENC_FIND_MATCH_LENGTH_H_
|
10
10
|
#define BROTLI_ENC_FIND_MATCH_LENGTH_H_
|
11
11
|
|
12
|
+
#include "../common/platform.h"
|
12
13
|
#include <brotli/types.h>
|
13
|
-
#include "./port.h"
|
14
14
|
|
15
15
|
#if defined(__cplusplus) || defined(c_plusplus)
|
16
16
|
extern "C" {
|
17
17
|
#endif
|
18
18
|
|
19
19
|
/* Separate implementation for little-endian 64-bit targets, for speed. */
|
20
|
-
#if defined(
|
21
|
-
|
20
|
+
#if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN
|
22
21
|
static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
|
23
22
|
const uint8_t* s2,
|
24
23
|
size_t limit) {
|
@@ -32,7 +31,7 @@ static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
|
|
32
31
|
} else {
|
33
32
|
uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^
|
34
33
|
BROTLI_UNALIGNED_LOAD64LE(s1 + matched);
|
35
|
-
size_t matching_bits = (size_t)
|
34
|
+
size_t matching_bits = (size_t)BROTLI_TZCNT64(x);
|
36
35
|
matched += matching_bits >> 3;
|
37
36
|
return matched;
|
38
37
|
}
|
@@ -60,8 +59,8 @@ static BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,
|
|
60
59
|
the first non-matching bit and use that to calculate the total
|
61
60
|
length of the match. */
|
62
61
|
while (s2_ptr <= s2_limit - 4 &&
|
63
|
-
|
64
|
-
|
62
|
+
BrotliUnalignedRead32(s2_ptr) ==
|
63
|
+
BrotliUnalignedRead32(s1 + matched)) {
|
65
64
|
s2_ptr += 4;
|
66
65
|
matched += 4;
|
67
66
|
}
|
data/vendor/brotli/c/enc/hash.h
CHANGED
@@ -14,11 +14,12 @@
|
|
14
14
|
|
15
15
|
#include "../common/constants.h"
|
16
16
|
#include "../common/dictionary.h"
|
17
|
+
#include "../common/platform.h"
|
17
18
|
#include <brotli/types.h>
|
19
|
+
#include "./encoder_dict.h"
|
18
20
|
#include "./fast_log.h"
|
19
21
|
#include "./find_match_length.h"
|
20
22
|
#include "./memory.h"
|
21
|
-
#include "./port.h"
|
22
23
|
#include "./quality.h"
|
23
24
|
#include "./static_dict.h"
|
24
25
|
|
@@ -26,32 +27,19 @@
|
|
26
27
|
extern "C" {
|
27
28
|
#endif
|
28
29
|
|
29
|
-
/* Pointer to hasher data.
|
30
|
-
*
|
31
|
-
* Excluding initialization and destruction, hasher can be passed as
|
32
|
-
* HasherHandle by value.
|
33
|
-
*
|
34
|
-
* Typically hasher data consists of 3 sections:
|
35
|
-
* * HasherCommon structure
|
36
|
-
* * private structured hasher data, depending on hasher type
|
37
|
-
* * private dynamic hasher data, depending on hasher type and parameters
|
38
|
-
*/
|
39
|
-
typedef uint8_t* HasherHandle;
|
40
|
-
|
41
30
|
typedef struct {
|
31
|
+
/* Dynamically allocated area; first member for quickest access. */
|
32
|
+
void* extra;
|
33
|
+
|
34
|
+
size_t dict_num_lookups;
|
35
|
+
size_t dict_num_matches;
|
36
|
+
|
42
37
|
BrotliHasherParams params;
|
43
38
|
|
44
39
|
/* False if hasher needs to be "prepared" before use. */
|
45
40
|
BROTLI_BOOL is_prepared_;
|
46
|
-
|
47
|
-
size_t dict_num_lookups;
|
48
|
-
size_t dict_num_matches;
|
49
41
|
} HasherCommon;
|
50
42
|
|
51
|
-
static BROTLI_INLINE HasherCommon* GetHasherCommon(HasherHandle handle) {
|
52
|
-
return (HasherCommon*)handle;
|
53
|
-
}
|
54
|
-
|
55
43
|
#define score_t size_t
|
56
44
|
|
57
45
|
static const uint32_t kCutoffTransformsCount = 10;
|
@@ -73,13 +61,13 @@ typedef struct HasherSearchResult {
|
|
73
61
|
* There is no effort to ensure that it is a prime, the oddity is enough
|
74
62
|
for this use.
|
75
63
|
* The number has been tuned heuristically against compression benchmarks. */
|
76
|
-
static const uint32_t kHashMul32 =
|
77
|
-
static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(
|
64
|
+
static const uint32_t kHashMul32 = 0x1E35A7BD;
|
65
|
+
static const uint64_t kHashMul64 = BROTLI_MAKE_UINT64_T(0x1E35A7BD, 0x1E35A7BD);
|
78
66
|
static const uint64_t kHashMul64Long =
|
79
|
-
BROTLI_MAKE_UINT64_T(
|
67
|
+
BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);
|
80
68
|
|
81
69
|
static BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {
|
82
|
-
uint32_t h =
|
70
|
+
uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
|
83
71
|
/* The higher bits contain more mixture from the multiplication,
|
84
72
|
so we take our results from there. */
|
85
73
|
return h >> (32 - 14);
|
@@ -146,34 +134,31 @@ static BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(
|
|
146
134
|
}
|
147
135
|
|
148
136
|
static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
|
149
|
-
const
|
150
|
-
size_t max_length, size_t max_backward,
|
151
|
-
|
152
|
-
size_t dist;
|
137
|
+
const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,
|
138
|
+
const uint8_t* data, size_t max_length, size_t max_backward,
|
139
|
+
size_t max_distance, HasherSearchResult* out) {
|
153
140
|
size_t offset;
|
154
141
|
size_t matchlen;
|
155
142
|
size_t backward;
|
156
143
|
score_t score;
|
157
|
-
|
158
|
-
dist = item >> 5;
|
159
|
-
offset = dictionary->offsets_by_length[len] + len * dist;
|
144
|
+
offset = dictionary->words->offsets_by_length[len] + len * word_idx;
|
160
145
|
if (len > max_length) {
|
161
146
|
return BROTLI_FALSE;
|
162
147
|
}
|
163
148
|
|
164
149
|
matchlen =
|
165
|
-
FindMatchLengthWithLimit(data, &dictionary->data[offset], len);
|
166
|
-
if (matchlen +
|
150
|
+
FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);
|
151
|
+
if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {
|
167
152
|
return BROTLI_FALSE;
|
168
153
|
}
|
169
154
|
{
|
170
155
|
size_t cut = len - matchlen;
|
171
|
-
size_t transform_id =
|
172
|
-
(
|
173
|
-
backward = max_backward +
|
174
|
-
(transform_id << dictionary->size_bits_by_length[len]);
|
156
|
+
size_t transform_id = (cut << 2) +
|
157
|
+
(size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);
|
158
|
+
backward = max_backward + 1 + word_idx +
|
159
|
+
(transform_id << dictionary->words->size_bits_by_length[len]);
|
175
160
|
}
|
176
|
-
if (backward
|
161
|
+
if (backward > max_distance) {
|
177
162
|
return BROTLI_FALSE;
|
178
163
|
}
|
179
164
|
score = BackwardReferenceScore(matchlen, backward);
|
@@ -188,24 +173,25 @@ static BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(
|
|
188
173
|
}
|
189
174
|
|
190
175
|
static BROTLI_INLINE void SearchInStaticDictionary(
|
191
|
-
const
|
192
|
-
|
193
|
-
size_t max_backward,
|
176
|
+
const BrotliEncoderDictionary* dictionary,
|
177
|
+
HasherCommon* common, const uint8_t* data, size_t max_length,
|
178
|
+
size_t max_backward, size_t max_distance,
|
179
|
+
HasherSearchResult* out, BROTLI_BOOL shallow) {
|
194
180
|
size_t key;
|
195
181
|
size_t i;
|
196
|
-
|
197
|
-
if (self->dict_num_matches < (self->dict_num_lookups >> 7)) {
|
182
|
+
if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {
|
198
183
|
return;
|
199
184
|
}
|
200
185
|
key = Hash14(data) << 1;
|
201
186
|
for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {
|
202
|
-
|
203
|
-
|
204
|
-
if (item != 0) {
|
187
|
+
common->dict_num_lookups++;
|
188
|
+
if (dictionary->hash_table_lengths[key] != 0) {
|
205
189
|
BROTLI_BOOL item_matches = TestStaticDictionaryItem(
|
206
|
-
dictionary,
|
190
|
+
dictionary, dictionary->hash_table_lengths[key],
|
191
|
+
dictionary->hash_table_words[key], data,
|
192
|
+
max_length, max_backward, max_distance, out);
|
207
193
|
if (item_matches) {
|
208
|
-
|
194
|
+
common->dict_num_matches++;
|
209
195
|
}
|
210
196
|
}
|
211
197
|
}
|
@@ -254,37 +240,37 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
254
240
|
/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */
|
255
241
|
#define MAX_NUM_MATCHES_H10 128
|
256
242
|
|
257
|
-
/* For
|
243
|
+
/* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression
|
258
244
|
a little faster (0.5% - 1%) and it compresses 0.15% better on small text
|
259
245
|
and HTML inputs. */
|
260
246
|
|
261
247
|
#define HASHER() H2
|
262
248
|
#define BUCKET_BITS 16
|
263
|
-
#define
|
249
|
+
#define BUCKET_SWEEP_BITS 0
|
264
250
|
#define HASH_LEN 5
|
265
251
|
#define USE_DICTIONARY 1
|
266
252
|
#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
267
|
-
#undef
|
253
|
+
#undef BUCKET_SWEEP_BITS
|
268
254
|
#undef USE_DICTIONARY
|
269
255
|
#undef HASHER
|
270
256
|
|
271
257
|
#define HASHER() H3
|
272
|
-
#define
|
258
|
+
#define BUCKET_SWEEP_BITS 1
|
273
259
|
#define USE_DICTIONARY 0
|
274
260
|
#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
275
261
|
#undef USE_DICTIONARY
|
276
|
-
#undef
|
262
|
+
#undef BUCKET_SWEEP_BITS
|
277
263
|
#undef BUCKET_BITS
|
278
264
|
#undef HASHER
|
279
265
|
|
280
266
|
#define HASHER() H4
|
281
267
|
#define BUCKET_BITS 17
|
282
|
-
#define
|
268
|
+
#define BUCKET_SWEEP_BITS 2
|
283
269
|
#define USE_DICTIONARY 1
|
284
270
|
#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
285
271
|
#undef USE_DICTIONARY
|
286
272
|
#undef HASH_LEN
|
287
|
-
#undef
|
273
|
+
#undef BUCKET_SWEEP_BITS
|
288
274
|
#undef BUCKET_BITS
|
289
275
|
#undef HASHER
|
290
276
|
|
@@ -328,110 +314,166 @@ static BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {
|
|
328
314
|
|
329
315
|
#define HASHER() H54
|
330
316
|
#define BUCKET_BITS 20
|
331
|
-
#define
|
317
|
+
#define BUCKET_SWEEP_BITS 2
|
332
318
|
#define HASH_LEN 7
|
333
319
|
#define USE_DICTIONARY 0
|
334
320
|
#include "./hash_longest_match_quickly_inc.h" /* NOLINT(build/include) */
|
335
321
|
#undef USE_DICTIONARY
|
336
322
|
#undef HASH_LEN
|
337
|
-
#undef
|
323
|
+
#undef BUCKET_SWEEP_BITS
|
338
324
|
#undef BUCKET_BITS
|
339
325
|
#undef HASHER
|
340
326
|
|
327
|
+
/* fast large window hashers */
|
328
|
+
|
329
|
+
#define HASHER() HROLLING_FAST
|
330
|
+
#define CHUNKLEN 32
|
331
|
+
#define JUMP 4
|
332
|
+
#define NUMBUCKETS 16777216
|
333
|
+
#define MASK ((NUMBUCKETS * 64) - 1)
|
334
|
+
#include "./hash_rolling_inc.h" /* NOLINT(build/include) */
|
335
|
+
#undef JUMP
|
336
|
+
#undef HASHER
|
337
|
+
|
338
|
+
|
339
|
+
#define HASHER() HROLLING
|
340
|
+
#define JUMP 1
|
341
|
+
#include "./hash_rolling_inc.h" /* NOLINT(build/include) */
|
342
|
+
#undef MASK
|
343
|
+
#undef NUMBUCKETS
|
344
|
+
#undef JUMP
|
345
|
+
#undef CHUNKLEN
|
346
|
+
#undef HASHER
|
347
|
+
|
348
|
+
#define HASHER() H35
|
349
|
+
#define HASHER_A H3
|
350
|
+
#define HASHER_B HROLLING_FAST
|
351
|
+
#include "./hash_composite_inc.h" /* NOLINT(build/include) */
|
352
|
+
#undef HASHER_A
|
353
|
+
#undef HASHER_B
|
354
|
+
#undef HASHER
|
355
|
+
|
356
|
+
#define HASHER() H55
|
357
|
+
#define HASHER_A H54
|
358
|
+
#define HASHER_B HROLLING_FAST
|
359
|
+
#include "./hash_composite_inc.h" /* NOLINT(build/include) */
|
360
|
+
#undef HASHER_A
|
361
|
+
#undef HASHER_B
|
362
|
+
#undef HASHER
|
363
|
+
|
364
|
+
#define HASHER() H65
|
365
|
+
#define HASHER_A H6
|
366
|
+
#define HASHER_B HROLLING
|
367
|
+
#include "./hash_composite_inc.h" /* NOLINT(build/include) */
|
368
|
+
#undef HASHER_A
|
369
|
+
#undef HASHER_B
|
370
|
+
#undef HASHER
|
371
|
+
|
341
372
|
#undef FN
|
342
373
|
#undef CAT
|
343
374
|
#undef EXPAND_CAT
|
344
375
|
|
345
|
-
#define
|
376
|
+
#define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)
|
377
|
+
#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)
|
378
|
+
#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)
|
346
379
|
#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)
|
347
380
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
381
|
+
typedef struct {
|
382
|
+
HasherCommon common;
|
383
|
+
|
384
|
+
union {
|
385
|
+
#define MEMBER_(N) \
|
386
|
+
H ## N _H ## N;
|
387
|
+
FOR_ALL_HASHERS(MEMBER_)
|
388
|
+
#undef MEMBER_
|
389
|
+
} privat;
|
390
|
+
} Hasher;
|
391
|
+
|
392
|
+
/* MUST be invoked before any other method. */
|
393
|
+
static BROTLI_INLINE void HasherInit(Hasher* hasher) {
|
394
|
+
hasher->common.extra = NULL;
|
395
|
+
}
|
396
|
+
|
397
|
+
static BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {
|
398
|
+
if (hasher->common.extra == NULL) return;
|
399
|
+
BROTLI_FREE(m, hasher->common.extra);
|
352
400
|
}
|
353
401
|
|
354
|
-
static BROTLI_INLINE void HasherReset(
|
355
|
-
|
356
|
-
GetHasherCommon(handle)->is_prepared_ = BROTLI_FALSE;
|
402
|
+
static BROTLI_INLINE void HasherReset(Hasher* hasher) {
|
403
|
+
hasher->common.is_prepared_ = BROTLI_FALSE;
|
357
404
|
}
|
358
405
|
|
359
406
|
static BROTLI_INLINE size_t HasherSize(const BrotliEncoderParams* params,
|
360
407
|
BROTLI_BOOL one_shot, const size_t input_size) {
|
361
|
-
size_t result = sizeof(HasherCommon);
|
362
408
|
switch (params->hasher.type) {
|
363
|
-
#define SIZE_(N)
|
364
|
-
case N:
|
365
|
-
|
366
|
-
break;
|
409
|
+
#define SIZE_(N) \
|
410
|
+
case N: \
|
411
|
+
return HashMemAllocInBytesH ## N(params, one_shot, input_size);
|
367
412
|
FOR_ALL_HASHERS(SIZE_)
|
368
413
|
#undef SIZE_
|
369
414
|
default:
|
370
415
|
break;
|
371
416
|
}
|
372
|
-
return
|
417
|
+
return 0; /* Default case. */
|
373
418
|
}
|
374
419
|
|
375
|
-
static BROTLI_INLINE void HasherSetup(MemoryManager* m,
|
420
|
+
static BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,
|
376
421
|
BrotliEncoderParams* params, const uint8_t* data, size_t position,
|
377
422
|
size_t input_size, BROTLI_BOOL is_last) {
|
378
|
-
HasherHandle self = NULL;
|
379
|
-
HasherCommon* common = NULL;
|
380
423
|
BROTLI_BOOL one_shot = (position == 0 && is_last);
|
381
|
-
if (
|
424
|
+
if (hasher->common.extra == NULL) {
|
382
425
|
size_t alloc_size;
|
383
426
|
ChooseHasher(params, ¶ms->hasher);
|
384
427
|
alloc_size = HasherSize(params, one_shot, input_size);
|
385
|
-
|
386
|
-
if (BROTLI_IS_OOM(m)) return;
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
InitializeH ## N(*handle, params); \
|
428
|
+
hasher->common.extra = BROTLI_ALLOC(m, uint8_t, alloc_size);
|
429
|
+
if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra)) return;
|
430
|
+
hasher->common.params = params->hasher;
|
431
|
+
switch (hasher->common.params.type) {
|
432
|
+
#define INITIALIZE_(N) \
|
433
|
+
case N: \
|
434
|
+
InitializeH ## N(&hasher->common, \
|
435
|
+
&hasher->privat._H ## N, params); \
|
394
436
|
break;
|
395
437
|
FOR_ALL_HASHERS(INITIALIZE_);
|
396
438
|
#undef INITIALIZE_
|
397
439
|
default:
|
398
440
|
break;
|
399
441
|
}
|
400
|
-
HasherReset(
|
442
|
+
HasherReset(hasher);
|
401
443
|
}
|
402
444
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
445
|
+
if (!hasher->common.is_prepared_) {
|
446
|
+
switch (hasher->common.params.type) {
|
447
|
+
#define PREPARE_(N) \
|
448
|
+
case N: \
|
449
|
+
PrepareH ## N( \
|
450
|
+
&hasher->privat._H ## N, \
|
451
|
+
one_shot, input_size, data); \
|
410
452
|
break;
|
411
453
|
FOR_ALL_HASHERS(PREPARE_)
|
412
454
|
#undef PREPARE_
|
413
455
|
default: break;
|
414
456
|
}
|
415
457
|
if (position == 0) {
|
416
|
-
|
417
|
-
|
458
|
+
hasher->common.dict_num_lookups = 0;
|
459
|
+
hasher->common.dict_num_matches = 0;
|
418
460
|
}
|
419
|
-
common
|
461
|
+
hasher->common.is_prepared_ = BROTLI_TRUE;
|
420
462
|
}
|
421
463
|
}
|
422
464
|
|
423
465
|
static BROTLI_INLINE void InitOrStitchToPreviousBlock(
|
424
|
-
MemoryManager* m,
|
466
|
+
MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,
|
425
467
|
BrotliEncoderParams* params, size_t position, size_t input_size,
|
426
468
|
BROTLI_BOOL is_last) {
|
427
|
-
|
428
|
-
HasherSetup(m, handle, params, data, position, input_size, is_last);
|
469
|
+
HasherSetup(m, hasher, params, data, position, input_size, is_last);
|
429
470
|
if (BROTLI_IS_OOM(m)) return;
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
471
|
+
switch (hasher->common.params.type) {
|
472
|
+
#define INIT_(N) \
|
473
|
+
case N: \
|
474
|
+
StitchToPreviousBlockH ## N( \
|
475
|
+
&hasher->privat._H ## N, \
|
476
|
+
input_size, position, data, mask); \
|
435
477
|
break;
|
436
478
|
FOR_ALL_HASHERS(INIT_)
|
437
479
|
#undef INIT_
|
@@ -0,0 +1,125 @@
|
|
1
|
+
/* NOLINT(build/header_guard) */
|
2
|
+
/* Copyright 2018 Google Inc. All Rights Reserved.
|
3
|
+
|
4
|
+
Distributed under MIT license.
|
5
|
+
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
6
|
+
*/
|
7
|
+
|
8
|
+
/* template parameters: FN, HASHER_A, HASHER_B */
|
9
|
+
|
10
|
+
/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A
|
11
|
+
and HASHER_B. */
|
12
|
+
|
13
|
+
#define HashComposite HASHER()
|
14
|
+
|
15
|
+
#define FN_A(X) EXPAND_CAT(X, HASHER_A)
|
16
|
+
#define FN_B(X) EXPAND_CAT(X, HASHER_B)
|
17
|
+
|
18
|
+
static BROTLI_INLINE size_t FN(HashTypeLength)(void) {
|
19
|
+
size_t a = FN_A(HashTypeLength)();
|
20
|
+
size_t b = FN_B(HashTypeLength)();
|
21
|
+
return a > b ? a : b;
|
22
|
+
}
|
23
|
+
|
24
|
+
static BROTLI_INLINE size_t FN(StoreLookahead)(void) {
|
25
|
+
size_t a = FN_A(StoreLookahead)();
|
26
|
+
size_t b = FN_B(StoreLookahead)();
|
27
|
+
return a > b ? a : b;
|
28
|
+
}
|
29
|
+
|
30
|
+
typedef struct HashComposite {
|
31
|
+
HASHER_A ha;
|
32
|
+
HASHER_B hb;
|
33
|
+
HasherCommon hb_common;
|
34
|
+
|
35
|
+
/* Shortcuts. */
|
36
|
+
void* extra;
|
37
|
+
HasherCommon* common;
|
38
|
+
|
39
|
+
BROTLI_BOOL fresh;
|
40
|
+
const BrotliEncoderParams* params;
|
41
|
+
} HashComposite;
|
42
|
+
|
43
|
+
static void FN(Initialize)(HasherCommon* common,
|
44
|
+
HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {
|
45
|
+
self->common = common;
|
46
|
+
self->extra = common->extra;
|
47
|
+
|
48
|
+
self->hb_common = *self->common;
|
49
|
+
self->fresh = BROTLI_TRUE;
|
50
|
+
self->params = params;
|
51
|
+
/* TODO: Initialize of the hashers is defered to Prepare (and params
|
52
|
+
remembered here) because we don't get the one_shot and input_size params
|
53
|
+
here that are needed to know the memory size of them. Instead provide
|
54
|
+
those params to all hashers FN(Initialize) */
|
55
|
+
}
|
56
|
+
|
57
|
+
static void FN(Prepare)(
|
58
|
+
HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
|
59
|
+
size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
|
60
|
+
if (self->fresh) {
|
61
|
+
self->fresh = BROTLI_FALSE;
|
62
|
+
self->hb_common.extra = (uint8_t*)self->extra +
|
63
|
+
FN_A(HashMemAllocInBytes)(self->params, one_shot, input_size);
|
64
|
+
|
65
|
+
FN_A(Initialize)(self->common, &self->ha, self->params);
|
66
|
+
FN_B(Initialize)(&self->hb_common, &self->hb, self->params);
|
67
|
+
}
|
68
|
+
FN_A(Prepare)(&self->ha, one_shot, input_size, data);
|
69
|
+
FN_B(Prepare)(&self->hb, one_shot, input_size, data);
|
70
|
+
}
|
71
|
+
|
72
|
+
static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
|
73
|
+
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
74
|
+
size_t input_size) {
|
75
|
+
return FN_A(HashMemAllocInBytes)(params, one_shot, input_size) +
|
76
|
+
FN_B(HashMemAllocInBytes)(params, one_shot, input_size);
|
77
|
+
}
|
78
|
+
|
79
|
+
static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,
|
80
|
+
const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
|
81
|
+
FN_A(Store)(&self->ha, data, mask, ix);
|
82
|
+
FN_B(Store)(&self->hb, data, mask, ix);
|
83
|
+
}
|
84
|
+
|
85
|
+
static BROTLI_INLINE void FN(StoreRange)(
|
86
|
+
HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
|
87
|
+
const size_t mask, const size_t ix_start,
|
88
|
+
const size_t ix_end) {
|
89
|
+
FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);
|
90
|
+
FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);
|
91
|
+
}
|
92
|
+
|
93
|
+
static BROTLI_INLINE void FN(StitchToPreviousBlock)(
|
94
|
+
HashComposite* BROTLI_RESTRICT self,
|
95
|
+
size_t num_bytes, size_t position, const uint8_t* ringbuffer,
|
96
|
+
size_t ring_buffer_mask) {
|
97
|
+
FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position,
|
98
|
+
ringbuffer, ring_buffer_mask);
|
99
|
+
FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position,
|
100
|
+
ringbuffer, ring_buffer_mask);
|
101
|
+
}
|
102
|
+
|
103
|
+
static BROTLI_INLINE void FN(PrepareDistanceCache)(
|
104
|
+
HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) {
|
105
|
+
FN_A(PrepareDistanceCache)(&self->ha, distance_cache);
|
106
|
+
FN_B(PrepareDistanceCache)(&self->hb, distance_cache);
|
107
|
+
}
|
108
|
+
|
109
|
+
static BROTLI_INLINE void FN(FindLongestMatch)(
|
110
|
+
HashComposite* BROTLI_RESTRICT self,
|
111
|
+
const BrotliEncoderDictionary* dictionary,
|
112
|
+
const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
|
113
|
+
const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
|
114
|
+
const size_t max_length, const size_t max_backward,
|
115
|
+
const size_t dictionary_distance, const size_t max_distance,
|
116
|
+
HasherSearchResult* BROTLI_RESTRICT out) {
|
117
|
+
FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,
|
118
|
+
distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
|
119
|
+
max_distance, out);
|
120
|
+
FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,
|
121
|
+
distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
|
122
|
+
max_distance, out);
|
123
|
+
}
|
124
|
+
|
125
|
+
#undef HashComposite
|