brotli 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +6 -3
- data/.github/workflows/publish.yml +7 -17
- data/.gitmodules +1 -1
- data/README.md +2 -2
- data/ext/brotli/brotli.c +1 -0
- data/ext/brotli/extconf.rb +6 -0
- data/lib/brotli/version.rb +1 -1
- data/test/brotli_test.rb +4 -1
- data/vendor/brotli/c/common/constants.c +1 -1
- data/vendor/brotli/c/common/constants.h +2 -1
- data/vendor/brotli/c/common/context.c +1 -1
- data/vendor/brotli/c/common/dictionary.c +5 -3
- data/vendor/brotli/c/common/platform.c +2 -1
- data/vendor/brotli/c/common/platform.h +60 -113
- 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 +1 -1
- data/vendor/brotli/c/common/version.h +31 -6
- data/vendor/brotli/c/dec/bit_reader.c +10 -8
- data/vendor/brotli/c/dec/bit_reader.h +172 -100
- data/vendor/brotli/c/dec/decode.c +467 -200
- data/vendor/brotli/c/dec/huffman.c +7 -4
- data/vendor/brotli/c/dec/huffman.h +2 -1
- data/vendor/brotli/c/dec/prefix.h +2 -1
- data/vendor/brotli/c/dec/state.c +33 -9
- data/vendor/brotli/c/dec/state.h +70 -35
- data/vendor/brotli/c/enc/backward_references.c +81 -19
- data/vendor/brotli/c/enc/backward_references.h +5 -4
- data/vendor/brotli/c/enc/backward_references_hq.c +148 -52
- data/vendor/brotli/c/enc/backward_references_hq.h +6 -5
- data/vendor/brotli/c/enc/backward_references_inc.h +31 -5
- 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 +37 -14
- data/vendor/brotli/c/enc/block_splitter.h +5 -4
- data/vendor/brotli/c/enc/block_splitter_inc.h +86 -45
- data/vendor/brotli/c/enc/brotli_bit_stream.c +132 -110
- 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 +25 -20
- data/vendor/brotli/c/enc/command.c +1 -1
- data/vendor/brotli/c/enc/command.h +5 -4
- 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 +99 -87
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
- data/vendor/brotli/c/enc/dictionary_hash.c +3 -1
- data/vendor/brotli/c/enc/encode.c +473 -404
- data/vendor/brotli/c/enc/encoder_dict.c +611 -4
- data/vendor/brotli/c/enc/encoder_dict.h +117 -3
- data/vendor/brotli/c/enc/entropy_encode.c +3 -2
- data/vendor/brotli/c/enc/entropy_encode.h +2 -1
- data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
- data/vendor/brotli/c/enc/fast_log.c +1 -1
- data/vendor/brotli/c/enc/fast_log.h +2 -1
- data/vendor/brotli/c/enc/find_match_length.h +15 -22
- data/vendor/brotli/c/enc/hash.h +285 -45
- data/vendor/brotli/c/enc/hash_composite_inc.h +26 -11
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +20 -18
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +34 -39
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +6 -10
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +4 -4
- data/vendor/brotli/c/enc/hash_rolling_inc.h +4 -4
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +6 -5
- 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 +19 -2
- data/vendor/brotli/c/enc/metablock.c +72 -58
- data/vendor/brotli/c/enc/metablock.h +9 -8
- data/vendor/brotli/c/enc/metablock_inc.h +8 -6
- data/vendor/brotli/c/enc/params.h +4 -3
- 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 +4 -3
- 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 +1 -1
- data/vendor/brotli/c/enc/utf8_util.h +2 -1
- data/vendor/brotli/c/enc/write_bits.h +2 -1
- data/vendor/brotli/c/include/brotli/decode.h +67 -2
- data/vendor/brotli/c/include/brotli/encode.h +55 -2
- data/vendor/brotli/c/include/brotli/port.h +28 -11
- data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
- metadata +9 -3
@@ -20,13 +20,12 @@ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }
|
|
20
20
|
static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }
|
21
21
|
|
22
22
|
/* HashBytes is the function that chooses the bucket to place the address in. */
|
23
|
-
static BROTLI_INLINE
|
24
|
-
|
25
|
-
|
26
|
-
const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(data) & mask) * kHashMul64Long;
|
23
|
+
static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data,
|
24
|
+
uint64_t hash_mul) {
|
25
|
+
const uint64_t h = BROTLI_UNALIGNED_LOAD64LE(data) * hash_mul;
|
27
26
|
/* The higher bits contain more mixture from the multiplication,
|
28
27
|
so we take our results from there. */
|
29
|
-
return (
|
28
|
+
return (size_t)(h >> (64 - 15));
|
30
29
|
}
|
31
30
|
|
32
31
|
typedef struct HashLongestMatch {
|
@@ -35,10 +34,8 @@ typedef struct HashLongestMatch {
|
|
35
34
|
/* Only block_size_ newest backward references are kept,
|
36
35
|
and the older are forgotten. */
|
37
36
|
size_t block_size_;
|
38
|
-
/*
|
39
|
-
|
40
|
-
/* Mask for selecting the next 4-8 bytes of input */
|
41
|
-
uint64_t hash_mask_;
|
37
|
+
/* Hash multiplier tuned to match length. */
|
38
|
+
uint64_t hash_mul_;
|
42
39
|
/* Mask for accessing entries in a block (in a ring-buffer manner). */
|
43
40
|
uint32_t block_mask_;
|
44
41
|
|
@@ -63,16 +60,16 @@ static void FN(Initialize)(
|
|
63
60
|
self->common_ = common;
|
64
61
|
|
65
62
|
BROTLI_UNUSED(params);
|
66
|
-
self->
|
67
|
-
|
63
|
+
self->hash_mul_ = kHashMul64 << (64 - 5 * 8);
|
64
|
+
BROTLI_DCHECK(common->params.bucket_bits == 15);
|
68
65
|
self->bucket_size_ = (size_t)1 << common->params.bucket_bits;
|
69
66
|
self->block_bits_ = common->params.block_bits;
|
70
67
|
self->block_size_ = (size_t)1 << common->params.block_bits;
|
71
68
|
self->block_mask_ = (uint32_t)(self->block_size_ - 1);
|
72
69
|
self->num_last_distances_to_check_ =
|
73
70
|
common->params.num_last_distances_to_check;
|
74
|
-
self->num_ = (uint16_t*)common->extra;
|
75
|
-
self->buckets_ = (uint32_t*)
|
71
|
+
self->num_ = (uint16_t*)common->extra[0];
|
72
|
+
self->buckets_ = (uint32_t*)common->extra[1];
|
76
73
|
}
|
77
74
|
|
78
75
|
static void FN(Prepare)(
|
@@ -84,8 +81,7 @@ static void FN(Prepare)(
|
|
84
81
|
if (one_shot && input_size <= partial_prepare_threshold) {
|
85
82
|
size_t i;
|
86
83
|
for (i = 0; i < input_size; ++i) {
|
87
|
-
const
|
88
|
-
self->hash_shift_);
|
84
|
+
const size_t key = FN(HashBytes)(&data[i], self->hash_mul_);
|
89
85
|
num[key] = 0;
|
90
86
|
}
|
91
87
|
} else {
|
@@ -93,15 +89,15 @@ static void FN(Prepare)(
|
|
93
89
|
}
|
94
90
|
}
|
95
91
|
|
96
|
-
static BROTLI_INLINE
|
92
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
97
93
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
98
|
-
size_t input_size) {
|
94
|
+
size_t input_size, size_t* alloc_size) {
|
99
95
|
size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;
|
100
96
|
size_t block_size = (size_t)1 << params->hasher.block_bits;
|
101
97
|
BROTLI_UNUSED(one_shot);
|
102
98
|
BROTLI_UNUSED(input_size);
|
103
|
-
|
104
|
-
|
99
|
+
alloc_size[0] = sizeof(uint16_t) * bucket_size;
|
100
|
+
alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size;
|
105
101
|
}
|
106
102
|
|
107
103
|
/* Look at 4 bytes at &data[ix & mask].
|
@@ -111,8 +107,7 @@ static BROTLI_INLINE void FN(Store)(
|
|
111
107
|
const size_t mask, const size_t ix) {
|
112
108
|
uint16_t* BROTLI_RESTRICT num = self->num_;
|
113
109
|
uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
|
114
|
-
const
|
115
|
-
self->hash_shift_);
|
110
|
+
const size_t key = FN(HashBytes)(&data[ix & mask], self->hash_mul_);
|
116
111
|
const size_t minor_ix = num[key] & self->block_mask_;
|
117
112
|
const size_t offset = minor_ix + (key << self->block_bits_);
|
118
113
|
++num[key];
|
@@ -217,14 +212,17 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
|
|
217
212
|
}
|
218
213
|
}
|
219
214
|
{
|
220
|
-
const
|
221
|
-
&data[cur_ix_masked], self->hash_mask_, self->hash_shift_);
|
215
|
+
const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);
|
222
216
|
uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
|
223
217
|
const size_t down =
|
224
218
|
(num[key] > self->block_size_) ?
|
225
219
|
(num[key] - self->block_size_) : 0u;
|
226
|
-
|
220
|
+
const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked);
|
221
|
+
const size_t max_length_m4 = max_length - 4;
|
222
|
+
i = num[key];
|
223
|
+
for (; i > down;) {
|
227
224
|
size_t prev_ix = bucket[--i & self->block_mask_];
|
225
|
+
uint32_t current4;
|
228
226
|
const size_t backward = cur_ix - prev_ix;
|
229
227
|
if (BROTLI_PREDICT_FALSE(backward > max_backward)) {
|
230
228
|
break;
|
@@ -235,22 +233,19 @@ static BROTLI_INLINE void FN(FindLongestMatch)(
|
|
235
233
|
data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
|
236
234
|
continue;
|
237
235
|
}
|
236
|
+
current4 = BrotliUnalignedRead32(data + prev_ix);
|
237
|
+
if (first4 != current4) continue;
|
238
238
|
{
|
239
|
-
const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
|
240
|
-
&data[cur_ix_masked],
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
best_len = len;
|
250
|
-
out->len = best_len;
|
251
|
-
out->distance = backward;
|
252
|
-
out->score = best_score;
|
253
|
-
}
|
239
|
+
const size_t len = FindMatchLengthWithLimit(&data[prev_ix + 4],
|
240
|
+
&data[cur_ix_masked + 4],
|
241
|
+
max_length_m4) + 4;
|
242
|
+
const score_t score = BackwardReferenceScore(len, backward);
|
243
|
+
if (best_score < score) {
|
244
|
+
best_score = score;
|
245
|
+
best_len = len;
|
246
|
+
out->len = best_len;
|
247
|
+
out->distance = backward;
|
248
|
+
out->score = best_score;
|
254
249
|
}
|
255
250
|
}
|
256
251
|
}
|
@@ -54,10 +54,6 @@ typedef struct HashLongestMatch {
|
|
54
54
|
uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */
|
55
55
|
} HashLongestMatch;
|
56
56
|
|
57
|
-
static BROTLI_INLINE uint16_t* FN(Num)(void* extra) {
|
58
|
-
return (uint16_t*)extra;
|
59
|
-
}
|
60
|
-
|
61
57
|
static void FN(Initialize)(
|
62
58
|
HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,
|
63
59
|
const BrotliEncoderParams* params) {
|
@@ -68,8 +64,8 @@ static void FN(Initialize)(
|
|
68
64
|
self->bucket_size_ = (size_t)1 << common->params.bucket_bits;
|
69
65
|
self->block_size_ = (size_t)1 << common->params.block_bits;
|
70
66
|
self->block_mask_ = (uint32_t)(self->block_size_ - 1);
|
71
|
-
self->num_ = (uint16_t*)common->extra;
|
72
|
-
self->buckets_ = (uint32_t*)
|
67
|
+
self->num_ = (uint16_t*)common->extra[0];
|
68
|
+
self->buckets_ = (uint32_t*)common->extra[1];
|
73
69
|
self->block_bits_ = common->params.block_bits;
|
74
70
|
self->num_last_distances_to_check_ =
|
75
71
|
common->params.num_last_distances_to_check;
|
@@ -92,15 +88,15 @@ static void FN(Prepare)(
|
|
92
88
|
}
|
93
89
|
}
|
94
90
|
|
95
|
-
static BROTLI_INLINE
|
91
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
96
92
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
97
|
-
size_t input_size) {
|
93
|
+
size_t input_size, size_t* alloc_size) {
|
98
94
|
size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;
|
99
95
|
size_t block_size = (size_t)1 << params->hasher.block_bits;
|
100
96
|
BROTLI_UNUSED(one_shot);
|
101
97
|
BROTLI_UNUSED(input_size);
|
102
|
-
|
103
|
-
|
98
|
+
alloc_size[0] = sizeof(uint16_t) * bucket_size;
|
99
|
+
alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size;
|
104
100
|
}
|
105
101
|
|
106
102
|
/* Look at 4 bytes at &data[ix & mask].
|
@@ -49,7 +49,7 @@ static void FN(Initialize)(
|
|
49
49
|
self->common = common;
|
50
50
|
|
51
51
|
BROTLI_UNUSED(params);
|
52
|
-
self->buckets_ = (uint32_t*)common->extra;
|
52
|
+
self->buckets_ = (uint32_t*)common->extra[0];
|
53
53
|
}
|
54
54
|
|
55
55
|
static void FN(Prepare)(
|
@@ -80,13 +80,13 @@ static void FN(Prepare)(
|
|
80
80
|
}
|
81
81
|
}
|
82
82
|
|
83
|
-
static BROTLI_INLINE
|
83
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
84
84
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
85
|
-
size_t input_size) {
|
85
|
+
size_t input_size, size_t* alloc_size) {
|
86
86
|
BROTLI_UNUSED(params);
|
87
87
|
BROTLI_UNUSED(one_shot);
|
88
88
|
BROTLI_UNUSED(input_size);
|
89
|
-
|
89
|
+
alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE;
|
90
90
|
}
|
91
91
|
|
92
92
|
/* Look at 5 bytes at &data[ix & mask].
|
@@ -67,7 +67,7 @@ static void FN(Initialize)(
|
|
67
67
|
self->factor_remove *= self->factor;
|
68
68
|
}
|
69
69
|
|
70
|
-
self->table = (uint32_t*)common->extra;
|
70
|
+
self->table = (uint32_t*)common->extra[0];
|
71
71
|
for (i = 0; i < NUMBUCKETS; i++) {
|
72
72
|
self->table[i] = FN(kInvalidPos);
|
73
73
|
}
|
@@ -88,13 +88,13 @@ static void FN(Prepare)(HashRolling* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
|
|
88
88
|
BROTLI_UNUSED(one_shot);
|
89
89
|
}
|
90
90
|
|
91
|
-
static BROTLI_INLINE
|
91
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
92
92
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
93
|
-
size_t input_size) {
|
94
|
-
return NUMBUCKETS * sizeof(uint32_t);
|
93
|
+
size_t input_size, size_t* alloc_size) {
|
95
94
|
BROTLI_UNUSED(params);
|
96
95
|
BROTLI_UNUSED(one_shot);
|
97
96
|
BROTLI_UNUSED(input_size);
|
97
|
+
alloc_size[0] = NUMBUCKETS * sizeof(uint32_t);
|
98
98
|
}
|
99
99
|
|
100
100
|
static BROTLI_INLINE void FN(Store)(HashRolling* BROTLI_RESTRICT self,
|
@@ -57,8 +57,8 @@ typedef struct HashToBinaryTree {
|
|
57
57
|
static void FN(Initialize)(
|
58
58
|
HasherCommon* common, HashToBinaryTree* BROTLI_RESTRICT self,
|
59
59
|
const BrotliEncoderParams* params) {
|
60
|
-
self->buckets_ = (uint32_t*)common->extra;
|
61
|
-
self->forest_ =
|
60
|
+
self->buckets_ = (uint32_t*)common->extra[0];
|
61
|
+
self->forest_ = (uint32_t*)common->extra[1];
|
62
62
|
|
63
63
|
self->window_mask_ = (1u << params->lgwin) - 1u;
|
64
64
|
self->invalid_pos_ = (uint32_t)(0 - self->window_mask_);
|
@@ -78,14 +78,15 @@ static void FN(Prepare)
|
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
-
static BROTLI_INLINE
|
81
|
+
static BROTLI_INLINE void FN(HashMemAllocInBytes)(
|
82
82
|
const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
|
83
|
-
size_t input_size) {
|
83
|
+
size_t input_size, size_t* alloc_size) {
|
84
84
|
size_t num_nodes = (size_t)1 << params->lgwin;
|
85
85
|
if (one_shot && input_size < num_nodes) {
|
86
86
|
num_nodes = input_size;
|
87
87
|
}
|
88
|
-
|
88
|
+
alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE;
|
89
|
+
alloc_size[1] = 2 * sizeof(uint32_t) * num_nodes;
|
89
90
|
}
|
90
91
|
|
91
92
|
static BROTLI_INLINE size_t FN(LeftChildIndex)(
|
@@ -6,11 +6,11 @@
|
|
6
6
|
|
7
7
|
/* Build per-context histograms of literals, commands and distance codes. */
|
8
8
|
|
9
|
-
#include "
|
9
|
+
#include "histogram.h"
|
10
10
|
|
11
11
|
#include "../common/context.h"
|
12
|
-
#include "
|
13
|
-
#include "
|
12
|
+
#include "block_splitter.h"
|
13
|
+
#include "command.h"
|
14
14
|
|
15
15
|
#if defined(__cplusplus) || defined(c_plusplus)
|
16
16
|
extern "C" {
|
@@ -63,7 +63,7 @@ void BrotliBuildHistogramsWithContext(
|
|
63
63
|
BlockSplitIteratorNext(&insert_and_copy_it);
|
64
64
|
HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_],
|
65
65
|
cmd->cmd_prefix_);
|
66
|
-
/* TODO: unwrap iterator blocks. */
|
66
|
+
/* TODO(eustas): unwrap iterator blocks. */
|
67
67
|
for (j = cmd->insert_len_; j != 0; --j) {
|
68
68
|
size_t context;
|
69
69
|
BlockSplitIteratorNext(&literal_it);
|
@@ -11,12 +11,13 @@
|
|
11
11
|
|
12
12
|
#include <string.h> /* memset */
|
13
13
|
|
14
|
+
#include <brotli/types.h>
|
15
|
+
|
14
16
|
#include "../common/constants.h"
|
15
17
|
#include "../common/context.h"
|
16
18
|
#include "../common/platform.h"
|
17
|
-
#include
|
18
|
-
#include "
|
19
|
-
#include "./command.h"
|
19
|
+
#include "block_splitter.h"
|
20
|
+
#include "command.h"
|
20
21
|
|
21
22
|
#if defined(__cplusplus) || defined(c_plusplus)
|
22
23
|
extern "C" {
|
@@ -28,7 +29,7 @@ extern "C" {
|
|
28
29
|
#define FN(X) X ## Literal
|
29
30
|
#define DATA_SIZE BROTLI_NUM_LITERAL_SYMBOLS
|
30
31
|
#define DataType uint8_t
|
31
|
-
#include "
|
32
|
+
#include "histogram_inc.h" /* NOLINT(build/include) */
|
32
33
|
#undef DataType
|
33
34
|
#undef DATA_SIZE
|
34
35
|
#undef FN
|
@@ -36,13 +37,13 @@ extern "C" {
|
|
36
37
|
#define FN(X) X ## Command
|
37
38
|
#define DataType uint16_t
|
38
39
|
#define DATA_SIZE BROTLI_NUM_COMMAND_SYMBOLS
|
39
|
-
#include "
|
40
|
+
#include "histogram_inc.h" /* NOLINT(build/include) */
|
40
41
|
#undef DATA_SIZE
|
41
42
|
#undef FN
|
42
43
|
|
43
44
|
#define FN(X) X ## Distance
|
44
45
|
#define DATA_SIZE BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS
|
45
|
-
#include "
|
46
|
+
#include "histogram_inc.h" /* NOLINT(build/include) */
|
46
47
|
#undef DataType
|
47
48
|
#undef DATA_SIZE
|
48
49
|
#undef FN
|
@@ -7,12 +7,15 @@
|
|
7
7
|
/* Literal cost model to allow backward reference replacement to be efficient.
|
8
8
|
*/
|
9
9
|
|
10
|
-
#include "
|
10
|
+
#include "literal_cost.h"
|
11
|
+
|
12
|
+
#include <string.h> /* memset */
|
11
13
|
|
12
|
-
#include "../common/platform.h"
|
13
14
|
#include <brotli/types.h>
|
14
|
-
|
15
|
-
#include "
|
15
|
+
|
16
|
+
#include "../common/platform.h"
|
17
|
+
#include "fast_log.h"
|
18
|
+
#include "utf8_util.h"
|
16
19
|
|
17
20
|
#if defined(__cplusplus) || defined(c_plusplus)
|
18
21
|
extern "C" {
|
@@ -54,22 +57,23 @@ static size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask,
|
|
54
57
|
}
|
55
58
|
|
56
59
|
static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,
|
57
|
-
const uint8_t* data,
|
60
|
+
const uint8_t* data,
|
61
|
+
size_t* histogram, float* cost) {
|
58
62
|
/* max_utf8 is 0 (normal ASCII single byte modeling),
|
59
63
|
1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */
|
60
64
|
const size_t max_utf8 = DecideMultiByteStatsLevel(pos, len, mask, data);
|
61
|
-
size_t histogram[3][256] = { { 0 } };
|
62
65
|
size_t window_half = 495;
|
63
66
|
size_t in_window = BROTLI_MIN(size_t, window_half, len);
|
64
67
|
size_t in_window_utf8[3] = { 0 };
|
65
|
-
|
66
68
|
size_t i;
|
69
|
+
memset(histogram, 0, 3 * 256 * sizeof(histogram[0]));
|
70
|
+
|
67
71
|
{ /* Bootstrap histograms. */
|
68
72
|
size_t last_c = 0;
|
69
73
|
size_t utf8_pos = 0;
|
70
74
|
for (i = 0; i < in_window; ++i) {
|
71
75
|
size_t c = data[(pos + i) & mask];
|
72
|
-
++histogram[utf8_pos
|
76
|
+
++histogram[256 * utf8_pos + c];
|
73
77
|
++in_window_utf8[utf8_pos];
|
74
78
|
utf8_pos = UTF8Position(last_c, c, max_utf8);
|
75
79
|
last_c = c;
|
@@ -85,7 +89,7 @@ static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,
|
|
85
89
|
size_t last_c =
|
86
90
|
i < window_half + 2 ? 0 : data[(pos + i - window_half - 2) & mask];
|
87
91
|
size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8);
|
88
|
-
--histogram[utf8_pos2
|
92
|
+
--histogram[256 * utf8_pos2 + data[(pos + i - window_half) & mask]];
|
89
93
|
--in_window_utf8[utf8_pos2];
|
90
94
|
}
|
91
95
|
if (i + window_half < len) {
|
@@ -93,7 +97,7 @@ static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,
|
|
93
97
|
size_t c = data[(pos + i + window_half - 1) & mask];
|
94
98
|
size_t last_c = data[(pos + i + window_half - 2) & mask];
|
95
99
|
size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8);
|
96
|
-
++histogram[utf8_pos2
|
100
|
+
++histogram[256 * utf8_pos2 + data[(pos + i + window_half) & mask]];
|
97
101
|
++in_window_utf8[utf8_pos2];
|
98
102
|
}
|
99
103
|
{
|
@@ -101,7 +105,7 @@ static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,
|
|
101
105
|
size_t last_c = i < 2 ? 0 : data[(pos + i - 2) & mask];
|
102
106
|
size_t utf8_pos = UTF8Position(last_c, c, max_utf8);
|
103
107
|
size_t masked_pos = (pos + i) & mask;
|
104
|
-
size_t histo = histogram[utf8_pos
|
108
|
+
size_t histo = histogram[256 * utf8_pos + data[masked_pos]];
|
105
109
|
double lit_cost;
|
106
110
|
if (histo == 0) {
|
107
111
|
histo = 1;
|
@@ -125,17 +129,18 @@ static void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,
|
|
125
129
|
}
|
126
130
|
|
127
131
|
void BrotliEstimateBitCostsForLiterals(size_t pos, size_t len, size_t mask,
|
128
|
-
const uint8_t* data,
|
132
|
+
const uint8_t* data,
|
133
|
+
size_t* histogram, float* cost) {
|
129
134
|
if (BrotliIsMostlyUTF8(data, pos, mask, len, kMinUTF8Ratio)) {
|
130
|
-
EstimateBitCostsForLiteralsUTF8(pos, len, mask, data, cost);
|
135
|
+
EstimateBitCostsForLiteralsUTF8(pos, len, mask, data, histogram, cost);
|
131
136
|
return;
|
132
137
|
} else {
|
133
|
-
size_t histogram[256] = { 0 };
|
134
138
|
size_t window_half = 2000;
|
135
139
|
size_t in_window = BROTLI_MIN(size_t, window_half, len);
|
140
|
+
size_t i;
|
141
|
+
memset(histogram, 0, 256 * sizeof(histogram[0]));
|
136
142
|
|
137
143
|
/* Bootstrap histogram. */
|
138
|
-
size_t i;
|
139
144
|
for (i = 0; i < in_window; ++i) {
|
140
145
|
++histogram[data[(pos + i) & mask]];
|
141
146
|
}
|
@@ -10,9 +10,10 @@
|
|
10
10
|
#ifndef BROTLI_ENC_LITERAL_COST_H_
|
11
11
|
#define BROTLI_ENC_LITERAL_COST_H_
|
12
12
|
|
13
|
-
#include "../common/platform.h"
|
14
13
|
#include <brotli/types.h>
|
15
14
|
|
15
|
+
#include "../common/platform.h"
|
16
|
+
|
16
17
|
#if defined(__cplusplus) || defined(c_plusplus)
|
17
18
|
extern "C" {
|
18
19
|
#endif
|
@@ -21,7 +22,8 @@ extern "C" {
|
|
21
22
|
ring-buffer (data, mask) will take entropy coded and writes these estimates
|
22
23
|
to the cost[0..len) array. */
|
23
24
|
BROTLI_INTERNAL void BrotliEstimateBitCostsForLiterals(
|
24
|
-
size_t pos, size_t len, size_t mask, const uint8_t* data,
|
25
|
+
size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram,
|
26
|
+
float* cost);
|
25
27
|
|
26
28
|
#if defined(__cplusplus) || defined(c_plusplus)
|
27
29
|
} /* extern "C" */
|
@@ -7,21 +7,22 @@
|
|
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 "memory.h"
|
11
11
|
|
12
12
|
#include <stdlib.h> /* exit, free, malloc */
|
13
13
|
#include <string.h> /* memcpy */
|
14
14
|
|
15
|
-
#include "../common/platform.h"
|
16
15
|
#include <brotli/types.h>
|
17
16
|
|
17
|
+
#include "../common/platform.h"
|
18
|
+
|
18
19
|
#if defined(__cplusplus) || defined(c_plusplus)
|
19
20
|
extern "C" {
|
20
21
|
#endif
|
21
22
|
|
22
|
-
#define
|
23
|
-
#define
|
24
|
-
#define
|
23
|
+
#define MAX_NEW_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2)
|
24
|
+
#define MAX_NEW_FREED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2)
|
25
|
+
#define MAX_PERM_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 1)
|
25
26
|
|
26
27
|
#define PERM_ALLOCATED_OFFSET 0
|
27
28
|
#define NEW_ALLOCATED_OFFSET MAX_PERM_ALLOCATED
|
@@ -67,6 +68,7 @@ void BrotliWipeOutMemoryManager(MemoryManager* m) {
|
|
67
68
|
|
68
69
|
static void SortPointers(void** items, const size_t n) {
|
69
70
|
/* Shell sort. */
|
71
|
+
/* TODO(eustas): fine-tune for "many slots" case */
|
70
72
|
static const size_t gaps[] = {23, 10, 4, 1};
|
71
73
|
int g = 0;
|
72
74
|
for (; g < 4; ++g) {
|
@@ -165,6 +167,28 @@ void BrotliWipeOutMemoryManager(MemoryManager* m) {
|
|
165
167
|
|
166
168
|
#endif /* BROTLI_ENCODER_EXIT_ON_OOM */
|
167
169
|
|
170
|
+
void* BrotliBootstrapAlloc(size_t size,
|
171
|
+
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
|
172
|
+
if (!alloc_func && !free_func) {
|
173
|
+
return malloc(size);
|
174
|
+
} else if (alloc_func && free_func) {
|
175
|
+
return alloc_func(opaque, size);
|
176
|
+
}
|
177
|
+
return NULL;
|
178
|
+
}
|
179
|
+
|
180
|
+
void BrotliBootstrapFree(void* address, MemoryManager* m) {
|
181
|
+
if (!address) {
|
182
|
+
/* Should not happen! */
|
183
|
+
return;
|
184
|
+
} else {
|
185
|
+
/* Copy values, as those would be freed. */
|
186
|
+
brotli_free_func free_func = m->free_func;
|
187
|
+
void* opaque = m->opaque;
|
188
|
+
free_func(opaque, address);
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
168
192
|
#if defined(__cplusplus) || defined(c_plusplus)
|
169
193
|
} /* extern "C" */
|
170
194
|
#endif
|
@@ -11,9 +11,10 @@
|
|
11
11
|
|
12
12
|
#include <string.h> /* memcpy */
|
13
13
|
|
14
|
-
#include "../common/platform.h"
|
15
14
|
#include <brotli/types.h>
|
16
15
|
|
16
|
+
#include "../common/platform.h"
|
17
|
+
|
17
18
|
#if defined(__cplusplus) || defined(c_plusplus)
|
18
19
|
extern "C" {
|
19
20
|
#endif
|
@@ -23,6 +24,16 @@ extern "C" {
|
|
23
24
|
#define BROTLI_ENCODER_EXIT_ON_OOM
|
24
25
|
#endif
|
25
26
|
|
27
|
+
#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)
|
28
|
+
#if defined(BROTLI_EXPERIMENTAL)
|
29
|
+
#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS (48*1024)
|
30
|
+
#else /* BROTLI_EXPERIMENTAL */
|
31
|
+
#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 256
|
32
|
+
#endif /* BROTLI_EXPERIMENTAL */
|
33
|
+
#else /* BROTLI_ENCODER_EXIT_ON_OOM */
|
34
|
+
#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 0
|
35
|
+
#endif /* BROTLI_ENCODER_EXIT_ON_OOM */
|
36
|
+
|
26
37
|
typedef struct MemoryManager {
|
27
38
|
brotli_alloc_func alloc_func;
|
28
39
|
brotli_free_func free_func;
|
@@ -32,7 +43,7 @@ typedef struct MemoryManager {
|
|
32
43
|
size_t perm_allocated;
|
33
44
|
size_t new_allocated;
|
34
45
|
size_t new_freed;
|
35
|
-
void* pointers[
|
46
|
+
void* pointers[BROTLI_ENCODER_MEMORY_MANAGER_SLOTS];
|
36
47
|
#endif /* BROTLI_ENCODER_EXIT_ON_OOM */
|
37
48
|
} MemoryManager;
|
38
49
|
|
@@ -107,6 +118,12 @@ V: value to append
|
|
107
118
|
A[(S) - 1] = (V); \
|
108
119
|
}
|
109
120
|
|
121
|
+
/* "Bootstrap" allocations are not tracked by memory manager; should be used
|
122
|
+
only to allocate MemoryManager itself (or structure containing it). */
|
123
|
+
BROTLI_INTERNAL void* BrotliBootstrapAlloc(size_t size,
|
124
|
+
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
|
125
|
+
BROTLI_INTERNAL void BrotliBootstrapFree(void* address, MemoryManager* m);
|
126
|
+
|
110
127
|
#if defined(__cplusplus) || defined(c_plusplus)
|
111
128
|
} /* extern "C" */
|
112
129
|
#endif
|