brotli 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +1 -0
- data/Rakefile +6 -1
- data/brotli.gemspec +1 -1
- data/docs/Brotli.html +485 -0
- data/docs/Brotli/Error.html +124 -0
- data/docs/_index.html +122 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +127 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +127 -0
- data/docs/js/app.js +292 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +67 -0
- data/docs/top-level-namespace.html +110 -0
- data/ext/brotli/brotli.c +20 -0
- data/lib/brotli/version.rb +1 -1
- data/vendor/brotli/c/common/constants.h +13 -6
- data/vendor/brotli/c/{dec → common}/context.h +182 -172
- 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 +1 -1
- data/vendor/brotli/c/common/dictionary.h +4 -4
- data/vendor/brotli/c/common/platform.h +509 -0
- data/vendor/brotli/c/common/transform.c +235 -0
- data/vendor/brotli/c/common/transform.h +80 -0
- data/vendor/brotli/c/common/version.h +8 -1
- data/vendor/brotli/c/dec/bit_reader.c +1 -1
- data/vendor/brotli/c/dec/bit_reader.h +35 -86
- data/vendor/brotli/c/dec/decode.c +322 -205
- data/vendor/brotli/c/dec/huffman.c +35 -37
- data/vendor/brotli/c/dec/huffman.h +13 -9
- data/vendor/brotli/c/dec/prefix.h +3 -4
- data/vendor/brotli/c/dec/state.c +26 -34
- data/vendor/brotli/c/dec/state.h +34 -23
- data/vendor/brotli/c/enc/backward_references.c +25 -15
- data/vendor/brotli/c/enc/backward_references.h +5 -6
- data/vendor/brotli/c/enc/backward_references_hq.c +94 -68
- data/vendor/brotli/c/enc/backward_references_hq.h +22 -25
- data/vendor/brotli/c/enc/backward_references_inc.h +10 -10
- 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 +2 -3
- data/vendor/brotli/c/enc/block_splitter.h +1 -1
- data/vendor/brotli/c/enc/block_splitter_inc.h +11 -11
- data/vendor/brotli/c/enc/brotli_bit_stream.c +102 -101
- 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/command.h +40 -30
- 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 +101 -68
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +1 -1
- data/vendor/brotli/c/enc/dictionary_hash.c +1 -1
- data/vendor/brotli/c/enc/encode.c +262 -162
- data/vendor/brotli/c/enc/encoder_dict.c +32 -0
- data/vendor/brotli/c/enc/encoder_dict.h +41 -0
- data/vendor/brotli/c/enc/entropy_encode.c +14 -14
- data/vendor/brotli/c/enc/entropy_encode.h +5 -5
- data/vendor/brotli/c/enc/entropy_encode_static.h +3 -3
- data/vendor/brotli/c/enc/fast_log.h +4 -2
- data/vendor/brotli/c/enc/find_match_length.h +3 -3
- data/vendor/brotli/c/enc/hash.h +75 -24
- data/vendor/brotli/c/enc/hash_composite_inc.h +133 -0
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +9 -8
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +8 -8
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +8 -8
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +10 -9
- data/vendor/brotli/c/enc/hash_rolling_inc.h +215 -0
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +9 -8
- 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 +40 -1
- data/vendor/brotli/c/enc/metablock.c +163 -25
- data/vendor/brotli/c/enc/metablock.h +13 -8
- data/vendor/brotli/c/enc/metablock_inc.h +1 -1
- data/vendor/brotli/c/enc/params.h +44 -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 +15 -11
- 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 +20 -20
- data/vendor/brotli/c/enc/utf8_util.h +1 -1
- data/vendor/brotli/c/enc/write_bits.h +16 -21
- data/vendor/brotli/c/include/brotli/decode.h +13 -8
- data/vendor/brotli/c/include/brotli/encode.h +33 -8
- data/vendor/brotli/c/include/brotli/port.h +211 -83
- data/vendor/brotli/c/include/brotli/types.h +0 -7
- metadata +33 -12
- 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
@@ -16,13 +16,13 @@
|
|
16
16
|
#ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
17
17
|
#define BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
18
18
|
|
19
|
+
#include "../common/context.h"
|
20
|
+
#include "../common/platform.h"
|
19
21
|
#include <brotli/types.h>
|
20
22
|
#include "./command.h"
|
21
|
-
#include "./context.h"
|
22
23
|
#include "./entropy_encode.h"
|
23
24
|
#include "./memory.h"
|
24
25
|
#include "./metablock.h"
|
25
|
-
#include "./port.h"
|
26
26
|
|
27
27
|
#if defined(__cplusplus) || defined(c_plusplus)
|
28
28
|
extern "C" {
|
@@ -32,7 +32,7 @@ extern "C" {
|
|
32
32
|
position for the current storage. */
|
33
33
|
|
34
34
|
BROTLI_INTERNAL void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,
|
35
|
-
HuffmanTree* tree, size_t
|
35
|
+
HuffmanTree* tree, size_t* storage_ix, uint8_t* storage);
|
36
36
|
|
37
37
|
BROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast(
|
38
38
|
MemoryManager* m, const uint32_t* histogram, const size_t histogram_total,
|
@@ -42,59 +42,40 @@ BROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast(
|
|
42
42
|
/* REQUIRES: length > 0 */
|
43
43
|
/* REQUIRES: length <= (1 << 24) */
|
44
44
|
BROTLI_INTERNAL void BrotliStoreMetaBlock(MemoryManager* m,
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
uint8_t prev_byte2,
|
51
|
-
BROTLI_BOOL is_final_block,
|
52
|
-
uint32_t num_direct_distance_codes,
|
53
|
-
uint32_t distance_postfix_bits,
|
54
|
-
ContextType literal_context_mode,
|
55
|
-
const Command* commands,
|
56
|
-
size_t n_commands,
|
57
|
-
const MetaBlockSplit* mb,
|
58
|
-
size_t* storage_ix,
|
59
|
-
uint8_t* storage);
|
45
|
+
const uint8_t* input, size_t start_pos, size_t length, size_t mask,
|
46
|
+
uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,
|
47
|
+
const BrotliEncoderParams* params, ContextType literal_context_mode,
|
48
|
+
const Command* commands, size_t n_commands, const MetaBlockSplit* mb,
|
49
|
+
size_t* storage_ix, uint8_t* storage);
|
60
50
|
|
61
51
|
/* Stores the meta-block without doing any block splitting, just collects
|
62
52
|
one histogram per block category and uses that for entropy coding.
|
63
53
|
REQUIRES: length > 0
|
64
54
|
REQUIRES: length <= (1 << 24) */
|
65
55
|
BROTLI_INTERNAL void BrotliStoreMetaBlockTrivial(MemoryManager* m,
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
BROTLI_BOOL is_last,
|
71
|
-
const Command *commands,
|
72
|
-
size_t n_commands,
|
73
|
-
size_t* storage_ix,
|
74
|
-
uint8_t* storage);
|
56
|
+
const uint8_t* input, size_t start_pos, size_t length, size_t mask,
|
57
|
+
BROTLI_BOOL is_last, const BrotliEncoderParams* params,
|
58
|
+
const Command* commands, size_t n_commands,
|
59
|
+
size_t* storage_ix, uint8_t* storage);
|
75
60
|
|
76
61
|
/* Same as above, but uses static prefix codes for histograms with a only a few
|
77
62
|
symbols, and uses static code length prefix codes for all other histograms.
|
78
63
|
REQUIRES: length > 0
|
79
64
|
REQUIRES: length <= (1 << 24) */
|
80
65
|
BROTLI_INTERNAL void BrotliStoreMetaBlockFast(MemoryManager* m,
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
BROTLI_BOOL is_last,
|
86
|
-
const Command *commands,
|
87
|
-
size_t n_commands,
|
88
|
-
size_t* storage_ix,
|
89
|
-
uint8_t* storage);
|
66
|
+
const uint8_t* input, size_t start_pos, size_t length, size_t mask,
|
67
|
+
BROTLI_BOOL is_last, const BrotliEncoderParams* params,
|
68
|
+
const Command* commands, size_t n_commands,
|
69
|
+
size_t* storage_ix, uint8_t* storage);
|
90
70
|
|
91
71
|
/* This is for storing uncompressed blocks (simple raw storage of
|
92
72
|
bytes-as-bytes).
|
93
73
|
REQUIRES: length > 0
|
94
74
|
REQUIRES: length <= (1 << 24) */
|
95
75
|
BROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock(
|
96
|
-
BROTLI_BOOL is_final_block, const uint8_t* input,
|
97
|
-
size_t
|
76
|
+
BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input,
|
77
|
+
size_t position, size_t mask, size_t len,
|
78
|
+
size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage);
|
98
79
|
|
99
80
|
#if defined(__cplusplus) || defined(c_plusplus)
|
100
81
|
} /* extern "C" */
|
@@ -8,12 +8,12 @@
|
|
8
8
|
|
9
9
|
#include "./cluster.h"
|
10
10
|
|
11
|
+
#include "../common/platform.h"
|
11
12
|
#include <brotli/types.h>
|
12
13
|
#include "./bit_cost.h" /* BrotliPopulationCost */
|
13
14
|
#include "./fast_log.h"
|
14
15
|
#include "./histogram.h"
|
15
16
|
#include "./memory.h"
|
16
|
-
#include "./port.h"
|
17
17
|
|
18
18
|
#if defined(__cplusplus) || defined(c_plusplus)
|
19
19
|
extern "C" {
|
@@ -9,10 +9,10 @@
|
|
9
9
|
#ifndef BROTLI_ENC_CLUSTER_H_
|
10
10
|
#define BROTLI_ENC_CLUSTER_H_
|
11
11
|
|
12
|
+
#include "../common/platform.h"
|
12
13
|
#include <brotli/types.h>
|
13
14
|
#include "./histogram.h"
|
14
15
|
#include "./memory.h"
|
15
|
-
#include "./port.h"
|
16
16
|
|
17
17
|
#if defined(__cplusplus) || defined(c_plusplus)
|
18
18
|
extern "C" {
|
@@ -10,9 +10,10 @@
|
|
10
10
|
#define BROTLI_ENC_COMMAND_H_
|
11
11
|
|
12
12
|
#include "../common/constants.h"
|
13
|
-
#include
|
13
|
+
#include "../common/platform.h"
|
14
14
|
#include <brotli/types.h>
|
15
15
|
#include "./fast_log.h"
|
16
|
+
#include "./params.h"
|
16
17
|
#include "./prefix.h"
|
17
18
|
|
18
19
|
#if defined(__cplusplus) || defined(c_plusplus)
|
@@ -61,21 +62,21 @@ static BROTLI_INLINE uint16_t GetCopyLengthCode(size_t copylen) {
|
|
61
62
|
static BROTLI_INLINE uint16_t CombineLengthCodes(
|
62
63
|
uint16_t inscode, uint16_t copycode, BROTLI_BOOL use_last_distance) {
|
63
64
|
uint16_t bits64 =
|
64
|
-
(uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) <<
|
65
|
-
if (use_last_distance && inscode <
|
66
|
-
return (copycode <
|
65
|
+
(uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3u));
|
66
|
+
if (use_last_distance && inscode < 8u && copycode < 16u) {
|
67
|
+
return (copycode < 8u) ? bits64 : (bits64 | 64u);
|
67
68
|
} else {
|
68
69
|
/* Specification: 5 Encoding of ... (last table) */
|
69
70
|
/* offset = 2 * index, where index is in range [0..8] */
|
70
|
-
|
71
|
+
uint32_t offset = 2u * ((copycode >> 3u) + 3u * (inscode >> 3u));
|
71
72
|
/* All values in specification are K * 64,
|
72
73
|
where K = [2, 3, 6, 4, 5, 8, 7, 9, 10],
|
73
74
|
i + 1 = [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
74
75
|
K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1, 2] = D.
|
75
76
|
All values in D require only 2 bits to encode.
|
76
77
|
Magic constant is shifted 6 bits left, to avoid final multiplication. */
|
77
|
-
offset = (offset <<
|
78
|
-
return (uint16_t)offset | bits64;
|
78
|
+
offset = (offset << 5u) + 0x40u + ((0x520D40u >> offset) & 0xC0u);
|
79
|
+
return (uint16_t)(offset | bits64);
|
79
80
|
}
|
80
81
|
}
|
81
82
|
|
@@ -105,53 +106,61 @@ static BROTLI_INLINE uint32_t GetCopyExtra(uint16_t copycode) {
|
|
105
106
|
|
106
107
|
typedef struct Command {
|
107
108
|
uint32_t insert_len_;
|
108
|
-
/* Stores copy_len in low
|
109
|
+
/* Stores copy_len in low 25 bits and copy_code - copy_len in high 7 bit. */
|
109
110
|
uint32_t copy_len_;
|
111
|
+
/* Stores distance extra bits. */
|
110
112
|
uint32_t dist_extra_;
|
111
113
|
uint16_t cmd_prefix_;
|
114
|
+
/* Stores distance code in low 10 bits
|
115
|
+
and number of extra bits in high 6 bits. */
|
112
116
|
uint16_t dist_prefix_;
|
113
117
|
} Command;
|
114
118
|
|
115
119
|
/* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */
|
116
|
-
static BROTLI_INLINE void InitCommand(Command* self,
|
120
|
+
static BROTLI_INLINE void InitCommand(Command* self,
|
121
|
+
const BrotliDistanceParams* dist, size_t insertlen,
|
117
122
|
size_t copylen, int copylen_code_delta, size_t distance_code) {
|
118
123
|
/* Don't rely on signed int representation, use honest casts. */
|
119
124
|
uint32_t delta = (uint8_t)((int8_t)copylen_code_delta);
|
120
125
|
self->insert_len_ = (uint32_t)insertlen;
|
121
|
-
self->copy_len_ = (uint32_t)(copylen | (delta <<
|
126
|
+
self->copy_len_ = (uint32_t)(copylen | (delta << 25));
|
122
127
|
/* The distance prefix and extra bits are stored in this Command as if
|
123
128
|
npostfix and ndirect were 0, they are only recomputed later after the
|
124
129
|
clustering if needed. */
|
125
130
|
PrefixEncodeCopyDistance(
|
126
|
-
distance_code,
|
131
|
+
distance_code, dist->num_direct_distance_codes,
|
132
|
+
dist->distance_postfix_bits, &self->dist_prefix_, &self->dist_extra_);
|
127
133
|
GetLengthCode(
|
128
134
|
insertlen, (size_t)((int)copylen + copylen_code_delta),
|
129
|
-
TO_BROTLI_BOOL(self->dist_prefix_ == 0), &self->cmd_prefix_);
|
135
|
+
TO_BROTLI_BOOL((self->dist_prefix_ & 0x3FF) == 0), &self->cmd_prefix_);
|
130
136
|
}
|
131
137
|
|
132
138
|
static BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) {
|
133
139
|
self->insert_len_ = (uint32_t)insertlen;
|
134
|
-
self->copy_len_ = 4 <<
|
140
|
+
self->copy_len_ = 4 << 25;
|
135
141
|
self->dist_extra_ = 0;
|
136
142
|
self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES;
|
137
143
|
GetLengthCode(insertlen, 4, BROTLI_FALSE, &self->cmd_prefix_);
|
138
144
|
}
|
139
145
|
|
140
|
-
static BROTLI_INLINE uint32_t CommandRestoreDistanceCode(
|
141
|
-
|
142
|
-
|
146
|
+
static BROTLI_INLINE uint32_t CommandRestoreDistanceCode(
|
147
|
+
const Command* self, const BrotliDistanceParams* dist) {
|
148
|
+
if ((self->dist_prefix_ & 0x3FFu) <
|
149
|
+
BROTLI_NUM_DISTANCE_SHORT_CODES + dist->num_direct_distance_codes) {
|
150
|
+
return self->dist_prefix_ & 0x3FFu;
|
143
151
|
} else {
|
144
|
-
uint32_t
|
145
|
-
uint32_t
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
return (
|
152
|
+
uint32_t dcode = self->dist_prefix_ & 0x3FFu;
|
153
|
+
uint32_t nbits = self->dist_prefix_ >> 10;
|
154
|
+
uint32_t extra = self->dist_extra_;
|
155
|
+
uint32_t postfix_mask = (1U << dist->distance_postfix_bits) - 1U;
|
156
|
+
uint32_t hcode = (dcode - dist->num_direct_distance_codes -
|
157
|
+
BROTLI_NUM_DISTANCE_SHORT_CODES) >>
|
158
|
+
dist->distance_postfix_bits;
|
159
|
+
uint32_t lcode = (dcode - dist->num_direct_distance_codes -
|
160
|
+
BROTLI_NUM_DISTANCE_SHORT_CODES) & postfix_mask;
|
161
|
+
uint32_t offset = ((2U + (hcode & 1U)) << nbits) - 4U;
|
162
|
+
return ((offset + extra) << dist->distance_postfix_bits) + lcode +
|
163
|
+
dist->num_direct_distance_codes + BROTLI_NUM_DISTANCE_SHORT_CODES;
|
155
164
|
}
|
156
165
|
}
|
157
166
|
|
@@ -165,12 +174,13 @@ static BROTLI_INLINE uint32_t CommandDistanceContext(const Command* self) {
|
|
165
174
|
}
|
166
175
|
|
167
176
|
static BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) {
|
168
|
-
return self->copy_len_ &
|
177
|
+
return self->copy_len_ & 0x1FFFFFF;
|
169
178
|
}
|
170
179
|
|
171
180
|
static BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) {
|
172
|
-
|
173
|
-
|
181
|
+
uint32_t modifier = self->copy_len_ >> 25;
|
182
|
+
int32_t delta = (int8_t)((uint8_t)(modifier | ((modifier & 0x40) << 1)));
|
183
|
+
return (uint32_t)((int32_t)(self->copy_len_ & 0x1FFFFFF) + delta);
|
174
184
|
}
|
175
185
|
|
176
186
|
#if defined(__cplusplus) || defined(c_plusplus)
|
@@ -17,16 +17,15 @@
|
|
17
17
|
#include <string.h> /* memcmp, memcpy, memset */
|
18
18
|
|
19
19
|
#include "../common/constants.h"
|
20
|
+
#include "../common/platform.h"
|
20
21
|
#include <brotli/types.h>
|
21
22
|
#include "./brotli_bit_stream.h"
|
22
23
|
#include "./entropy_encode.h"
|
23
24
|
#include "./fast_log.h"
|
24
25
|
#include "./find_match_length.h"
|
25
26
|
#include "./memory.h"
|
26
|
-
#include "./port.h"
|
27
27
|
#include "./write_bits.h"
|
28
28
|
|
29
|
-
|
30
29
|
#if defined(__cplusplus) || defined(c_plusplus)
|
31
30
|
extern "C" {
|
32
31
|
#endif
|
@@ -39,7 +38,7 @@ extern "C" {
|
|
39
38
|
* There is no effort to ensure that it is a prime, the oddity is enough
|
40
39
|
for this use.
|
41
40
|
* The number has been tuned heuristically against compression benchmarks. */
|
42
|
-
static const uint32_t kHashMul32 =
|
41
|
+
static const uint32_t kHashMul32 = 0x1E35A7BD;
|
43
42
|
|
44
43
|
static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) {
|
45
44
|
const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 24) * kHashMul32;
|
@@ -48,8 +47,8 @@ static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) {
|
|
48
47
|
|
49
48
|
static BROTLI_INLINE uint32_t HashBytesAtOffset(
|
50
49
|
uint64_t v, int offset, size_t shift) {
|
51
|
-
|
52
|
-
|
50
|
+
BROTLI_DCHECK(offset >= 0);
|
51
|
+
BROTLI_DCHECK(offset <= 3);
|
53
52
|
{
|
54
53
|
const uint64_t h = ((v >> (8 * offset)) << 24) * kHashMul32;
|
55
54
|
return (uint32_t)(h >> shift);
|
@@ -58,7 +57,7 @@ static BROTLI_INLINE uint32_t HashBytesAtOffset(
|
|
58
57
|
|
59
58
|
static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2) {
|
60
59
|
return TO_BROTLI_BOOL(
|
61
|
-
|
60
|
+
BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2) &&
|
62
61
|
p1[4] == p2[4]);
|
63
62
|
}
|
64
63
|
|
@@ -203,7 +202,7 @@ static BROTLI_INLINE void EmitInsertLen(size_t insertlen,
|
|
203
202
|
} else {
|
204
203
|
BrotliWriteBits(depth[61], bits[61], storage_ix, storage);
|
205
204
|
BrotliWriteBits(12, insertlen - 2114, storage_ix, storage);
|
206
|
-
++histo[
|
205
|
+
++histo[61];
|
207
206
|
}
|
208
207
|
}
|
209
208
|
|
@@ -216,11 +215,11 @@ static BROTLI_INLINE void EmitLongInsertLen(size_t insertlen,
|
|
216
215
|
if (insertlen < 22594) {
|
217
216
|
BrotliWriteBits(depth[62], bits[62], storage_ix, storage);
|
218
217
|
BrotliWriteBits(14, insertlen - 6210, storage_ix, storage);
|
219
|
-
++histo[
|
218
|
+
++histo[62];
|
220
219
|
} else {
|
221
220
|
BrotliWriteBits(depth[63], bits[63], storage_ix, storage);
|
222
221
|
BrotliWriteBits(24, insertlen - 22594, storage_ix, storage);
|
223
|
-
++histo[
|
222
|
+
++histo[63];
|
224
223
|
}
|
225
224
|
}
|
226
225
|
|
@@ -252,7 +251,7 @@ static BROTLI_INLINE void EmitCopyLen(size_t copylen,
|
|
252
251
|
} else {
|
253
252
|
BrotliWriteBits(depth[39], bits[39], storage_ix, storage);
|
254
253
|
BrotliWriteBits(24, copylen - 2118, storage_ix, storage);
|
255
|
-
++histo[
|
254
|
+
++histo[39];
|
256
255
|
}
|
257
256
|
}
|
258
257
|
|
@@ -294,7 +293,7 @@ static BROTLI_INLINE void EmitCopyLenLastDistance(size_t copylen,
|
|
294
293
|
BrotliWriteBits(depth[39], bits[39], storage_ix, storage);
|
295
294
|
BrotliWriteBits(24, copylen - 2120, storage_ix, storage);
|
296
295
|
BrotliWriteBits(depth[64], bits[64], storage_ix, storage);
|
297
|
-
++histo[
|
296
|
+
++histo[39];
|
298
297
|
++histo[64];
|
299
298
|
}
|
300
299
|
}
|
@@ -344,7 +343,7 @@ static void BrotliStoreMetaBlockHeader(
|
|
344
343
|
}
|
345
344
|
|
346
345
|
static void UpdateBits(size_t n_bits, uint32_t bits, size_t pos,
|
347
|
-
uint8_t
|
346
|
+
uint8_t* array) {
|
348
347
|
while (n_bits > 0) {
|
349
348
|
size_t byte_pos = pos >> 3;
|
350
349
|
size_t n_unchanged_bits = pos & 7;
|
@@ -522,12 +521,12 @@ static BROTLI_INLINE void BrotliCompressFragmentFastImpl(
|
|
522
521
|
|
523
522
|
const uint8_t* next_ip = ip;
|
524
523
|
const uint8_t* candidate;
|
525
|
-
|
524
|
+
BROTLI_DCHECK(next_emit < ip);
|
526
525
|
trawl:
|
527
526
|
do {
|
528
527
|
uint32_t hash = next_hash;
|
529
528
|
uint32_t bytes_between_hash_lookups = skip++ >> 5;
|
530
|
-
|
529
|
+
BROTLI_DCHECK(hash == Hash(next_ip, shift));
|
531
530
|
ip = next_ip;
|
532
531
|
next_ip = ip + bytes_between_hash_lookups;
|
533
532
|
if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {
|
@@ -542,8 +541,8 @@ trawl:
|
|
542
541
|
}
|
543
542
|
}
|
544
543
|
candidate = base_ip + table[hash];
|
545
|
-
|
546
|
-
|
544
|
+
BROTLI_DCHECK(candidate >= base_ip);
|
545
|
+
BROTLI_DCHECK(candidate < ip);
|
547
546
|
|
548
547
|
table[hash] = (int)(ip - base_ip);
|
549
548
|
} while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate)));
|
@@ -566,7 +565,7 @@ trawl:
|
|
566
565
|
int distance = (int)(base - candidate); /* > 0 */
|
567
566
|
size_t insert = (size_t)(base - next_emit);
|
568
567
|
ip += matched;
|
569
|
-
|
568
|
+
BROTLI_DCHECK(0 == memcmp(base, candidate, matched));
|
570
569
|
if (BROTLI_PREDICT_TRUE(insert < 6210)) {
|
571
570
|
EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,
|
572
571
|
storage_ix, storage);
|
@@ -626,7 +625,7 @@ trawl:
|
|
626
625
|
if (ip - candidate > MAX_DISTANCE) break;
|
627
626
|
ip += matched;
|
628
627
|
last_distance = (int)(base - candidate); /* > 0 */
|
629
|
-
|
628
|
+
BROTLI_DCHECK(0 == memcmp(base, candidate, matched));
|
630
629
|
EmitCopyLen(matched, cmd_depth, cmd_bits, cmd_histo,
|
631
630
|
storage_ix, storage);
|
632
631
|
EmitDistance((size_t)last_distance, cmd_depth, cmd_bits,
|
@@ -659,7 +658,7 @@ trawl:
|
|
659
658
|
}
|
660
659
|
|
661
660
|
emit_remainder:
|
662
|
-
|
661
|
+
BROTLI_DCHECK(next_emit <= ip_end);
|
663
662
|
input += block_size;
|
664
663
|
input_size -= block_size;
|
665
664
|
block_size = BROTLI_MIN(size_t, input_size, kMergeBlockSize);
|
@@ -669,7 +668,7 @@ trawl:
|
|
669
668
|
if (input_size > 0 &&
|
670
669
|
total_block_size + block_size <= (1 << 20) &&
|
671
670
|
ShouldMergeBlock(input, block_size, lit_depth)) {
|
672
|
-
|
671
|
+
BROTLI_DCHECK(total_block_size > (1 << 16));
|
673
672
|
/* Update the size of the current meta-block and continue emitting commands.
|
674
673
|
We can do this because the current size and the new size both have 5
|
675
674
|
nibbles. */
|
@@ -752,7 +751,7 @@ void BrotliCompressFragmentFast(
|
|
752
751
|
const size_t table_bits = Log2FloorNonZero(table_size);
|
753
752
|
|
754
753
|
if (input_size == 0) {
|
755
|
-
|
754
|
+
BROTLI_DCHECK(is_last);
|
756
755
|
BrotliWriteBits(1, 1, storage_ix, storage); /* islast */
|
757
756
|
BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */
|
758
757
|
*storage_ix = (*storage_ix + 7u) & ~7u;
|
@@ -768,7 +767,7 @@ void BrotliCompressFragmentFast(
|
|
768
767
|
break;
|
769
768
|
FOR_TABLE_BITS_(CASE_)
|
770
769
|
#undef CASE_
|
771
|
-
default:
|
770
|
+
default: BROTLI_DCHECK(0); break;
|
772
771
|
}
|
773
772
|
|
774
773
|
/* If output is larger than single uncompressed block, rewrite it. */
|
@@ -12,9 +12,9 @@
|
|
12
12
|
#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_H_
|
13
13
|
#define BROTLI_ENC_COMPRESS_FRAGMENT_H_
|
14
14
|
|
15
|
+
#include "../common/platform.h"
|
15
16
|
#include <brotli/types.h>
|
16
17
|
#include "./memory.h"
|
17
|
-
#include "./port.h"
|
18
18
|
|
19
19
|
#if defined(__cplusplus) || defined(c_plusplus)
|
20
20
|
extern "C" {
|
@@ -15,6 +15,7 @@
|
|
15
15
|
#include <string.h> /* memcmp, memcpy, memset */
|
16
16
|
|
17
17
|
#include "../common/constants.h"
|
18
|
+
#include "../common/platform.h"
|
18
19
|
#include <brotli/types.h>
|
19
20
|
#include "./bit_cost.h"
|
20
21
|
#include "./brotli_bit_stream.h"
|
@@ -22,10 +23,8 @@
|
|
22
23
|
#include "./fast_log.h"
|
23
24
|
#include "./find_match_length.h"
|
24
25
|
#include "./memory.h"
|
25
|
-
#include "./port.h"
|
26
26
|
#include "./write_bits.h"
|
27
27
|
|
28
|
-
|
29
28
|
#if defined(__cplusplus) || defined(c_plusplus)
|
30
29
|
extern "C" {
|
31
30
|
#endif
|
@@ -38,28 +37,31 @@ extern "C" {
|
|
38
37
|
* There is no effort to ensure that it is a prime, the oddity is enough
|
39
38
|
for this use.
|
40
39
|
* The number has been tuned heuristically against compression benchmarks. */
|
41
|
-
static const uint32_t kHashMul32 =
|
40
|
+
static const uint32_t kHashMul32 = 0x1E35A7BD;
|
42
41
|
|
43
|
-
static BROTLI_INLINE uint32_t Hash(const uint8_t* p,
|
44
|
-
|
42
|
+
static BROTLI_INLINE uint32_t Hash(const uint8_t* p,
|
43
|
+
size_t shift, size_t length) {
|
44
|
+
const uint64_t h =
|
45
|
+
(BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32;
|
45
46
|
return (uint32_t)(h >> shift);
|
46
47
|
}
|
47
48
|
|
48
|
-
static BROTLI_INLINE uint32_t HashBytesAtOffset(
|
49
|
-
|
50
|
-
|
51
|
-
assert(offset <= 2);
|
49
|
+
static BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset,
|
50
|
+
size_t shift, size_t length) {
|
51
|
+
BROTLI_DCHECK(offset <= 8 - length);
|
52
52
|
{
|
53
|
-
const uint64_t h = ((v >> (8 * offset)) <<
|
53
|
+
const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32;
|
54
54
|
return (uint32_t)(h >> shift);
|
55
55
|
}
|
56
56
|
}
|
57
57
|
|
58
|
-
static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2,
|
59
|
+
size_t length) {
|
60
|
+
if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) {
|
61
|
+
if (length == 4) return BROTLI_TRUE;
|
62
|
+
return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]);
|
63
|
+
}
|
64
|
+
return BROTLI_FALSE;
|
63
65
|
}
|
64
66
|
|
65
67
|
/* Builds a command and distance prefix code (each 64 symbols) into "depth" and
|
@@ -236,7 +238,8 @@ static void BrotliStoreMetaBlockHeader(
|
|
236
238
|
|
237
239
|
static BROTLI_INLINE void CreateCommands(const uint8_t* input,
|
238
240
|
size_t block_size, size_t input_size, const uint8_t* base_ip, int* table,
|
239
|
-
size_t table_bits,
|
241
|
+
size_t table_bits, size_t min_match,
|
242
|
+
uint8_t** literals, uint32_t** commands) {
|
240
243
|
/* "ip" is the input pointer. */
|
241
244
|
const uint8_t* ip = input;
|
242
245
|
const size_t shift = 64u - table_bits;
|
@@ -248,19 +251,18 @@ static BROTLI_INLINE void CreateCommands(const uint8_t* input,
|
|
248
251
|
|
249
252
|
int last_distance = -1;
|
250
253
|
const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;
|
251
|
-
const size_t kMinMatchLen = 6;
|
252
254
|
|
253
255
|
if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {
|
254
256
|
/* For the last block, we need to keep a 16 bytes margin so that we can be
|
255
257
|
sure that all distances are at most window size - 16.
|
256
258
|
For all other blocks, we only need to keep a margin of 5 bytes so that
|
257
259
|
we don't go over the block size with a copy. */
|
258
|
-
const size_t len_limit = BROTLI_MIN(size_t, block_size -
|
260
|
+
const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match,
|
259
261
|
input_size - kInputMarginBytes);
|
260
262
|
const uint8_t* ip_limit = input + len_limit;
|
261
263
|
|
262
264
|
uint32_t next_hash;
|
263
|
-
for (next_hash = Hash(++ip, shift); ; ) {
|
265
|
+
for (next_hash = Hash(++ip, shift, min_match); ; ) {
|
264
266
|
/* Step 1: Scan forward in the input looking for a 6-byte-long match.
|
265
267
|
If we get close to exhausting the input then goto emit_remainder.
|
266
268
|
|
@@ -281,31 +283,31 @@ static BROTLI_INLINE void CreateCommands(const uint8_t* input,
|
|
281
283
|
const uint8_t* next_ip = ip;
|
282
284
|
const uint8_t* candidate;
|
283
285
|
|
284
|
-
|
286
|
+
BROTLI_DCHECK(next_emit < ip);
|
285
287
|
trawl:
|
286
288
|
do {
|
287
289
|
uint32_t hash = next_hash;
|
288
290
|
uint32_t bytes_between_hash_lookups = skip++ >> 5;
|
289
291
|
ip = next_ip;
|
290
|
-
|
292
|
+
BROTLI_DCHECK(hash == Hash(ip, shift, min_match));
|
291
293
|
next_ip = ip + bytes_between_hash_lookups;
|
292
294
|
if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {
|
293
295
|
goto emit_remainder;
|
294
296
|
}
|
295
|
-
next_hash = Hash(next_ip, shift);
|
297
|
+
next_hash = Hash(next_ip, shift, min_match);
|
296
298
|
candidate = ip - last_distance;
|
297
|
-
if (IsMatch(ip, candidate)) {
|
299
|
+
if (IsMatch(ip, candidate, min_match)) {
|
298
300
|
if (BROTLI_PREDICT_TRUE(candidate < ip)) {
|
299
301
|
table[hash] = (int)(ip - base_ip);
|
300
302
|
break;
|
301
303
|
}
|
302
304
|
}
|
303
305
|
candidate = base_ip + table[hash];
|
304
|
-
|
305
|
-
|
306
|
+
BROTLI_DCHECK(candidate >= base_ip);
|
307
|
+
BROTLI_DCHECK(candidate < ip);
|
306
308
|
|
307
309
|
table[hash] = (int)(ip - base_ip);
|
308
|
-
} while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate)));
|
310
|
+
} while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match)));
|
309
311
|
|
310
312
|
/* Check copy distance. If candidate is not feasible, continue search.
|
311
313
|
Checking is done outside of hot loop to reduce overhead. */
|
@@ -320,12 +322,13 @@ trawl:
|
|
320
322
|
/* We have a 6-byte match at ip, and we need to emit bytes in
|
321
323
|
[next_emit, ip). */
|
322
324
|
const uint8_t* base = ip;
|
323
|
-
size_t matched =
|
324
|
-
candidate +
|
325
|
+
size_t matched = min_match + FindMatchLengthWithLimit(
|
326
|
+
candidate + min_match, ip + min_match,
|
327
|
+
(size_t)(ip_end - ip) - min_match);
|
325
328
|
int distance = (int)(base - candidate); /* > 0 */
|
326
329
|
int insert = (int)(base - next_emit);
|
327
330
|
ip += matched;
|
328
|
-
|
331
|
+
BROTLI_DCHECK(0 == memcmp(base, candidate, matched));
|
329
332
|
EmitInsertLen((uint32_t)insert, commands);
|
330
333
|
memcpy(*literals, next_emit, (size_t)insert);
|
331
334
|
*literals += insert;
|
@@ -346,35 +349,50 @@ trawl:
|
|
346
349
|
/* We could immediately start working at ip now, but to improve
|
347
350
|
compression we first update "table" with the hashes of some
|
348
351
|
positions within the last copy. */
|
349
|
-
uint64_t input_bytes
|
350
|
-
uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);
|
352
|
+
uint64_t input_bytes;
|
351
353
|
uint32_t cur_hash;
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
354
|
+
uint32_t prev_hash;
|
355
|
+
if (min_match == 4) {
|
356
|
+
input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);
|
357
|
+
cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);
|
358
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
359
|
+
table[prev_hash] = (int)(ip - base_ip - 3);
|
360
|
+
prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
|
361
|
+
table[prev_hash] = (int)(ip - base_ip - 2);
|
362
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
363
|
+
table[prev_hash] = (int)(ip - base_ip - 1);
|
364
|
+
} else {
|
365
|
+
input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);
|
366
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
367
|
+
table[prev_hash] = (int)(ip - base_ip - 5);
|
368
|
+
prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
|
369
|
+
table[prev_hash] = (int)(ip - base_ip - 4);
|
370
|
+
prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
|
371
|
+
table[prev_hash] = (int)(ip - base_ip - 3);
|
372
|
+
input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);
|
373
|
+
cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
|
374
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
375
|
+
table[prev_hash] = (int)(ip - base_ip - 2);
|
376
|
+
prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
|
377
|
+
table[prev_hash] = (int)(ip - base_ip - 1);
|
378
|
+
}
|
363
379
|
|
364
380
|
candidate = base_ip + table[cur_hash];
|
365
381
|
table[cur_hash] = (int)(ip - base_ip);
|
366
382
|
}
|
367
383
|
}
|
368
384
|
|
369
|
-
while (ip - candidate <= MAX_DISTANCE &&
|
385
|
+
while (ip - candidate <= MAX_DISTANCE &&
|
386
|
+
IsMatch(ip, candidate, min_match)) {
|
370
387
|
/* We have a 6-byte match at ip, and no need to emit any
|
371
388
|
literal bytes prior to ip. */
|
372
389
|
const uint8_t* base = ip;
|
373
|
-
size_t matched =
|
374
|
-
candidate +
|
390
|
+
size_t matched = min_match + FindMatchLengthWithLimit(
|
391
|
+
candidate + min_match, ip + min_match,
|
392
|
+
(size_t)(ip_end - ip) - min_match);
|
375
393
|
ip += matched;
|
376
394
|
last_distance = (int)(base - candidate); /* > 0 */
|
377
|
-
|
395
|
+
BROTLI_DCHECK(0 == memcmp(base, candidate, matched));
|
378
396
|
EmitCopyLen(matched, commands);
|
379
397
|
EmitDistance((uint32_t)last_distance, commands);
|
380
398
|
|
@@ -386,32 +404,45 @@ trawl:
|
|
386
404
|
/* We could immediately start working at ip now, but to improve
|
387
405
|
compression we first update "table" with the hashes of some
|
388
406
|
positions within the last copy. */
|
389
|
-
uint64_t input_bytes
|
390
|
-
uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);
|
407
|
+
uint64_t input_bytes;
|
391
408
|
uint32_t cur_hash;
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
409
|
+
uint32_t prev_hash;
|
410
|
+
if (min_match == 4) {
|
411
|
+
input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);
|
412
|
+
cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);
|
413
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
414
|
+
table[prev_hash] = (int)(ip - base_ip - 3);
|
415
|
+
prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
|
416
|
+
table[prev_hash] = (int)(ip - base_ip - 2);
|
417
|
+
prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
|
418
|
+
table[prev_hash] = (int)(ip - base_ip - 1);
|
419
|
+
} else {
|
420
|
+
input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);
|
421
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
422
|
+
table[prev_hash] = (int)(ip - base_ip - 5);
|
423
|
+
prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
|
424
|
+
table[prev_hash] = (int)(ip - base_ip - 4);
|
425
|
+
prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
|
426
|
+
table[prev_hash] = (int)(ip - base_ip - 3);
|
427
|
+
input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);
|
428
|
+
cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);
|
429
|
+
prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);
|
430
|
+
table[prev_hash] = (int)(ip - base_ip - 2);
|
431
|
+
prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);
|
432
|
+
table[prev_hash] = (int)(ip - base_ip - 1);
|
433
|
+
}
|
403
434
|
|
404
435
|
candidate = base_ip + table[cur_hash];
|
405
436
|
table[cur_hash] = (int)(ip - base_ip);
|
406
437
|
}
|
407
438
|
}
|
408
439
|
|
409
|
-
next_hash = Hash(++ip, shift);
|
440
|
+
next_hash = Hash(++ip, shift, min_match);
|
410
441
|
}
|
411
442
|
}
|
412
443
|
|
413
444
|
emit_remainder:
|
414
|
-
|
445
|
+
BROTLI_DCHECK(next_emit <= ip_end);
|
415
446
|
/* Emit the remaining bytes as literals. */
|
416
447
|
if (next_emit < ip_end) {
|
417
448
|
const uint32_t insert = (uint32_t)(ip_end - next_emit);
|
@@ -457,7 +488,7 @@ static void StoreCommands(MemoryManager* m,
|
|
457
488
|
|
458
489
|
for (i = 0; i < num_commands; ++i) {
|
459
490
|
const uint32_t code = commands[i] & 0xFF;
|
460
|
-
|
491
|
+
BROTLI_DCHECK(code < 128);
|
461
492
|
++cmd_histo[code];
|
462
493
|
}
|
463
494
|
cmd_histo[1] += 1;
|
@@ -471,7 +502,7 @@ static void StoreCommands(MemoryManager* m,
|
|
471
502
|
const uint32_t cmd = commands[i];
|
472
503
|
const uint32_t code = cmd & 0xFF;
|
473
504
|
const uint32_t extra = cmd >> 8;
|
474
|
-
|
505
|
+
BROTLI_DCHECK(code < 128);
|
475
506
|
BrotliWriteBits(cmd_depths[code], cmd_bits[code], storage_ix, storage);
|
476
507
|
BrotliWriteBits(kNumExtraBits[code], extra, storage_ix, storage);
|
477
508
|
if (code < 24) {
|
@@ -526,7 +557,8 @@ static void EmitUncompressedMetaBlock(const uint8_t* input, size_t input_size,
|
|
526
557
|
static BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl(
|
527
558
|
MemoryManager* m, const uint8_t* input, size_t input_size,
|
528
559
|
BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,
|
529
|
-
int* table, size_t table_bits, size_t
|
560
|
+
int* table, size_t table_bits, size_t min_match,
|
561
|
+
size_t* storage_ix, uint8_t* storage) {
|
530
562
|
/* Save the start of the first block for position and distance computations.
|
531
563
|
*/
|
532
564
|
const uint8_t* base_ip = input;
|
@@ -538,8 +570,8 @@ static BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl(
|
|
538
570
|
uint32_t* commands = command_buf;
|
539
571
|
uint8_t* literals = literal_buf;
|
540
572
|
size_t num_literals;
|
541
|
-
CreateCommands(input, block_size, input_size, base_ip, table,
|
542
|
-
&literals, &commands);
|
573
|
+
CreateCommands(input, block_size, input_size, base_ip, table,
|
574
|
+
table_bits, min_match, &literals, &commands);
|
543
575
|
num_literals = (size_t)(literals - literal_buf);
|
544
576
|
if (ShouldCompress(input, block_size, num_literals)) {
|
545
577
|
const size_t num_commands = (size_t)(commands - command_buf);
|
@@ -568,8 +600,9 @@ static BROTLI_NOINLINE void BrotliCompressFragmentTwoPassImpl ## B( \
|
|
568
600
|
MemoryManager* m, const uint8_t* input, size_t input_size, \
|
569
601
|
BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, \
|
570
602
|
int* table, size_t* storage_ix, uint8_t* storage) { \
|
603
|
+
size_t min_match = (B <= 15) ? 4 : 6; \
|
571
604
|
BrotliCompressFragmentTwoPassImpl(m, input, input_size, is_last, command_buf,\
|
572
|
-
literal_buf, table, B, storage_ix, storage);
|
605
|
+
literal_buf, table, B, min_match, storage_ix, storage); \
|
573
606
|
}
|
574
607
|
FOR_TABLE_BITS_(BAKE_METHOD_PARAM_)
|
575
608
|
#undef BAKE_METHOD_PARAM_
|
@@ -589,7 +622,7 @@ void BrotliCompressFragmentTwoPass(
|
|
589
622
|
break;
|
590
623
|
FOR_TABLE_BITS_(CASE_)
|
591
624
|
#undef CASE_
|
592
|
-
default:
|
625
|
+
default: BROTLI_DCHECK(0); break;
|
593
626
|
}
|
594
627
|
|
595
628
|
/* If output is larger than single uncompressed block, rewrite it. */
|