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
@@ -28,108 +28,112 @@ static BROTLI_INLINE size_t FN(StoreLookahead)(void) {
|
|
28
28
|
}
|
29
29
|
|
30
30
|
typedef struct HashComposite {
|
31
|
-
|
32
|
-
|
31
|
+
HASHER_A ha;
|
32
|
+
HASHER_B hb;
|
33
|
+
HasherCommon ha_common;
|
34
|
+
HasherCommon hb_common;
|
35
|
+
|
36
|
+
/* Shortcuts. */
|
37
|
+
HasherCommon* common;
|
38
|
+
|
39
|
+
BROTLI_BOOL fresh;
|
33
40
|
const BrotliEncoderParams* params;
|
34
41
|
} HashComposite;
|
35
42
|
|
36
|
-
static
|
37
|
-
|
38
|
-
|
43
|
+
static void FN(Initialize)(HasherCommon* common,
|
44
|
+
HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {
|
45
|
+
self->common = common;
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
self->ha = 0;
|
44
|
-
self->hb = 0;
|
47
|
+
self->ha_common = *self->common;
|
48
|
+
self->hb_common = *self->common;
|
49
|
+
self->fresh = BROTLI_TRUE;
|
45
50
|
self->params = params;
|
46
|
-
/* TODO: Initialize of the hashers is
|
51
|
+
/* TODO(lode): Initialize of the hashers is deferred to Prepare (and params
|
47
52
|
remembered here) because we don't get the one_shot and input_size params
|
48
53
|
here that are needed to know the memory size of them. Instead provide
|
49
54
|
those params to all hashers FN(Initialize) */
|
50
55
|
}
|
51
56
|
|
52
|
-
static void FN(Prepare)(
|
53
|
-
|
54
|
-
|
55
|
-
if (
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
self->
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
self->hb
|
68
|
-
self->params, one_shot, input_size);
|
69
|
-
common_b = (HasherCommon*)self->hb;
|
70
|
-
common_b->params = self->params->hasher;
|
71
|
-
common_b->is_prepared_ = BROTLI_FALSE;
|
72
|
-
common_b->dict_num_lookups = 0;
|
73
|
-
common_b->dict_num_matches = 0;
|
74
|
-
FN_B(Initialize)(self->hb, self->params);
|
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->ha_common.extra[0] = self->common->extra[0];
|
63
|
+
self->ha_common.extra[1] = self->common->extra[1];
|
64
|
+
self->ha_common.extra[2] = NULL;
|
65
|
+
self->ha_common.extra[3] = NULL;
|
66
|
+
self->hb_common.extra[0] = self->common->extra[2];
|
67
|
+
self->hb_common.extra[1] = self->common->extra[3];
|
68
|
+
self->hb_common.extra[2] = NULL;
|
69
|
+
self->hb_common.extra[3] = NULL;
|
70
|
+
|
71
|
+
FN_A(Initialize)(&self->ha_common, &self->ha, self->params);
|
72
|
+
FN_B(Initialize)(&self->hb_common, &self->hb, self->params);
|
75
73
|
}
|
76
|
-
FN_A(Prepare)(self->ha, one_shot, input_size, data);
|
77
|
-
FN_B(Prepare)(self->hb, one_shot, input_size, data);
|
74
|
+
FN_A(Prepare)(&self->ha, one_shot, input_size, data);
|
75
|
+
FN_B(Prepare)(&self->hb, one_shot, input_size, data);
|
78
76
|
}
|
79
77
|
|
80
|
-
static BROTLI_INLINE
|
78
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
81
79
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
82
|
-
size_t input_size) {
|
83
|
-
|
84
|
-
|
85
|
-
|
80
|
+
size_t input_size, size_t* alloc_size) {
|
81
|
+
size_t alloc_size_a[4] = {0};
|
82
|
+
size_t alloc_size_b[4] = {0};
|
83
|
+
FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a);
|
84
|
+
FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b);
|
85
|
+
/* Should never happen. */
|
86
|
+
if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE);
|
87
|
+
if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE);
|
88
|
+
alloc_size[0] = alloc_size_a[0];
|
89
|
+
alloc_size[1] = alloc_size_a[1];
|
90
|
+
alloc_size[2] = alloc_size_b[0];
|
91
|
+
alloc_size[3] = alloc_size_b[1];
|
86
92
|
}
|
87
93
|
|
88
|
-
static BROTLI_INLINE void FN(Store)(
|
94
|
+
static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,
|
89
95
|
const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
|
90
|
-
|
91
|
-
|
92
|
-
FN_B(Store)(self->hb, data, mask, ix);
|
96
|
+
FN_A(Store)(&self->ha, data, mask, ix);
|
97
|
+
FN_B(Store)(&self->hb, data, mask, ix);
|
93
98
|
}
|
94
99
|
|
95
|
-
static BROTLI_INLINE void FN(StoreRange)(
|
96
|
-
|
100
|
+
static BROTLI_INLINE void FN(StoreRange)(
|
101
|
+
HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
|
102
|
+
const size_t mask, const size_t ix_start,
|
97
103
|
const size_t ix_end) {
|
98
|
-
|
99
|
-
|
100
|
-
FN_B(StoreRange)(self->hb, data, mask, ix_start, ix_end);
|
104
|
+
FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);
|
105
|
+
FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);
|
101
106
|
}
|
102
107
|
|
103
|
-
static BROTLI_INLINE void FN(StitchToPreviousBlock)(
|
108
|
+
static BROTLI_INLINE void FN(StitchToPreviousBlock)(
|
109
|
+
HashComposite* BROTLI_RESTRICT self,
|
104
110
|
size_t num_bytes, size_t position, const uint8_t* ringbuffer,
|
105
111
|
size_t ring_buffer_mask) {
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
ring_buffer_mask);
|
112
|
+
FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position,
|
113
|
+
ringbuffer, ring_buffer_mask);
|
114
|
+
FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position,
|
115
|
+
ringbuffer, ring_buffer_mask);
|
111
116
|
}
|
112
117
|
|
113
118
|
static BROTLI_INLINE void FN(PrepareDistanceCache)(
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
FN_B(PrepareDistanceCache)(self->hb, distance_cache);
|
119
|
+
HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) {
|
120
|
+
FN_A(PrepareDistanceCache)(&self->ha, distance_cache);
|
121
|
+
FN_B(PrepareDistanceCache)(&self->hb, distance_cache);
|
118
122
|
}
|
119
123
|
|
120
|
-
static BROTLI_INLINE void FN(FindLongestMatch)(
|
124
|
+
static BROTLI_INLINE void FN(FindLongestMatch)(
|
125
|
+
HashComposite* BROTLI_RESTRICT self,
|
121
126
|
const BrotliEncoderDictionary* dictionary,
|
122
127
|
const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
|
123
128
|
const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
|
124
129
|
const size_t max_length, const size_t max_backward,
|
125
|
-
const size_t
|
130
|
+
const size_t dictionary_distance, const size_t max_distance,
|
126
131
|
HasherSearchResult* BROTLI_RESTRICT out) {
|
127
|
-
|
128
|
-
|
129
|
-
distance_cache, cur_ix, max_length, max_backward, gap,
|
132
|
+
FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,
|
133
|
+
distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
|
130
134
|
max_distance, out);
|
131
|
-
FN_B(FindLongestMatch)(self->hb, dictionary, data, ring_buffer_mask,
|
132
|
-
distance_cache, cur_ix, max_length, max_backward,
|
135
|
+
FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,
|
136
|
+
distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
|
133
137
|
max_distance, out);
|
134
138
|
}
|
135
139
|
|
@@ -28,7 +28,7 @@ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }
|
|
28
28
|
static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }
|
29
29
|
|
30
30
|
/* HashBytes is the function that chooses the bucket to place the address in.*/
|
31
|
-
static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* data) {
|
31
|
+
static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {
|
32
32
|
const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
|
33
33
|
/* The higher bits contain more mixture from the multiplication,
|
34
34
|
so we take our results from there. */
|
@@ -45,28 +45,57 @@ typedef struct FN(Bank) {
|
|
45
45
|
} FN(Bank);
|
46
46
|
|
47
47
|
typedef struct HashForgetfulChain {
|
48
|
-
|
49
|
-
uint16_t head[BUCKET_SIZE];
|
50
|
-
/* Truncated hash used for quick rejection of "distance cache" candidates. */
|
51
|
-
uint8_t tiny_hash[65536];
|
52
|
-
FN(Bank) banks[NUM_BANKS];
|
53
|
-
uint16_t free_slot_idx[NUM_BANKS];
|
48
|
+
uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */
|
54
49
|
size_t max_hops;
|
50
|
+
|
51
|
+
/* Shortcuts. */
|
52
|
+
void* extra[2];
|
53
|
+
HasherCommon* common;
|
54
|
+
|
55
|
+
/* --- Dynamic size members --- */
|
56
|
+
|
57
|
+
/* uint32_t addr[BUCKET_SIZE]; */
|
58
|
+
|
59
|
+
/* uint16_t head[BUCKET_SIZE]; */
|
60
|
+
|
61
|
+
/* Truncated hash used for quick rejection of "distance cache" candidates. */
|
62
|
+
/* uint8_t tiny_hash[65536];*/
|
63
|
+
|
64
|
+
/* FN(Bank) banks[NUM_BANKS]; */
|
55
65
|
} HashForgetfulChain;
|
56
66
|
|
57
|
-
static
|
58
|
-
return (
|
67
|
+
static uint32_t* FN(Addr)(void* extra) {
|
68
|
+
return (uint32_t*)extra;
|
69
|
+
}
|
70
|
+
|
71
|
+
static uint16_t* FN(Head)(void* extra) {
|
72
|
+
return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]);
|
73
|
+
}
|
74
|
+
|
75
|
+
static uint8_t* FN(TinyHash)(void* extra) {
|
76
|
+
return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]);
|
77
|
+
}
|
78
|
+
|
79
|
+
static FN(Bank)* FN(Banks)(void* extra) {
|
80
|
+
return (FN(Bank)*)(extra);
|
59
81
|
}
|
60
82
|
|
61
83
|
static void FN(Initialize)(
|
62
|
-
|
63
|
-
|
64
|
-
|
84
|
+
HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self,
|
85
|
+
const BrotliEncoderParams* params) {
|
86
|
+
self->common = common;
|
87
|
+
self->extra[0] = common->extra[0];
|
88
|
+
self->extra[1] = common->extra[1];
|
89
|
+
|
90
|
+
self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4);
|
65
91
|
}
|
66
92
|
|
67
|
-
static void FN(Prepare)(
|
68
|
-
|
69
|
-
|
93
|
+
static void FN(Prepare)(
|
94
|
+
HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
|
95
|
+
size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
|
96
|
+
uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);
|
97
|
+
uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);
|
98
|
+
uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]);
|
70
99
|
/* Partial preparation is 100 times slower (per socket). */
|
71
100
|
size_t partial_prepare_threshold = BUCKET_SIZE >> 6;
|
72
101
|
if (one_shot && input_size <= partial_prepare_threshold) {
|
@@ -74,71 +103,79 @@ static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot,
|
|
74
103
|
for (i = 0; i < input_size; ++i) {
|
75
104
|
size_t bucket = FN(HashBytes)(&data[i]);
|
76
105
|
/* See InitEmpty comment. */
|
77
|
-
|
78
|
-
|
106
|
+
addr[bucket] = 0xCCCCCCCC;
|
107
|
+
head[bucket] = 0xCCCC;
|
79
108
|
}
|
80
109
|
} else {
|
81
110
|
/* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position
|
82
111
|
processed by hasher never reaches 3GB + 64M; this makes all new chains
|
83
112
|
to be terminated after the first node. */
|
84
|
-
memset(
|
85
|
-
memset(
|
113
|
+
memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE);
|
114
|
+
memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE);
|
86
115
|
}
|
87
|
-
memset(
|
116
|
+
memset(tiny_hash, 0, sizeof(uint8_t) * 65536);
|
88
117
|
memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx));
|
89
118
|
}
|
90
119
|
|
91
|
-
static BROTLI_INLINE
|
120
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
92
121
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
93
|
-
size_t input_size) {
|
122
|
+
size_t input_size, size_t* alloc_size) {
|
94
123
|
BROTLI_UNUSED(params);
|
95
124
|
BROTLI_UNUSED(one_shot);
|
96
125
|
BROTLI_UNUSED(input_size);
|
97
|
-
|
126
|
+
alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE +
|
127
|
+
sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536;
|
128
|
+
alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS;
|
98
129
|
}
|
99
130
|
|
100
131
|
/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend
|
101
132
|
node to corresponding chain; also update tiny_hash for current position. */
|
102
|
-
static BROTLI_INLINE void FN(Store)(
|
133
|
+
static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self,
|
103
134
|
const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
|
104
|
-
|
135
|
+
uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);
|
136
|
+
uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);
|
137
|
+
uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]);
|
138
|
+
FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]);
|
105
139
|
const size_t key = FN(HashBytes)(&data[ix & mask]);
|
106
140
|
const size_t bank = key & (NUM_BANKS - 1);
|
107
141
|
const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1);
|
108
|
-
size_t delta = ix -
|
109
|
-
|
142
|
+
size_t delta = ix - addr[key];
|
143
|
+
tiny_hash[(uint16_t)ix] = (uint8_t)key;
|
110
144
|
if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF;
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
145
|
+
banks[bank].slots[idx].delta = (uint16_t)delta;
|
146
|
+
banks[bank].slots[idx].next = head[key];
|
147
|
+
addr[key] = (uint32_t)ix;
|
148
|
+
head[key] = (uint16_t)idx;
|
115
149
|
}
|
116
150
|
|
117
|
-
static BROTLI_INLINE void FN(StoreRange)(
|
118
|
-
|
119
|
-
const size_t
|
151
|
+
static BROTLI_INLINE void FN(StoreRange)(
|
152
|
+
HashForgetfulChain* BROTLI_RESTRICT self,
|
153
|
+
const uint8_t* BROTLI_RESTRICT data, const size_t mask,
|
154
|
+
const size_t ix_start, const size_t ix_end) {
|
120
155
|
size_t i;
|
121
156
|
for (i = ix_start; i < ix_end; ++i) {
|
122
|
-
FN(Store)(
|
157
|
+
FN(Store)(self, data, mask, i);
|
123
158
|
}
|
124
159
|
}
|
125
160
|
|
126
|
-
static BROTLI_INLINE void FN(StitchToPreviousBlock)(
|
161
|
+
static BROTLI_INLINE void FN(StitchToPreviousBlock)(
|
162
|
+
HashForgetfulChain* BROTLI_RESTRICT self,
|
127
163
|
size_t num_bytes, size_t position, const uint8_t* ringbuffer,
|
128
164
|
size_t ring_buffer_mask) {
|
129
165
|
if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
|
130
166
|
/* Prepare the hashes for three last bytes of the last write.
|
131
167
|
These could not be calculated before, since they require knowledge
|
132
168
|
of both the previous and the current block. */
|
133
|
-
FN(Store)(
|
134
|
-
FN(Store)(
|
135
|
-
FN(Store)(
|
169
|
+
FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3);
|
170
|
+
FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2);
|
171
|
+
FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1);
|
136
172
|
}
|
137
173
|
}
|
138
174
|
|
139
175
|
static BROTLI_INLINE void FN(PrepareDistanceCache)(
|
140
|
-
|
141
|
-
|
176
|
+
HashForgetfulChain* BROTLI_RESTRICT self,
|
177
|
+
int* BROTLI_RESTRICT distance_cache) {
|
178
|
+
BROTLI_UNUSED(self);
|
142
179
|
PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK);
|
143
180
|
}
|
144
181
|
|
@@ -153,14 +190,18 @@ static BROTLI_INLINE void FN(PrepareDistanceCache)(
|
|
153
190
|
Does not look for matches further away than max_backward.
|
154
191
|
Writes the best match into |out|.
|
155
192
|
|out|->score is updated only if a better match is found. */
|
156
|
-
static BROTLI_INLINE void FN(FindLongestMatch)(
|
193
|
+
static BROTLI_INLINE void FN(FindLongestMatch)(
|
194
|
+
HashForgetfulChain* BROTLI_RESTRICT self,
|
157
195
|
const BrotliEncoderDictionary* dictionary,
|
158
196
|
const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
|
159
197
|
const int* BROTLI_RESTRICT distance_cache,
|
160
198
|
const size_t cur_ix, const size_t max_length, const size_t max_backward,
|
161
|
-
const size_t
|
199
|
+
const size_t dictionary_distance, const size_t max_distance,
|
162
200
|
HasherSearchResult* BROTLI_RESTRICT out) {
|
163
|
-
|
201
|
+
uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);
|
202
|
+
uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);
|
203
|
+
uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]);
|
204
|
+
FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]);
|
164
205
|
const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
|
165
206
|
/* Don't accept a short copy from far away. */
|
166
207
|
score_t min_score = out->score;
|
@@ -176,7 +217,7 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
|
|
176
217
|
const size_t backward = (size_t)distance_cache[i];
|
177
218
|
size_t prev_ix = (cur_ix - backward);
|
178
219
|
/* For distance code 0 we want to consider 2-byte matches. */
|
179
|
-
if (i > 0 &&
|
220
|
+
if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue;
|
180
221
|
if (prev_ix >= cur_ix || backward > max_backward) {
|
181
222
|
continue;
|
182
223
|
}
|
@@ -204,16 +245,16 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
|
|
204
245
|
const size_t bank = key & (NUM_BANKS - 1);
|
205
246
|
size_t backward = 0;
|
206
247
|
size_t hops = self->max_hops;
|
207
|
-
size_t delta = cur_ix -
|
208
|
-
size_t slot =
|
248
|
+
size_t delta = cur_ix - addr[key];
|
249
|
+
size_t slot = head[key];
|
209
250
|
while (hops--) {
|
210
251
|
size_t prev_ix;
|
211
252
|
size_t last = slot;
|
212
253
|
backward += delta;
|
213
254
|
if (backward > max_backward || (CAPPED_CHAINS && !delta)) break;
|
214
255
|
prev_ix = (cur_ix - backward) & ring_buffer_mask;
|
215
|
-
slot =
|
216
|
-
delta =
|
256
|
+
slot = banks[bank].slots[last].next;
|
257
|
+
delta = banks[bank].slots[last].delta;
|
217
258
|
if (cur_ix_masked + best_len > ring_buffer_mask ||
|
218
259
|
prev_ix + best_len > ring_buffer_mask ||
|
219
260
|
data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
|
@@ -238,11 +279,11 @@ static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle,
|
|
238
279
|
}
|
239
280
|
}
|
240
281
|
}
|
241
|
-
FN(Store)(
|
282
|
+
FN(Store)(self, data, ring_buffer_mask, cur_ix);
|
242
283
|
}
|
243
284
|
if (out->score == min_score) {
|
244
285
|
SearchInStaticDictionary(dictionary,
|
245
|
-
|
286
|
+
self->common, &data[cur_ix_masked], max_length, dictionary_distance,
|
246
287
|
max_distance, out, BROTLI_FALSE);
|
247
288
|
}
|
248
289
|
}
|