brotli 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -3
- data/brotli.gemspec +1 -1
- data/ext/brotli/brotli.c +4 -4
- data/ext/brotli/brotli.h +2 -2
- data/ext/brotli/extconf.rb +9 -16
- data/lib/brotli/version.rb +1 -1
- data/vendor/brotli/{common → c/common}/constants.h +11 -1
- data/vendor/brotli/c/common/dictionary.bin +432 -0
- data/vendor/brotli/c/common/dictionary.c +5905 -0
- data/vendor/brotli/c/common/dictionary.h +64 -0
- data/vendor/brotli/c/common/version.h +19 -0
- data/vendor/brotli/{dec → c/dec}/bit_reader.c +2 -2
- data/vendor/brotli/{dec → c/dec}/bit_reader.h +11 -34
- data/vendor/brotli/{dec → c/dec}/context.h +1 -1
- data/vendor/brotli/{dec → c/dec}/decode.c +389 -356
- data/vendor/brotli/{dec → c/dec}/huffman.c +24 -23
- data/vendor/brotli/{dec → c/dec}/huffman.h +1 -1
- data/vendor/brotli/{dec → c/dec}/port.h +19 -10
- data/vendor/brotli/{dec → c/dec}/prefix.h +1 -1
- data/vendor/brotli/{dec → c/dec}/state.c +23 -19
- data/vendor/brotli/{dec → c/dec}/state.h +18 -17
- data/vendor/brotli/{dec → c/dec}/transform.h +2 -2
- data/vendor/brotli/c/enc/backward_references.c +134 -0
- data/vendor/brotli/c/enc/backward_references.h +39 -0
- data/vendor/brotli/{enc/backward_references.c → c/enc/backward_references_hq.c} +144 -232
- data/vendor/brotli/{enc/backward_references.h → c/enc/backward_references_hq.h} +28 -31
- data/vendor/brotli/{enc → c/enc}/backward_references_inc.h +37 -31
- data/vendor/brotli/{enc → c/enc}/bit_cost.c +1 -1
- data/vendor/brotli/{enc → c/enc}/bit_cost.h +1 -1
- data/vendor/brotli/{enc → c/enc}/bit_cost_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/block_encoder_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/block_splitter.c +2 -4
- data/vendor/brotli/{enc → c/enc}/block_splitter.h +1 -1
- data/vendor/brotli/{enc → c/enc}/block_splitter_inc.h +6 -7
- data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.c +22 -26
- data/vendor/brotli/{enc → c/enc}/brotli_bit_stream.h +1 -5
- data/vendor/brotli/{enc → c/enc}/cluster.c +1 -1
- data/vendor/brotli/{enc → c/enc}/cluster.h +1 -1
- data/vendor/brotli/{enc → c/enc}/cluster_inc.h +2 -0
- data/vendor/brotli/{enc → c/enc}/command.h +34 -17
- data/vendor/brotli/{enc → c/enc}/compress_fragment.c +97 -53
- data/vendor/brotli/{enc → c/enc}/compress_fragment.h +5 -2
- data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.c +106 -51
- data/vendor/brotli/{enc → c/enc}/compress_fragment_two_pass.h +5 -2
- data/vendor/brotli/{enc → c/enc}/context.h +3 -3
- data/vendor/brotli/c/enc/dictionary_hash.c +1120 -0
- data/vendor/brotli/c/enc/dictionary_hash.h +24 -0
- data/vendor/brotli/{enc → c/enc}/encode.c +442 -240
- data/vendor/brotli/{enc → c/enc}/entropy_encode.c +9 -9
- data/vendor/brotli/{enc → c/enc}/entropy_encode.h +4 -4
- data/vendor/brotli/{enc → c/enc}/entropy_encode_static.h +4 -4
- data/vendor/brotli/{enc → c/enc}/fast_log.h +3 -3
- data/vendor/brotli/{enc → c/enc}/find_match_length.h +8 -8
- data/vendor/brotli/c/enc/hash.h +446 -0
- data/vendor/brotli/{enc → c/enc}/hash_forgetful_chain_inc.h +72 -68
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +266 -0
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +258 -0
- data/vendor/brotli/{enc → c/enc}/hash_longest_match_quickly_inc.h +81 -77
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +326 -0
- data/vendor/brotli/{enc → c/enc}/histogram.c +4 -2
- data/vendor/brotli/{enc → c/enc}/histogram.h +1 -1
- data/vendor/brotli/{enc → c/enc}/histogram_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/literal_cost.c +4 -7
- data/vendor/brotli/{enc → c/enc}/literal_cost.h +2 -2
- data/vendor/brotli/{enc → c/enc}/memory.c +1 -1
- data/vendor/brotli/{enc → c/enc}/memory.h +3 -2
- data/vendor/brotli/{enc → c/enc}/metablock.c +136 -123
- data/vendor/brotli/{enc → c/enc}/metablock.h +2 -12
- data/vendor/brotli/{enc → c/enc}/metablock_inc.h +0 -0
- data/vendor/brotli/{enc → c/enc}/port.h +49 -33
- data/vendor/brotli/{enc → c/enc}/prefix.h +4 -2
- data/vendor/brotli/{enc → c/enc}/quality.h +47 -17
- data/vendor/brotli/{enc → c/enc}/ringbuffer.h +6 -6
- data/vendor/brotli/{enc → c/enc}/static_dict.c +26 -22
- data/vendor/brotli/{enc → c/enc}/static_dict.h +3 -1
- data/vendor/brotli/c/enc/static_dict_lut.h +5864 -0
- data/vendor/brotli/{enc → c/enc}/utf8_util.c +1 -1
- data/vendor/brotli/{enc → c/enc}/utf8_util.h +2 -2
- data/vendor/brotli/{enc → c/enc}/write_bits.h +3 -3
- data/vendor/brotli/c/include/brotli/decode.h +339 -0
- data/vendor/brotli/c/include/brotli/encode.h +402 -0
- data/vendor/brotli/c/include/brotli/port.h +146 -0
- data/vendor/brotli/c/include/brotli/types.h +90 -0
- metadata +80 -79
- data/vendor/brotli/common/dictionary.c +0 -9474
- data/vendor/brotli/common/dictionary.h +0 -29
- data/vendor/brotli/common/port.h +0 -107
- data/vendor/brotli/common/types.h +0 -58
- data/vendor/brotli/dec/decode.h +0 -188
- data/vendor/brotli/enc/compressor.cc +0 -139
- data/vendor/brotli/enc/compressor.h +0 -161
- data/vendor/brotli/enc/dictionary_hash.h +0 -4121
- data/vendor/brotli/enc/encode.h +0 -221
- data/vendor/brotli/enc/encode_parallel.cc +0 -289
- data/vendor/brotli/enc/encode_parallel.h +0 -27
- data/vendor/brotli/enc/hash.h +0 -717
- data/vendor/brotli/enc/hash_longest_match_inc.h +0 -241
- data/vendor/brotli/enc/static_dict_lut.h +0 -11241
- data/vendor/brotli/enc/streams.cc +0 -114
- data/vendor/brotli/enc/streams.h +0 -121
@@ -16,7 +16,7 @@
|
|
16
16
|
#ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
17
17
|
#define BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
18
18
|
|
19
|
-
#include
|
19
|
+
#include <brotli/types.h>
|
20
20
|
#include "./command.h"
|
21
21
|
#include "./context.h"
|
22
22
|
#include "./entropy_encode.h"
|
@@ -96,10 +96,6 @@ BROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock(
|
|
96
96
|
BROTLI_BOOL is_final_block, const uint8_t* input, size_t position,
|
97
97
|
size_t mask, size_t len, size_t* storage_ix, uint8_t* storage);
|
98
98
|
|
99
|
-
/* Stores an empty metadata meta-block and syncs to a byte boundary. */
|
100
|
-
BROTLI_INTERNAL void BrotliStoreSyncMetaBlock(size_t* storage_ix,
|
101
|
-
uint8_t* storage);
|
102
|
-
|
103
99
|
#if defined(__cplusplus) || defined(c_plusplus)
|
104
100
|
} /* extern "C" */
|
105
101
|
#endif
|
@@ -9,8 +9,9 @@
|
|
9
9
|
#ifndef BROTLI_ENC_COMMAND_H_
|
10
10
|
#define BROTLI_ENC_COMMAND_H_
|
11
11
|
|
12
|
-
#include "../common/
|
13
|
-
#include
|
12
|
+
#include "../common/constants.h"
|
13
|
+
#include <brotli/port.h>
|
14
|
+
#include <brotli/types.h>
|
14
15
|
#include "./fast_log.h"
|
15
16
|
#include "./prefix.h"
|
16
17
|
|
@@ -64,11 +65,17 @@ static BROTLI_INLINE uint16_t CombineLengthCodes(
|
|
64
65
|
if (use_last_distance && inscode < 8 && copycode < 16) {
|
65
66
|
return (copycode < 8) ? bits64 : (bits64 | 64);
|
66
67
|
} else {
|
67
|
-
/*
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
/* Specification: 5 Encoding of ... (last table) */
|
69
|
+
/* offset = 2 * index, where index is in range [0..8] */
|
70
|
+
int offset = 2 * ((copycode >> 3) + 3 * (inscode >> 3));
|
71
|
+
/* All values in specification are K * 64,
|
72
|
+
where K = [2, 3, 6, 4, 5, 8, 7, 9, 10],
|
73
|
+
i + 1 = [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
74
|
+
K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1, 2] = D.
|
75
|
+
All values in D require only 2 bits to encode.
|
76
|
+
Magic constant is shifted 6 bits left, to avoid final multiplication. */
|
77
|
+
offset = (offset << 5) + 0x40 + ((0x520D40 >> offset) & 0xC0);
|
78
|
+
return (uint16_t)offset | bits64;
|
72
79
|
}
|
73
80
|
}
|
74
81
|
|
@@ -107,35 +114,44 @@ typedef struct Command {
|
|
107
114
|
|
108
115
|
/* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */
|
109
116
|
static BROTLI_INLINE void InitCommand(Command* self, size_t insertlen,
|
110
|
-
size_t copylen,
|
117
|
+
size_t copylen, int copylen_code_delta, size_t distance_code) {
|
118
|
+
/* Don't rely on signed int representation, use honest casts. */
|
119
|
+
uint32_t delta = (uint8_t)((int8_t)copylen_code_delta);
|
111
120
|
self->insert_len_ = (uint32_t)insertlen;
|
112
|
-
self->copy_len_ = (uint32_t)(copylen | (
|
121
|
+
self->copy_len_ = (uint32_t)(copylen | (delta << 24));
|
113
122
|
/* The distance prefix and extra bits are stored in this Command as if
|
114
123
|
npostfix and ndirect were 0, they are only recomputed later after the
|
115
124
|
clustering if needed. */
|
116
125
|
PrefixEncodeCopyDistance(
|
117
126
|
distance_code, 0, 0, &self->dist_prefix_, &self->dist_extra_);
|
118
127
|
GetLengthCode(
|
119
|
-
insertlen,
|
120
|
-
&self->cmd_prefix_);
|
128
|
+
insertlen, (size_t)((int)copylen + copylen_code_delta),
|
129
|
+
TO_BROTLI_BOOL(self->dist_prefix_ == 0), &self->cmd_prefix_);
|
121
130
|
}
|
122
131
|
|
123
132
|
static BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) {
|
124
133
|
self->insert_len_ = (uint32_t)insertlen;
|
125
134
|
self->copy_len_ = 4 << 24;
|
126
135
|
self->dist_extra_ = 0;
|
127
|
-
self->dist_prefix_ =
|
136
|
+
self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES;
|
128
137
|
GetLengthCode(insertlen, 4, BROTLI_FALSE, &self->cmd_prefix_);
|
129
138
|
}
|
130
139
|
|
131
|
-
static BROTLI_INLINE uint32_t
|
132
|
-
if (self->dist_prefix_ <
|
140
|
+
static BROTLI_INLINE uint32_t CommandRestoreDistanceCode(const Command* self) {
|
141
|
+
if (self->dist_prefix_ < BROTLI_NUM_DISTANCE_SHORT_CODES) {
|
133
142
|
return self->dist_prefix_;
|
134
143
|
} else {
|
135
144
|
uint32_t nbits = self->dist_extra_ >> 24;
|
136
145
|
uint32_t extra = self->dist_extra_ & 0xffffff;
|
137
|
-
|
138
|
-
|
146
|
+
/* It is assumed that the distance was first encoded with NPOSTFIX = 0 and
|
147
|
+
NDIRECT = 0, so the code itself is of this form:
|
148
|
+
BROTLI_NUM_DISTANCE_SHORT_CODES + 2 * (nbits - 1) + prefix_bit
|
149
|
+
Therefore, the following expression results in (2 + prefix_bit). */
|
150
|
+
uint32_t prefix =
|
151
|
+
self->dist_prefix_ + 4u - BROTLI_NUM_DISTANCE_SHORT_CODES - 2u * nbits;
|
152
|
+
/* Subtract 4 for offset (Chapter 4.) and
|
153
|
+
increase by BROTLI_NUM_DISTANCE_SHORT_CODES - 1 */
|
154
|
+
return (prefix << nbits) + extra + BROTLI_NUM_DISTANCE_SHORT_CODES - 4u;
|
139
155
|
}
|
140
156
|
}
|
141
157
|
|
@@ -153,7 +169,8 @@ static BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) {
|
|
153
169
|
}
|
154
170
|
|
155
171
|
static BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) {
|
156
|
-
|
172
|
+
int32_t delta = (int8_t)((uint8_t)(self->copy_len_ >> 24));
|
173
|
+
return (uint32_t)((int32_t)(self->copy_len_ & 0xFFFFFF) + delta);
|
157
174
|
}
|
158
175
|
|
159
176
|
#if defined(__cplusplus) || defined(c_plusplus)
|
@@ -16,7 +16,8 @@
|
|
16
16
|
|
17
17
|
#include <string.h> /* memcmp, memcpy, memset */
|
18
18
|
|
19
|
-
#include "../common/
|
19
|
+
#include "../common/constants.h"
|
20
|
+
#include <brotli/types.h>
|
20
21
|
#include "./brotli_bit_stream.h"
|
21
22
|
#include "./entropy_encode.h"
|
22
23
|
#include "./fast_log.h"
|
@@ -30,16 +31,18 @@
|
|
30
31
|
extern "C" {
|
31
32
|
#endif
|
32
33
|
|
34
|
+
#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)
|
35
|
+
|
33
36
|
/* kHashMul32 multiplier has these properties:
|
34
37
|
* The multiplier must be odd. Otherwise we may lose the highest bit.
|
35
|
-
* No long streaks of
|
38
|
+
* No long streaks of ones or zeros.
|
36
39
|
* There is no effort to ensure that it is a prime, the oddity is enough
|
37
40
|
for this use.
|
38
41
|
* The number has been tuned heuristically against compression benchmarks. */
|
39
42
|
static const uint32_t kHashMul32 = 0x1e35a7bd;
|
40
43
|
|
41
44
|
static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) {
|
42
|
-
const uint64_t h = (
|
45
|
+
const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 24) * kHashMul32;
|
43
46
|
return (uint32_t)(h >> shift);
|
44
47
|
}
|
45
48
|
|
@@ -132,7 +135,7 @@ static void BuildAndStoreCommandPrefixCode(const uint32_t histogram[128],
|
|
132
135
|
|
133
136
|
BrotliCreateHuffmanTree(histogram, 64, 15, tree, depth);
|
134
137
|
BrotliCreateHuffmanTree(&histogram[64], 64, 14, tree, &depth[64]);
|
135
|
-
/* We have to jump through a few
|
138
|
+
/* We have to jump through a few hoops here in order to compute
|
136
139
|
the command bits because the symbols are in a different order than in
|
137
140
|
the full alphabet. This looks complicated, but having the symbols
|
138
141
|
in this order in the command bits saves a few branches in the Emit*
|
@@ -322,21 +325,20 @@ static BROTLI_INLINE void EmitLiterals(const uint8_t* input, const size_t len,
|
|
322
325
|
}
|
323
326
|
}
|
324
327
|
|
325
|
-
/* REQUIRES: len <= 1 <<
|
328
|
+
/* REQUIRES: len <= 1 << 24. */
|
326
329
|
static void BrotliStoreMetaBlockHeader(
|
327
330
|
size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix,
|
328
331
|
uint8_t* storage) {
|
332
|
+
size_t nibbles = 6;
|
329
333
|
/* ISLAST */
|
330
334
|
BrotliWriteBits(1, 0, storage_ix, storage);
|
331
335
|
if (len <= (1U << 16)) {
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
} else {
|
336
|
-
/* MNIBBLES is 5 */
|
337
|
-
BrotliWriteBits(2, 1, storage_ix, storage);
|
338
|
-
BrotliWriteBits(20, len - 1, storage_ix, storage);
|
336
|
+
nibbles = 4;
|
337
|
+
} else if (len <= (1U << 20)) {
|
338
|
+
nibbles = 5;
|
339
339
|
}
|
340
|
+
BrotliWriteBits(2, nibbles - 4, storage_ix, storage);
|
341
|
+
BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage);
|
340
342
|
/* ISUNCOMPRESSED */
|
341
343
|
BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage);
|
342
344
|
}
|
@@ -421,13 +423,11 @@ static uint32_t kCmdHistoSeed[128] = {
|
|
421
423
|
1, 1, 1, 1, 0, 0, 0, 0,
|
422
424
|
};
|
423
425
|
|
424
|
-
void
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
size_t* cmd_code_numbits, uint8_t* cmd_code,
|
430
|
-
size_t* storage_ix, uint8_t* storage) {
|
426
|
+
static BROTLI_INLINE void BrotliCompressFragmentFastImpl(
|
427
|
+
MemoryManager* m, const uint8_t* input, size_t input_size,
|
428
|
+
BROTLI_BOOL is_last, int* table, size_t table_bits, uint8_t cmd_depth[128],
|
429
|
+
uint16_t cmd_bits[128], size_t* cmd_code_numbits, uint8_t* cmd_code,
|
430
|
+
size_t* storage_ix, uint8_t* storage) {
|
431
431
|
uint32_t cmd_histo[128];
|
432
432
|
const uint8_t* ip_end;
|
433
433
|
|
@@ -442,7 +442,7 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
442
442
|
static const size_t kFirstBlockSize = 3 << 15;
|
443
443
|
static const size_t kMergeBlockSize = 1 << 16;
|
444
444
|
|
445
|
-
const size_t kInputMarginBytes =
|
445
|
+
const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;
|
446
446
|
const size_t kMinMatchLen = 5;
|
447
447
|
|
448
448
|
const uint8_t* metablock_start = input;
|
@@ -460,21 +460,7 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
460
460
|
const uint8_t* ip;
|
461
461
|
int last_distance;
|
462
462
|
|
463
|
-
const size_t shift = 64u -
|
464
|
-
assert(table_size);
|
465
|
-
assert(table_size <= (1u << 31));
|
466
|
-
/* table must be power of two */
|
467
|
-
assert((table_size & (table_size - 1)) == 0);
|
468
|
-
assert(table_size - 1 ==
|
469
|
-
(size_t)(MAKE_UINT64_T(0xFFFFFFFF, 0xFFFFFF) >> shift));
|
470
|
-
|
471
|
-
if (input_size == 0) {
|
472
|
-
assert(is_last);
|
473
|
-
BrotliWriteBits(1, 1, storage_ix, storage); /* islast */
|
474
|
-
BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */
|
475
|
-
*storage_ix = (*storage_ix + 7u) & ~7u;
|
476
|
-
return;
|
477
|
-
}
|
463
|
+
const size_t shift = 64u - table_bits;
|
478
464
|
|
479
465
|
BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);
|
480
466
|
/* No block splits, no contexts. */
|
@@ -506,7 +492,7 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
506
492
|
last_distance = -1;
|
507
493
|
ip_end = input + block_size;
|
508
494
|
|
509
|
-
if (
|
495
|
+
if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {
|
510
496
|
/* For the last block, we need to keep a 16 bytes margin so that we can be
|
511
497
|
sure that all distances are at most window size - 16.
|
512
498
|
For all other blocks, we only need to keep a margin of 5 bytes so that
|
@@ -530,27 +516,27 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
530
516
|
and doesn't bother looking for matches everywhere.
|
531
517
|
|
532
518
|
The "skip" variable keeps track of how many bytes there are since the
|
533
|
-
last match; dividing it by 32 (
|
519
|
+
last match; dividing it by 32 (i.e. right-shifting by five) gives the
|
534
520
|
number of bytes to move ahead for each iteration. */
|
535
521
|
uint32_t skip = 32;
|
536
522
|
|
537
523
|
const uint8_t* next_ip = ip;
|
538
524
|
const uint8_t* candidate;
|
539
525
|
assert(next_emit < ip);
|
540
|
-
|
526
|
+
trawl:
|
541
527
|
do {
|
542
528
|
uint32_t hash = next_hash;
|
543
529
|
uint32_t bytes_between_hash_lookups = skip++ >> 5;
|
544
530
|
assert(hash == Hash(next_ip, shift));
|
545
531
|
ip = next_ip;
|
546
532
|
next_ip = ip + bytes_between_hash_lookups;
|
547
|
-
if (
|
533
|
+
if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {
|
548
534
|
goto emit_remainder;
|
549
535
|
}
|
550
536
|
next_hash = Hash(next_ip, shift);
|
551
537
|
candidate = ip - last_distance;
|
552
538
|
if (IsMatch(ip, candidate)) {
|
553
|
-
if (
|
539
|
+
if (BROTLI_PREDICT_TRUE(candidate < ip)) {
|
554
540
|
table[hash] = (int)(ip - base_ip);
|
555
541
|
break;
|
556
542
|
}
|
@@ -560,10 +546,14 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
560
546
|
assert(candidate < ip);
|
561
547
|
|
562
548
|
table[hash] = (int)(ip - base_ip);
|
563
|
-
} while (
|
549
|
+
} while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate)));
|
550
|
+
|
551
|
+
/* Check copy distance. If candidate is not feasible, continue search.
|
552
|
+
Checking is done outside of hot loop to reduce overhead. */
|
553
|
+
if (ip - candidate > MAX_DISTANCE) goto trawl;
|
564
554
|
|
565
555
|
/* Step 2: Emit the found match together with the literal bytes from
|
566
|
-
"next_emit" to the bit stream, and then see if we can find a next
|
556
|
+
"next_emit" to the bit stream, and then see if we can find a next match
|
567
557
|
immediately afterwards. Repeat until we find no match for the input
|
568
558
|
without emitting some literal bytes. */
|
569
559
|
|
@@ -577,7 +567,7 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
577
567
|
size_t insert = (size_t)(base - next_emit);
|
578
568
|
ip += matched;
|
579
569
|
assert(0 == memcmp(base, candidate, matched));
|
580
|
-
if (
|
570
|
+
if (BROTLI_PREDICT_TRUE(insert < 6210)) {
|
581
571
|
EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,
|
582
572
|
storage_ix, storage);
|
583
573
|
} else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert,
|
@@ -606,14 +596,14 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
606
596
|
storage_ix, storage);
|
607
597
|
|
608
598
|
next_emit = ip;
|
609
|
-
if (
|
599
|
+
if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {
|
610
600
|
goto emit_remainder;
|
611
601
|
}
|
612
602
|
/* We could immediately start working at ip now, but to improve
|
613
603
|
compression we first update "table" with the hashes of some positions
|
614
604
|
within the last copy. */
|
615
605
|
{
|
616
|
-
uint64_t input_bytes =
|
606
|
+
uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);
|
617
607
|
uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);
|
618
608
|
uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift);
|
619
609
|
table[prev_hash] = (int)(ip - base_ip - 3);
|
@@ -633,6 +623,7 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
633
623
|
const uint8_t* base = ip;
|
634
624
|
size_t matched = 5 + FindMatchLengthWithLimit(
|
635
625
|
candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5);
|
626
|
+
if (ip - candidate > MAX_DISTANCE) break;
|
636
627
|
ip += matched;
|
637
628
|
last_distance = (int)(base - candidate); /* > 0 */
|
638
629
|
assert(0 == memcmp(base, candidate, matched));
|
@@ -642,14 +633,14 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
642
633
|
cmd_histo, storage_ix, storage);
|
643
634
|
|
644
635
|
next_emit = ip;
|
645
|
-
if (
|
636
|
+
if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {
|
646
637
|
goto emit_remainder;
|
647
638
|
}
|
648
639
|
/* We could immediately start working at ip now, but to improve
|
649
640
|
compression we first update "table" with the hashes of some positions
|
650
641
|
within the last copy. */
|
651
642
|
{
|
652
|
-
uint64_t input_bytes =
|
643
|
+
uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);
|
653
644
|
uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);
|
654
645
|
uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift);
|
655
646
|
table[prev_hash] = (int)(ip - base_ip - 3);
|
@@ -690,7 +681,7 @@ void BrotliCompressFragmentFast(MemoryManager* m,
|
|
690
681
|
/* Emit the remaining bytes as literals. */
|
691
682
|
if (next_emit < ip_end) {
|
692
683
|
const size_t insert = (size_t)(ip_end - next_emit);
|
693
|
-
if (
|
684
|
+
if (BROTLI_PREDICT_TRUE(insert < 6210)) {
|
694
685
|
EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,
|
695
686
|
storage_ix, storage);
|
696
687
|
EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage);
|
@@ -728,11 +719,7 @@ next_block:
|
|
728
719
|
goto emit_commands;
|
729
720
|
}
|
730
721
|
|
731
|
-
if (is_last) {
|
732
|
-
BrotliWriteBits(1, 1, storage_ix, storage); /* islast */
|
733
|
-
BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */
|
734
|
-
*storage_ix = (*storage_ix + 7u) & ~7u;
|
735
|
-
} else {
|
722
|
+
if (!is_last) {
|
736
723
|
/* If this is not the last block, update the command and distance prefix
|
737
724
|
codes for the next block and store the compressed forms. */
|
738
725
|
cmd_code[0] = 0;
|
@@ -742,6 +729,63 @@ next_block:
|
|
742
729
|
}
|
743
730
|
}
|
744
731
|
|
732
|
+
#define FOR_TABLE_BITS_(X) X(9) X(11) X(13) X(15)
|
733
|
+
|
734
|
+
#define BAKE_METHOD_PARAM_(B) \
|
735
|
+
static BROTLI_NOINLINE void BrotliCompressFragmentFastImpl ## B( \
|
736
|
+
MemoryManager* m, const uint8_t* input, size_t input_size, \
|
737
|
+
BROTLI_BOOL is_last, int* table, uint8_t cmd_depth[128], \
|
738
|
+
uint16_t cmd_bits[128], size_t* cmd_code_numbits, uint8_t* cmd_code, \
|
739
|
+
size_t* storage_ix, uint8_t* storage) { \
|
740
|
+
BrotliCompressFragmentFastImpl(m, input, input_size, is_last, table, B, \
|
741
|
+
cmd_depth, cmd_bits, cmd_code_numbits, cmd_code, storage_ix, storage); \
|
742
|
+
}
|
743
|
+
FOR_TABLE_BITS_(BAKE_METHOD_PARAM_)
|
744
|
+
#undef BAKE_METHOD_PARAM_
|
745
|
+
|
746
|
+
void BrotliCompressFragmentFast(
|
747
|
+
MemoryManager* m, const uint8_t* input, size_t input_size,
|
748
|
+
BROTLI_BOOL is_last, int* table, size_t table_size, uint8_t cmd_depth[128],
|
749
|
+
uint16_t cmd_bits[128], size_t* cmd_code_numbits, uint8_t* cmd_code,
|
750
|
+
size_t* storage_ix, uint8_t* storage) {
|
751
|
+
const size_t initial_storage_ix = *storage_ix;
|
752
|
+
const size_t table_bits = Log2FloorNonZero(table_size);
|
753
|
+
|
754
|
+
if (input_size == 0) {
|
755
|
+
assert(is_last);
|
756
|
+
BrotliWriteBits(1, 1, storage_ix, storage); /* islast */
|
757
|
+
BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */
|
758
|
+
*storage_ix = (*storage_ix + 7u) & ~7u;
|
759
|
+
return;
|
760
|
+
}
|
761
|
+
|
762
|
+
switch (table_bits) {
|
763
|
+
#define CASE_(B) \
|
764
|
+
case B: \
|
765
|
+
BrotliCompressFragmentFastImpl ## B( \
|
766
|
+
m, input, input_size, is_last, table, cmd_depth, cmd_bits, \
|
767
|
+
cmd_code_numbits, cmd_code, storage_ix, storage); \
|
768
|
+
break;
|
769
|
+
FOR_TABLE_BITS_(CASE_)
|
770
|
+
#undef CASE_
|
771
|
+
default: assert(0); break;
|
772
|
+
}
|
773
|
+
|
774
|
+
/* If output is larger than single uncompressed block, rewrite it. */
|
775
|
+
if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) {
|
776
|
+
EmitUncompressedMetaBlock(input, input + input_size, initial_storage_ix,
|
777
|
+
storage_ix, storage);
|
778
|
+
}
|
779
|
+
|
780
|
+
if (is_last) {
|
781
|
+
BrotliWriteBits(1, 1, storage_ix, storage); /* islast */
|
782
|
+
BrotliWriteBits(1, 1, storage_ix, storage); /* isempty */
|
783
|
+
*storage_ix = (*storage_ix + 7u) & ~7u;
|
784
|
+
}
|
785
|
+
}
|
786
|
+
|
787
|
+
#undef FOR_TABLE_BITS_
|
788
|
+
|
745
789
|
#if defined(__cplusplus) || defined(c_plusplus)
|
746
790
|
} /* extern "C" */
|
747
791
|
#endif
|