brotli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/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
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_
|
|
14
14
|
#define BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_
|
|
15
15
|
|
|
16
|
+
#include "../common/platform.h"
|
|
16
17
|
#include <brotli/types.h>
|
|
17
18
|
#include "./memory.h"
|
|
18
|
-
#include "./port.h"
|
|
19
19
|
|
|
20
20
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
21
21
|
extern "C" {
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
#include <stdlib.h> /* free, malloc */
|
|
12
12
|
#include <string.h> /* memcpy, memset */
|
|
13
13
|
|
|
14
|
+
#include "../common/constants.h"
|
|
15
|
+
#include "../common/context.h"
|
|
16
|
+
#include "../common/platform.h"
|
|
14
17
|
#include "../common/version.h"
|
|
15
18
|
#include "./backward_references.h"
|
|
16
19
|
#include "./backward_references_hq.h"
|
|
@@ -18,14 +21,13 @@
|
|
|
18
21
|
#include "./brotli_bit_stream.h"
|
|
19
22
|
#include "./compress_fragment.h"
|
|
20
23
|
#include "./compress_fragment_two_pass.h"
|
|
21
|
-
#include "./
|
|
24
|
+
#include "./encoder_dict.h"
|
|
22
25
|
#include "./entropy_encode.h"
|
|
23
26
|
#include "./fast_log.h"
|
|
24
27
|
#include "./hash.h"
|
|
25
28
|
#include "./histogram.h"
|
|
26
29
|
#include "./memory.h"
|
|
27
30
|
#include "./metablock.h"
|
|
28
|
-
#include "./port.h"
|
|
29
31
|
#include "./prefix.h"
|
|
30
32
|
#include "./quality.h"
|
|
31
33
|
#include "./ringbuffer.h"
|
|
@@ -69,8 +71,8 @@ typedef struct BrotliEncoderStateStruct {
|
|
|
69
71
|
uint64_t last_processed_pos_;
|
|
70
72
|
int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES];
|
|
71
73
|
int saved_dist_cache_[4];
|
|
72
|
-
|
|
73
|
-
uint8_t
|
|
74
|
+
uint16_t last_bytes_;
|
|
75
|
+
uint8_t last_bytes_bits_;
|
|
74
76
|
uint8_t prev_byte_;
|
|
75
77
|
uint8_t prev_byte2_;
|
|
76
78
|
size_t storage_size_;
|
|
@@ -115,7 +117,6 @@ typedef struct BrotliEncoderStateStruct {
|
|
|
115
117
|
static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s);
|
|
116
118
|
|
|
117
119
|
static size_t InputBlockSize(BrotliEncoderState* s) {
|
|
118
|
-
if (!EnsureInitialized(s)) return 0;
|
|
119
120
|
return (size_t)1 << s->params.lgblock;
|
|
120
121
|
}
|
|
121
122
|
|
|
@@ -161,27 +162,19 @@ BROTLI_BOOL BrotliEncoderSetParameter(
|
|
|
161
162
|
state->params.size_hint = value;
|
|
162
163
|
return BROTLI_TRUE;
|
|
163
164
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
case BROTLI_PARAM_LARGE_WINDOW:
|
|
166
|
+
state->params.large_window = TO_BROTLI_BOOL(!!value);
|
|
167
|
+
return BROTLI_TRUE;
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
Command* cmd = &cmds[i];
|
|
178
|
-
if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {
|
|
179
|
-
PrefixEncodeCopyDistance(CommandRestoreDistanceCode(cmd),
|
|
180
|
-
num_direct_distance_codes,
|
|
181
|
-
distance_postfix_bits,
|
|
182
|
-
&cmd->dist_prefix_,
|
|
183
|
-
&cmd->dist_extra_);
|
|
184
|
-
}
|
|
169
|
+
case BROTLI_PARAM_NPOSTFIX:
|
|
170
|
+
state->params.dist.distance_postfix_bits = value;
|
|
171
|
+
return BROTLI_TRUE;
|
|
172
|
+
|
|
173
|
+
case BROTLI_PARAM_NDIRECT:
|
|
174
|
+
state->params.dist.num_direct_distance_codes = value;
|
|
175
|
+
return BROTLI_TRUE;
|
|
176
|
+
|
|
177
|
+
default: return BROTLI_FALSE;
|
|
185
178
|
}
|
|
186
179
|
}
|
|
187
180
|
|
|
@@ -226,7 +219,7 @@ static int* GetHashTable(BrotliEncoderState* s, int quality,
|
|
|
226
219
|
const size_t max_table_size = MaxHashTableSize(quality);
|
|
227
220
|
size_t htsize = HashTableSize(max_table_size, input_size);
|
|
228
221
|
int* table;
|
|
229
|
-
|
|
222
|
+
BROTLI_DCHECK(max_table_size >= 256);
|
|
230
223
|
if (quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
|
|
231
224
|
/* Only odd shifts are supported by fast-one-pass. */
|
|
232
225
|
if ((htsize & 0xAAAAA) == 0) {
|
|
@@ -251,20 +244,25 @@ static int* GetHashTable(BrotliEncoderState* s, int quality,
|
|
|
251
244
|
return table;
|
|
252
245
|
}
|
|
253
246
|
|
|
254
|
-
static void EncodeWindowBits(int lgwin,
|
|
255
|
-
uint8_t*
|
|
256
|
-
if (
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
} else if (lgwin == 17) {
|
|
260
|
-
*last_byte = 1;
|
|
261
|
-
*last_byte_bits = 7;
|
|
262
|
-
} else if (lgwin > 17) {
|
|
263
|
-
*last_byte = (uint8_t)(((lgwin - 17) << 1) | 1);
|
|
264
|
-
*last_byte_bits = 4;
|
|
247
|
+
static void EncodeWindowBits(int lgwin, BROTLI_BOOL large_window,
|
|
248
|
+
uint16_t* last_bytes, uint8_t* last_bytes_bits) {
|
|
249
|
+
if (large_window) {
|
|
250
|
+
*last_bytes = (uint16_t)(((lgwin & 0x3F) << 8) | 0x11);
|
|
251
|
+
*last_bytes_bits = 14;
|
|
265
252
|
} else {
|
|
266
|
-
|
|
267
|
-
|
|
253
|
+
if (lgwin == 16) {
|
|
254
|
+
*last_bytes = 0;
|
|
255
|
+
*last_bytes_bits = 1;
|
|
256
|
+
} else if (lgwin == 17) {
|
|
257
|
+
*last_bytes = 1;
|
|
258
|
+
*last_bytes_bits = 7;
|
|
259
|
+
} else if (lgwin > 17) {
|
|
260
|
+
*last_bytes = (uint16_t)(((lgwin - 17) << 1) | 0x01);
|
|
261
|
+
*last_bytes_bits = 4;
|
|
262
|
+
} else {
|
|
263
|
+
*last_bytes = (uint16_t)(((lgwin - 8) << 4) | 0x01);
|
|
264
|
+
*last_bytes_bits = 7;
|
|
265
|
+
}
|
|
268
266
|
}
|
|
269
267
|
}
|
|
270
268
|
|
|
@@ -357,7 +355,7 @@ static void ChooseContextMap(int quality,
|
|
|
357
355
|
}
|
|
358
356
|
|
|
359
357
|
total = monogram_histo[0] + monogram_histo[1] + monogram_histo[2];
|
|
360
|
-
|
|
358
|
+
BROTLI_DCHECK(total != 0);
|
|
361
359
|
entropy[0] = 1.0 / (double)total;
|
|
362
360
|
entropy[1] *= entropy[0];
|
|
363
361
|
entropy[2] *= entropy[0];
|
|
@@ -420,6 +418,7 @@ static BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input,
|
|
|
420
418
|
double entropy[3];
|
|
421
419
|
size_t dummy;
|
|
422
420
|
size_t i;
|
|
421
|
+
ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8);
|
|
423
422
|
for (; start_pos + 64 <= end_pos; start_pos += 4096) {
|
|
424
423
|
const size_t stride_end_pos = start_pos + 64;
|
|
425
424
|
uint8_t prev2 = input[start_pos & mask];
|
|
@@ -430,7 +429,7 @@ static BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input,
|
|
|
430
429
|
for (pos = start_pos + 2; pos < stride_end_pos; ++pos) {
|
|
431
430
|
const uint8_t literal = input[pos & mask];
|
|
432
431
|
const uint8_t context = (uint8_t)kStaticContextMapComplexUTF8[
|
|
433
|
-
|
|
432
|
+
BROTLI_CONTEXT(prev1, prev2, utf8_lut)];
|
|
434
433
|
++total;
|
|
435
434
|
++combined_histo[literal >> 3];
|
|
436
435
|
++context_histo[context][literal >> 3];
|
|
@@ -519,12 +518,26 @@ static BROTLI_BOOL ShouldCompress(
|
|
|
519
518
|
return BROTLI_TRUE;
|
|
520
519
|
}
|
|
521
520
|
|
|
521
|
+
/* Chooses the literal context mode for a metablock */
|
|
522
|
+
static ContextType ChooseContextMode(const BrotliEncoderParams* params,
|
|
523
|
+
const uint8_t* data, const size_t pos, const size_t mask,
|
|
524
|
+
const size_t length) {
|
|
525
|
+
/* We only do the computation for the option of something else than
|
|
526
|
+
CONTEXT_UTF8 for the highest qualities */
|
|
527
|
+
if (params->quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING &&
|
|
528
|
+
!BrotliIsMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio)) {
|
|
529
|
+
return CONTEXT_SIGNED;
|
|
530
|
+
}
|
|
531
|
+
return CONTEXT_UTF8;
|
|
532
|
+
}
|
|
533
|
+
|
|
522
534
|
static void WriteMetaBlockInternal(MemoryManager* m,
|
|
523
535
|
const uint8_t* data,
|
|
524
536
|
const size_t mask,
|
|
525
537
|
const uint64_t last_flush_pos,
|
|
526
538
|
const size_t bytes,
|
|
527
539
|
const BROTLI_BOOL is_last,
|
|
540
|
+
ContextType literal_context_mode,
|
|
528
541
|
const BrotliEncoderParams* params,
|
|
529
542
|
const uint8_t prev_byte,
|
|
530
543
|
const uint8_t prev_byte2,
|
|
@@ -536,10 +549,10 @@ static void WriteMetaBlockInternal(MemoryManager* m,
|
|
|
536
549
|
size_t* storage_ix,
|
|
537
550
|
uint8_t* storage) {
|
|
538
551
|
const uint32_t wrapped_last_flush_pos = WrapPosition(last_flush_pos);
|
|
539
|
-
|
|
540
|
-
uint8_t
|
|
541
|
-
|
|
542
|
-
|
|
552
|
+
uint16_t last_bytes;
|
|
553
|
+
uint8_t last_bytes_bits;
|
|
554
|
+
ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
|
|
555
|
+
BrotliEncoderParams block_params = *params;
|
|
543
556
|
|
|
544
557
|
if (bytes == 0) {
|
|
545
558
|
/* Write the ISLAST and ISEMPTY bits. */
|
|
@@ -559,31 +572,22 @@ static void WriteMetaBlockInternal(MemoryManager* m,
|
|
|
559
572
|
return;
|
|
560
573
|
}
|
|
561
574
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
params->mode == BROTLI_MODE_FONT) {
|
|
566
|
-
num_direct_distance_codes = 12;
|
|
567
|
-
distance_postfix_bits = 1;
|
|
568
|
-
RecomputeDistancePrefixes(commands,
|
|
569
|
-
num_commands,
|
|
570
|
-
num_direct_distance_codes,
|
|
571
|
-
distance_postfix_bits);
|
|
572
|
-
}
|
|
575
|
+
BROTLI_DCHECK(*storage_ix <= 14);
|
|
576
|
+
last_bytes = (uint16_t)((storage[1] << 8) | storage[0]);
|
|
577
|
+
last_bytes_bits = (uint8_t)(*storage_ix);
|
|
573
578
|
if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) {
|
|
574
579
|
BrotliStoreMetaBlockFast(m, data, wrapped_last_flush_pos,
|
|
575
|
-
bytes, mask, is_last,
|
|
580
|
+
bytes, mask, is_last, params,
|
|
576
581
|
commands, num_commands,
|
|
577
582
|
storage_ix, storage);
|
|
578
583
|
if (BROTLI_IS_OOM(m)) return;
|
|
579
584
|
} else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {
|
|
580
585
|
BrotliStoreMetaBlockTrivial(m, data, wrapped_last_flush_pos,
|
|
581
|
-
bytes, mask, is_last,
|
|
586
|
+
bytes, mask, is_last, params,
|
|
582
587
|
commands, num_commands,
|
|
583
588
|
storage_ix, storage);
|
|
584
589
|
if (BROTLI_IS_OOM(m)) return;
|
|
585
590
|
} else {
|
|
586
|
-
ContextType literal_context_mode = CONTEXT_UTF8;
|
|
587
591
|
MetaBlockSplit mb;
|
|
588
592
|
InitMetaBlockSplit(&mb);
|
|
589
593
|
if (params->quality < MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {
|
|
@@ -596,15 +600,11 @@ static void WriteMetaBlockInternal(MemoryManager* m,
|
|
|
596
600
|
&literal_context_map);
|
|
597
601
|
}
|
|
598
602
|
BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask,
|
|
599
|
-
prev_byte, prev_byte2,
|
|
603
|
+
prev_byte, prev_byte2, literal_context_lut, num_literal_contexts,
|
|
600
604
|
literal_context_map, commands, num_commands, &mb);
|
|
601
605
|
if (BROTLI_IS_OOM(m)) return;
|
|
602
606
|
} else {
|
|
603
|
-
|
|
604
|
-
kMinUTF8Ratio)) {
|
|
605
|
-
literal_context_mode = CONTEXT_SIGNED;
|
|
606
|
-
}
|
|
607
|
-
BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, params,
|
|
607
|
+
BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params,
|
|
608
608
|
prev_byte, prev_byte2,
|
|
609
609
|
commands, num_commands,
|
|
610
610
|
literal_context_mode,
|
|
@@ -612,15 +612,19 @@ static void WriteMetaBlockInternal(MemoryManager* m,
|
|
|
612
612
|
if (BROTLI_IS_OOM(m)) return;
|
|
613
613
|
}
|
|
614
614
|
if (params->quality >= MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS) {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
615
|
+
/* The number of distance symbols effectively used for distance
|
|
616
|
+
histograms. It might be less than distance alphabet size
|
|
617
|
+
for "Large Window Brotli" (32-bit). */
|
|
618
|
+
uint32_t num_effective_dist_codes = block_params.dist.alphabet_size;
|
|
619
|
+
if (num_effective_dist_codes > BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS) {
|
|
620
|
+
num_effective_dist_codes = BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS;
|
|
621
|
+
}
|
|
622
|
+
BrotliOptimizeHistograms(num_effective_dist_codes, &mb);
|
|
618
623
|
}
|
|
619
624
|
BrotliStoreMetaBlock(m, data, wrapped_last_flush_pos, bytes, mask,
|
|
620
625
|
prev_byte, prev_byte2,
|
|
621
626
|
is_last,
|
|
622
|
-
|
|
623
|
-
distance_postfix_bits,
|
|
627
|
+
&block_params,
|
|
624
628
|
literal_context_mode,
|
|
625
629
|
commands, num_commands,
|
|
626
630
|
&mb,
|
|
@@ -631,20 +635,48 @@ static void WriteMetaBlockInternal(MemoryManager* m,
|
|
|
631
635
|
if (bytes + 4 < (*storage_ix >> 3)) {
|
|
632
636
|
/* Restore the distance cache and last byte. */
|
|
633
637
|
memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
|
|
634
|
-
storage[0] =
|
|
635
|
-
|
|
638
|
+
storage[0] = (uint8_t)last_bytes;
|
|
639
|
+
storage[1] = (uint8_t)(last_bytes >> 8);
|
|
640
|
+
*storage_ix = last_bytes_bits;
|
|
636
641
|
BrotliStoreUncompressedMetaBlock(is_last, data,
|
|
637
642
|
wrapped_last_flush_pos, mask,
|
|
638
643
|
bytes, storage_ix, storage);
|
|
639
644
|
}
|
|
640
645
|
}
|
|
641
646
|
|
|
647
|
+
static void ChooseDistanceParams(BrotliEncoderParams* params) {
|
|
648
|
+
uint32_t distance_postfix_bits = 0;
|
|
649
|
+
uint32_t num_direct_distance_codes = 0;
|
|
650
|
+
|
|
651
|
+
if (params->quality >= MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS) {
|
|
652
|
+
uint32_t ndirect_msb;
|
|
653
|
+
if (params->mode == BROTLI_MODE_FONT) {
|
|
654
|
+
distance_postfix_bits = 1;
|
|
655
|
+
num_direct_distance_codes = 12;
|
|
656
|
+
} else {
|
|
657
|
+
distance_postfix_bits = params->dist.distance_postfix_bits;
|
|
658
|
+
num_direct_distance_codes = params->dist.num_direct_distance_codes;
|
|
659
|
+
}
|
|
660
|
+
ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F;
|
|
661
|
+
if (distance_postfix_bits > BROTLI_MAX_NPOSTFIX ||
|
|
662
|
+
num_direct_distance_codes > BROTLI_MAX_NDIRECT ||
|
|
663
|
+
(ndirect_msb << distance_postfix_bits) != num_direct_distance_codes) {
|
|
664
|
+
distance_postfix_bits = 0;
|
|
665
|
+
num_direct_distance_codes = 0;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
BrotliInitDistanceParams(
|
|
670
|
+
params, distance_postfix_bits, num_direct_distance_codes);
|
|
671
|
+
}
|
|
672
|
+
|
|
642
673
|
static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {
|
|
643
674
|
if (BROTLI_IS_OOM(&s->memory_manager_)) return BROTLI_FALSE;
|
|
644
675
|
if (s->is_initialized_) return BROTLI_TRUE;
|
|
645
676
|
|
|
646
677
|
SanitizeParams(&s->params);
|
|
647
678
|
s->params.lgblock = ComputeLgBlock(&s->params);
|
|
679
|
+
ChooseDistanceParams(&s->params);
|
|
648
680
|
|
|
649
681
|
s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;
|
|
650
682
|
|
|
@@ -657,7 +689,8 @@ static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {
|
|
|
657
689
|
s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
|
|
658
690
|
lgwin = BROTLI_MAX(int, lgwin, 18);
|
|
659
691
|
}
|
|
660
|
-
EncodeWindowBits(lgwin,
|
|
692
|
+
EncodeWindowBits(lgwin, s->params.large_window,
|
|
693
|
+
&s->last_bytes_, &s->last_bytes_bits_);
|
|
661
694
|
}
|
|
662
695
|
|
|
663
696
|
if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
|
|
@@ -671,11 +704,18 @@ static BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {
|
|
|
671
704
|
|
|
672
705
|
static void BrotliEncoderInitParams(BrotliEncoderParams* params) {
|
|
673
706
|
params->mode = BROTLI_DEFAULT_MODE;
|
|
707
|
+
params->large_window = BROTLI_FALSE;
|
|
674
708
|
params->quality = BROTLI_DEFAULT_QUALITY;
|
|
675
709
|
params->lgwin = BROTLI_DEFAULT_WINDOW;
|
|
676
710
|
params->lgblock = 0;
|
|
677
711
|
params->size_hint = 0;
|
|
678
712
|
params->disable_literal_context_modeling = BROTLI_FALSE;
|
|
713
|
+
BrotliInitEncoderDictionary(¶ms->dictionary);
|
|
714
|
+
params->dist.distance_postfix_bits = 0;
|
|
715
|
+
params->dist.num_direct_distance_codes = 0;
|
|
716
|
+
params->dist.alphabet_size =
|
|
717
|
+
BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_MAX_DISTANCE_BITS);
|
|
718
|
+
params->dist.max_distance = BROTLI_MAX_DISTANCE;
|
|
679
719
|
}
|
|
680
720
|
|
|
681
721
|
static void BrotliEncoderInitState(BrotliEncoderState* s) {
|
|
@@ -718,9 +758,8 @@ static void BrotliEncoderInitState(BrotliEncoderState* s) {
|
|
|
718
758
|
memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));
|
|
719
759
|
}
|
|
720
760
|
|
|
721
|
-
BrotliEncoderState* BrotliEncoderCreateInstance(
|
|
722
|
-
|
|
723
|
-
void* opaque) {
|
|
761
|
+
BrotliEncoderState* BrotliEncoderCreateInstance(
|
|
762
|
+
brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
|
|
724
763
|
BrotliEncoderState* state = 0;
|
|
725
764
|
if (!alloc_func && !free_func) {
|
|
726
765
|
state = (BrotliEncoderState*)malloc(sizeof(BrotliEncoderState));
|
|
@@ -777,7 +816,6 @@ static void CopyInputToRingBuffer(BrotliEncoderState* s,
|
|
|
777
816
|
const uint8_t* input_buffer) {
|
|
778
817
|
RingBuffer* ringbuffer_ = &s->ringbuffer_;
|
|
779
818
|
MemoryManager* m = &s->memory_manager_;
|
|
780
|
-
if (!EnsureInitialized(s)) return;
|
|
781
819
|
RingBufferWrite(m, input_buffer, input_size, ringbuffer_);
|
|
782
820
|
if (BROTLI_IS_OOM(m)) return;
|
|
783
821
|
s->input_pos_ += input_size;
|
|
@@ -837,6 +875,39 @@ static BROTLI_BOOL UpdateLastProcessedPos(BrotliEncoderState* s) {
|
|
|
837
875
|
return TO_BROTLI_BOOL(wrapped_input_pos < wrapped_last_processed_pos);
|
|
838
876
|
}
|
|
839
877
|
|
|
878
|
+
static void ExtendLastCommand(BrotliEncoderState* s, uint32_t* bytes,
|
|
879
|
+
uint32_t* wrapped_last_processed_pos) {
|
|
880
|
+
Command* last_command = &s->commands_[s->num_commands_ - 1];
|
|
881
|
+
const uint8_t* data = s->ringbuffer_.buffer_;
|
|
882
|
+
const uint32_t mask = s->ringbuffer_.mask_;
|
|
883
|
+
uint64_t max_backward_distance =
|
|
884
|
+
(((uint64_t)1) << s->params.lgwin) - BROTLI_WINDOW_GAP;
|
|
885
|
+
uint64_t last_copy_len = last_command->copy_len_ & 0x1FFFFFF;
|
|
886
|
+
uint64_t last_processed_pos = s->last_processed_pos_ - last_copy_len;
|
|
887
|
+
uint64_t max_distance = last_processed_pos < max_backward_distance ?
|
|
888
|
+
last_processed_pos : max_backward_distance;
|
|
889
|
+
uint64_t cmd_dist = (uint64_t)s->dist_cache_[0];
|
|
890
|
+
uint32_t distance_code = CommandRestoreDistanceCode(last_command,
|
|
891
|
+
&s->params.dist);
|
|
892
|
+
if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES ||
|
|
893
|
+
distance_code - (BROTLI_NUM_DISTANCE_SHORT_CODES - 1) == cmd_dist) {
|
|
894
|
+
if (cmd_dist <= max_distance) {
|
|
895
|
+
while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==
|
|
896
|
+
data[(*wrapped_last_processed_pos - cmd_dist) & mask]) {
|
|
897
|
+
last_command->copy_len_++;
|
|
898
|
+
(*bytes)--;
|
|
899
|
+
(*wrapped_last_processed_pos)++;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
/* The copy length is at most the metablock size, and thus expressible. */
|
|
903
|
+
GetLengthCode(last_command->insert_len_,
|
|
904
|
+
(size_t)((int)(last_command->copy_len_ & 0x1FFFFFF) +
|
|
905
|
+
(int)(last_command->copy_len_ >> 25)),
|
|
906
|
+
TO_BROTLI_BOOL((last_command->dist_prefix_ & 0x3FF) == 0),
|
|
907
|
+
&last_command->cmd_prefix_);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
840
911
|
/*
|
|
841
912
|
Processes the accumulated input data and sets |*out_size| to the length of
|
|
842
913
|
the new output meta-block, or to zero if no new output meta-block has been
|
|
@@ -853,15 +924,13 @@ static BROTLI_BOOL EncodeData(
|
|
|
853
924
|
BrotliEncoderState* s, const BROTLI_BOOL is_last,
|
|
854
925
|
const BROTLI_BOOL force_flush, size_t* out_size, uint8_t** output) {
|
|
855
926
|
const uint64_t delta = UnprocessedInputSize(s);
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
WrapPosition(s->last_processed_pos_);
|
|
927
|
+
uint32_t bytes = (uint32_t)delta;
|
|
928
|
+
uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);
|
|
859
929
|
uint8_t* data;
|
|
860
930
|
uint32_t mask;
|
|
861
931
|
MemoryManager* m = &s->memory_manager_;
|
|
862
|
-
|
|
932
|
+
ContextType literal_context_mode;
|
|
863
933
|
|
|
864
|
-
if (!EnsureInitialized(s)) return BROTLI_FALSE;
|
|
865
934
|
data = s->ringbuffer_.buffer_;
|
|
866
935
|
mask = s->ringbuffer_.mask_;
|
|
867
936
|
|
|
@@ -884,7 +953,7 @@ static BROTLI_BOOL EncodeData(
|
|
|
884
953
|
if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||
|
|
885
954
|
s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
|
|
886
955
|
uint8_t* storage;
|
|
887
|
-
size_t storage_ix = s->
|
|
956
|
+
size_t storage_ix = s->last_bytes_bits_;
|
|
888
957
|
size_t table_size;
|
|
889
958
|
int* table;
|
|
890
959
|
|
|
@@ -894,9 +963,10 @@ static BROTLI_BOOL EncodeData(
|
|
|
894
963
|
*out_size = 0;
|
|
895
964
|
return BROTLI_TRUE;
|
|
896
965
|
}
|
|
897
|
-
storage = GetBrotliStorage(s, 2 * bytes +
|
|
966
|
+
storage = GetBrotliStorage(s, 2 * bytes + 503);
|
|
898
967
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
899
|
-
storage[0] = s->
|
|
968
|
+
storage[0] = (uint8_t)s->last_bytes_;
|
|
969
|
+
storage[1] = (uint8_t)(s->last_bytes_ >> 8);
|
|
900
970
|
table = GetHashTable(s, s->params.quality, bytes, &table_size);
|
|
901
971
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
902
972
|
if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {
|
|
@@ -917,8 +987,8 @@ static BROTLI_BOOL EncodeData(
|
|
|
917
987
|
&storage_ix, storage);
|
|
918
988
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
919
989
|
}
|
|
920
|
-
s->
|
|
921
|
-
s->
|
|
990
|
+
s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
|
|
991
|
+
s->last_bytes_bits_ = storage_ix & 7u;
|
|
922
992
|
UpdateLastProcessedPos(s);
|
|
923
993
|
*output = &storage[0];
|
|
924
994
|
*out_size = storage_ix >> 3;
|
|
@@ -946,27 +1016,39 @@ static BROTLI_BOOL EncodeData(
|
|
|
946
1016
|
|
|
947
1017
|
InitOrStitchToPreviousBlock(m, &s->hasher_, data, mask, &s->params,
|
|
948
1018
|
wrapped_last_processed_pos, bytes, is_last);
|
|
1019
|
+
|
|
1020
|
+
literal_context_mode = ChooseContextMode(
|
|
1021
|
+
&s->params, data, WrapPosition(s->last_flush_pos_),
|
|
1022
|
+
mask, (size_t)(s->input_pos_ - s->last_flush_pos_));
|
|
1023
|
+
|
|
949
1024
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
950
1025
|
|
|
1026
|
+
if (s->num_commands_ && s->last_insert_len_ == 0) {
|
|
1027
|
+
ExtendLastCommand(s, &bytes, &wrapped_last_processed_pos);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
951
1030
|
if (s->params.quality == ZOPFLIFICATION_QUALITY) {
|
|
952
|
-
|
|
953
|
-
BrotliCreateZopfliBackwardReferences(
|
|
954
|
-
|
|
955
|
-
&s->params, s->hasher_, s->dist_cache_,
|
|
956
|
-
&s->commands_[s->num_commands_],
|
|
1031
|
+
BROTLI_DCHECK(s->params.hasher.type == 10);
|
|
1032
|
+
BrotliCreateZopfliBackwardReferences(m,
|
|
1033
|
+
bytes, wrapped_last_processed_pos,
|
|
1034
|
+
data, mask, &s->params, s->hasher_, s->dist_cache_,
|
|
1035
|
+
&s->last_insert_len_, &s->commands_[s->num_commands_],
|
|
1036
|
+
&s->num_commands_, &s->num_literals_);
|
|
957
1037
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
958
1038
|
} else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) {
|
|
959
|
-
|
|
960
|
-
BrotliCreateHqZopfliBackwardReferences(
|
|
961
|
-
|
|
962
|
-
&s->params, s->hasher_, s->dist_cache_,
|
|
963
|
-
&s->commands_[s->num_commands_],
|
|
1039
|
+
BROTLI_DCHECK(s->params.hasher.type == 10);
|
|
1040
|
+
BrotliCreateHqZopfliBackwardReferences(m,
|
|
1041
|
+
bytes, wrapped_last_processed_pos,
|
|
1042
|
+
data, mask, &s->params, s->hasher_, s->dist_cache_,
|
|
1043
|
+
&s->last_insert_len_, &s->commands_[s->num_commands_],
|
|
1044
|
+
&s->num_commands_, &s->num_literals_);
|
|
964
1045
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
965
1046
|
} else {
|
|
966
1047
|
BrotliCreateBackwardReferences(
|
|
967
|
-
|
|
968
|
-
&s->params, s->hasher_, s->dist_cache_,
|
|
969
|
-
&s->commands_[s->num_commands_],
|
|
1048
|
+
bytes, wrapped_last_processed_pos,
|
|
1049
|
+
data, mask, &s->params, s->hasher_, s->dist_cache_,
|
|
1050
|
+
&s->last_insert_len_, &s->commands_[s->num_commands_],
|
|
1051
|
+
&s->num_commands_, &s->num_literals_);
|
|
970
1052
|
}
|
|
971
1053
|
|
|
972
1054
|
{
|
|
@@ -1009,24 +1091,25 @@ static BROTLI_BOOL EncodeData(
|
|
|
1009
1091
|
*out_size = 0;
|
|
1010
1092
|
return BROTLI_TRUE;
|
|
1011
1093
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1094
|
+
BROTLI_DCHECK(s->input_pos_ >= s->last_flush_pos_);
|
|
1095
|
+
BROTLI_DCHECK(s->input_pos_ > s->last_flush_pos_ || is_last);
|
|
1096
|
+
BROTLI_DCHECK(s->input_pos_ - s->last_flush_pos_ <= 1u << 24);
|
|
1015
1097
|
{
|
|
1016
1098
|
const uint32_t metablock_size =
|
|
1017
1099
|
(uint32_t)(s->input_pos_ - s->last_flush_pos_);
|
|
1018
|
-
uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size +
|
|
1019
|
-
size_t storage_ix = s->
|
|
1100
|
+
uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size + 503);
|
|
1101
|
+
size_t storage_ix = s->last_bytes_bits_;
|
|
1020
1102
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
1021
|
-
storage[0] = s->
|
|
1103
|
+
storage[0] = (uint8_t)s->last_bytes_;
|
|
1104
|
+
storage[1] = (uint8_t)(s->last_bytes_ >> 8);
|
|
1022
1105
|
WriteMetaBlockInternal(
|
|
1023
1106
|
m, data, mask, s->last_flush_pos_, metablock_size, is_last,
|
|
1024
|
-
&s->params, s->prev_byte_, s->prev_byte2_,
|
|
1107
|
+
literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_,
|
|
1025
1108
|
s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_,
|
|
1026
1109
|
s->dist_cache_, &storage_ix, storage);
|
|
1027
1110
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
1028
|
-
s->
|
|
1029
|
-
s->
|
|
1111
|
+
s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
|
|
1112
|
+
s->last_bytes_bits_ = storage_ix & 7u;
|
|
1030
1113
|
s->last_flush_pos_ = s->input_pos_;
|
|
1031
1114
|
if (UpdateLastProcessedPos(s)) {
|
|
1032
1115
|
HasherReset(s->hasher_);
|
|
@@ -1055,10 +1138,11 @@ static BROTLI_BOOL EncodeData(
|
|
|
1055
1138
|
static size_t WriteMetadataHeader(
|
|
1056
1139
|
BrotliEncoderState* s, const size_t block_size, uint8_t* header) {
|
|
1057
1140
|
size_t storage_ix;
|
|
1058
|
-
storage_ix = s->
|
|
1059
|
-
header[0] = s->
|
|
1060
|
-
s->
|
|
1061
|
-
s->
|
|
1141
|
+
storage_ix = s->last_bytes_bits_;
|
|
1142
|
+
header[0] = (uint8_t)s->last_bytes_;
|
|
1143
|
+
header[1] = (uint8_t)(s->last_bytes_ >> 8);
|
|
1144
|
+
s->last_bytes_ = 0;
|
|
1145
|
+
s->last_bytes_bits_ = 0;
|
|
1062
1146
|
|
|
1063
1147
|
BrotliWriteBits(1, 0, &storage_ix, header);
|
|
1064
1148
|
BrotliWriteBits(2, 3, &storage_ix, header);
|
|
@@ -1088,15 +1172,14 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1088
1172
|
BROTLI_BOOL ok = BROTLI_TRUE;
|
|
1089
1173
|
const size_t max_out_size = *encoded_size;
|
|
1090
1174
|
size_t total_out_size = 0;
|
|
1091
|
-
|
|
1092
|
-
uint8_t
|
|
1175
|
+
uint16_t last_bytes;
|
|
1176
|
+
uint8_t last_bytes_bits;
|
|
1093
1177
|
HasherHandle hasher = NULL;
|
|
1094
1178
|
|
|
1095
1179
|
const size_t hasher_eff_size =
|
|
1096
1180
|
BROTLI_MIN(size_t, input_size, max_backward_limit + BROTLI_WINDOW_GAP);
|
|
1097
1181
|
|
|
1098
1182
|
BrotliEncoderParams params;
|
|
1099
|
-
const BrotliDictionary* dictionary = BrotliGetDictionary();
|
|
1100
1183
|
|
|
1101
1184
|
const int lgmetablock = BROTLI_MIN(int, 24, lgwin + 1);
|
|
1102
1185
|
size_t max_block_size;
|
|
@@ -1110,14 +1193,18 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1110
1193
|
BrotliEncoderInitParams(¶ms);
|
|
1111
1194
|
params.quality = 10;
|
|
1112
1195
|
params.lgwin = lgwin;
|
|
1196
|
+
if (lgwin > BROTLI_MAX_WINDOW_BITS) {
|
|
1197
|
+
params.large_window = BROTLI_TRUE;
|
|
1198
|
+
}
|
|
1113
1199
|
SanitizeParams(¶ms);
|
|
1114
1200
|
params.lgblock = ComputeLgBlock(¶ms);
|
|
1201
|
+
ChooseDistanceParams(¶ms);
|
|
1115
1202
|
max_block_size = (size_t)1 << params.lgblock;
|
|
1116
1203
|
|
|
1117
1204
|
BrotliInitMemoryManager(m, 0, 0, 0);
|
|
1118
1205
|
|
|
1119
|
-
|
|
1120
|
-
EncodeWindowBits(lgwin, &
|
|
1206
|
+
BROTLI_DCHECK(input_size <= mask + 1);
|
|
1207
|
+
EncodeWindowBits(lgwin, params.large_window, &last_bytes, &last_bytes_bits);
|
|
1121
1208
|
InitOrStitchToPreviousBlock(m, &hasher, input_buffer, mask, ¶ms,
|
|
1122
1209
|
0, hasher_eff_size, BROTLI_TRUE);
|
|
1123
1210
|
if (BROTLI_IS_OOM(m)) goto oom;
|
|
@@ -1137,6 +1224,9 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1137
1224
|
uint8_t* storage;
|
|
1138
1225
|
size_t storage_ix;
|
|
1139
1226
|
|
|
1227
|
+
ContextType literal_context_mode = ChooseContextMode(¶ms,
|
|
1228
|
+
input_buffer, metablock_start, mask, metablock_end - metablock_start);
|
|
1229
|
+
|
|
1140
1230
|
size_t block_start;
|
|
1141
1231
|
for (block_start = metablock_start; block_start < metablock_end; ) {
|
|
1142
1232
|
size_t block_size =
|
|
@@ -1148,8 +1238,8 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1148
1238
|
BrotliInitZopfliNodes(nodes, block_size + 1);
|
|
1149
1239
|
StitchToPreviousBlockH10(hasher, block_size, block_start,
|
|
1150
1240
|
input_buffer, mask);
|
|
1151
|
-
path_size = BrotliZopfliComputeShortestPath(
|
|
1152
|
-
|
|
1241
|
+
path_size = BrotliZopfliComputeShortestPath(m,
|
|
1242
|
+
block_size, block_start, input_buffer, mask, ¶ms,
|
|
1153
1243
|
max_backward_limit, dist_cache, hasher, nodes);
|
|
1154
1244
|
if (BROTLI_IS_OOM(m)) goto oom;
|
|
1155
1245
|
/* We allocate a command buffer in the first iteration of this loop that
|
|
@@ -1193,13 +1283,14 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1193
1283
|
|
|
1194
1284
|
is_last = TO_BROTLI_BOOL(metablock_start + metablock_size == input_size);
|
|
1195
1285
|
storage = NULL;
|
|
1196
|
-
storage_ix =
|
|
1286
|
+
storage_ix = last_bytes_bits;
|
|
1197
1287
|
|
|
1198
1288
|
if (metablock_size == 0) {
|
|
1199
1289
|
/* Write the ISLAST and ISEMPTY bits. */
|
|
1200
1290
|
storage = BROTLI_ALLOC(m, uint8_t, 16);
|
|
1201
1291
|
if (BROTLI_IS_OOM(m)) goto oom;
|
|
1202
|
-
storage[0] =
|
|
1292
|
+
storage[0] = (uint8_t)last_bytes;
|
|
1293
|
+
storage[1] = (uint8_t)(last_bytes >> 8);
|
|
1203
1294
|
BrotliWriteBits(2, 3, &storage_ix, storage);
|
|
1204
1295
|
storage_ix = (storage_ix + 7u) & ~7u;
|
|
1205
1296
|
} else if (!ShouldCompress(input_buffer, mask, metablock_start,
|
|
@@ -1209,37 +1300,40 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1209
1300
|
memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
|
|
1210
1301
|
storage = BROTLI_ALLOC(m, uint8_t, metablock_size + 16);
|
|
1211
1302
|
if (BROTLI_IS_OOM(m)) goto oom;
|
|
1212
|
-
storage[0] =
|
|
1303
|
+
storage[0] = (uint8_t)last_bytes;
|
|
1304
|
+
storage[1] = (uint8_t)(last_bytes >> 8);
|
|
1213
1305
|
BrotliStoreUncompressedMetaBlock(is_last, input_buffer,
|
|
1214
1306
|
metablock_start, mask, metablock_size,
|
|
1215
1307
|
&storage_ix, storage);
|
|
1216
1308
|
} else {
|
|
1217
|
-
uint32_t num_direct_distance_codes = 0;
|
|
1218
|
-
uint32_t distance_postfix_bits = 0;
|
|
1219
|
-
ContextType literal_context_mode = CONTEXT_UTF8;
|
|
1220
1309
|
MetaBlockSplit mb;
|
|
1310
|
+
BrotliEncoderParams block_params = params;
|
|
1221
1311
|
InitMetaBlockSplit(&mb);
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
literal_context_mode = CONTEXT_SIGNED;
|
|
1225
|
-
}
|
|
1226
|
-
BrotliBuildMetaBlock(m, input_buffer, metablock_start, mask, ¶ms,
|
|
1312
|
+
BrotliBuildMetaBlock(m, input_buffer, metablock_start, mask,
|
|
1313
|
+
&block_params,
|
|
1227
1314
|
prev_byte, prev_byte2,
|
|
1228
1315
|
commands, num_commands,
|
|
1229
1316
|
literal_context_mode,
|
|
1230
1317
|
&mb);
|
|
1231
1318
|
if (BROTLI_IS_OOM(m)) goto oom;
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1319
|
+
{
|
|
1320
|
+
/* The number of distance symbols effectively used for distance
|
|
1321
|
+
histograms. It might be less than distance alphabet size
|
|
1322
|
+
for "Large Window Brotli" (32-bit). */
|
|
1323
|
+
uint32_t num_effective_dist_codes = block_params.dist.alphabet_size;
|
|
1324
|
+
if (num_effective_dist_codes > BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS) {
|
|
1325
|
+
num_effective_dist_codes = BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS;
|
|
1326
|
+
}
|
|
1327
|
+
BrotliOptimizeHistograms(num_effective_dist_codes, &mb);
|
|
1328
|
+
}
|
|
1329
|
+
storage = BROTLI_ALLOC(m, uint8_t, 2 * metablock_size + 503);
|
|
1236
1330
|
if (BROTLI_IS_OOM(m)) goto oom;
|
|
1237
|
-
storage[0] =
|
|
1331
|
+
storage[0] = (uint8_t)last_bytes;
|
|
1332
|
+
storage[1] = (uint8_t)(last_bytes >> 8);
|
|
1238
1333
|
BrotliStoreMetaBlock(m, input_buffer, metablock_start, metablock_size,
|
|
1239
1334
|
mask, prev_byte, prev_byte2,
|
|
1240
1335
|
is_last,
|
|
1241
|
-
|
|
1242
|
-
distance_postfix_bits,
|
|
1336
|
+
&block_params,
|
|
1243
1337
|
literal_context_mode,
|
|
1244
1338
|
commands, num_commands,
|
|
1245
1339
|
&mb,
|
|
@@ -1248,19 +1342,22 @@ static BROTLI_BOOL BrotliCompressBufferQuality10(
|
|
|
1248
1342
|
if (metablock_size + 4 < (storage_ix >> 3)) {
|
|
1249
1343
|
/* Restore the distance cache and last byte. */
|
|
1250
1344
|
memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));
|
|
1251
|
-
storage[0] =
|
|
1252
|
-
|
|
1345
|
+
storage[0] = (uint8_t)last_bytes;
|
|
1346
|
+
storage[1] = (uint8_t)(last_bytes >> 8);
|
|
1347
|
+
storage_ix = last_bytes_bits;
|
|
1253
1348
|
BrotliStoreUncompressedMetaBlock(is_last, input_buffer,
|
|
1254
1349
|
metablock_start, mask,
|
|
1255
1350
|
metablock_size, &storage_ix, storage);
|
|
1256
1351
|
}
|
|
1257
1352
|
DestroyMetaBlockSplit(m, &mb);
|
|
1258
1353
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1354
|
+
last_bytes = (uint16_t)(storage[storage_ix >> 3]);
|
|
1355
|
+
last_bytes_bits = storage_ix & 7u;
|
|
1261
1356
|
metablock_start += metablock_size;
|
|
1262
|
-
|
|
1263
|
-
|
|
1357
|
+
if (metablock_start < input_size) {
|
|
1358
|
+
prev_byte = input_buffer[metablock_start - 1];
|
|
1359
|
+
prev_byte2 = input_buffer[metablock_start - 2];
|
|
1360
|
+
}
|
|
1264
1361
|
/* Save the state of the distance cache in case we need to restore it for
|
|
1265
1362
|
emitting an uncompressed block. */
|
|
1266
1363
|
memcpy(saved_dist_cache, dist_cache, 4 * sizeof(dist_cache[0]));
|
|
@@ -1290,12 +1387,10 @@ oom:
|
|
|
1290
1387
|
|
|
1291
1388
|
size_t BrotliEncoderMaxCompressedSize(size_t input_size) {
|
|
1292
1389
|
/* [window bits / empty metadata] + N * [uncompressed] + [last empty] */
|
|
1293
|
-
size_t num_large_blocks = input_size >>
|
|
1294
|
-
size_t
|
|
1295
|
-
size_t tail_overhead = (tail > (1 << 20)) ? 4 : 3;
|
|
1296
|
-
size_t overhead = 2 + (4 * num_large_blocks) + tail_overhead + 1;
|
|
1390
|
+
size_t num_large_blocks = input_size >> 14;
|
|
1391
|
+
size_t overhead = 2 + (4 * num_large_blocks) + 3 + 1;
|
|
1297
1392
|
size_t result = input_size + overhead;
|
|
1298
|
-
if (input_size == 0) return
|
|
1393
|
+
if (input_size == 0) return 2;
|
|
1299
1394
|
return (result < input_size) ? 0 : result;
|
|
1300
1395
|
}
|
|
1301
1396
|
|
|
@@ -1356,7 +1451,7 @@ BROTLI_BOOL BrotliEncoderCompress(
|
|
|
1356
1451
|
}
|
|
1357
1452
|
if (quality == 10) {
|
|
1358
1453
|
/* TODO: Implement this direct path for all quality levels. */
|
|
1359
|
-
const int lg_win = BROTLI_MIN(int,
|
|
1454
|
+
const int lg_win = BROTLI_MIN(int, BROTLI_LARGE_MAX_WINDOW_BITS,
|
|
1360
1455
|
BROTLI_MAX(int, 16, lgwin));
|
|
1361
1456
|
int ok = BrotliCompressBufferQuality10(lg_win, input_size, input_buffer,
|
|
1362
1457
|
encoded_size, encoded_buffer);
|
|
@@ -1380,6 +1475,9 @@ BROTLI_BOOL BrotliEncoderCompress(
|
|
|
1380
1475
|
BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
|
|
1381
1476
|
BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode);
|
|
1382
1477
|
BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size);
|
|
1478
|
+
if (lgwin > BROTLI_MAX_WINDOW_BITS) {
|
|
1479
|
+
BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);
|
|
1480
|
+
}
|
|
1383
1481
|
result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH,
|
|
1384
1482
|
&available_in, &next_in, &available_out, &next_out, &total_out);
|
|
1385
1483
|
if (!BrotliEncoderIsFinished(s)) result = 0;
|
|
@@ -1402,11 +1500,11 @@ fallback:
|
|
|
1402
1500
|
}
|
|
1403
1501
|
|
|
1404
1502
|
static void InjectBytePaddingBlock(BrotliEncoderState* s) {
|
|
1405
|
-
uint32_t seal = s->
|
|
1406
|
-
size_t seal_bits = s->
|
|
1503
|
+
uint32_t seal = s->last_bytes_;
|
|
1504
|
+
size_t seal_bits = s->last_bytes_bits_;
|
|
1407
1505
|
uint8_t* destination;
|
|
1408
|
-
s->
|
|
1409
|
-
s->
|
|
1506
|
+
s->last_bytes_ = 0;
|
|
1507
|
+
s->last_bytes_bits_ = 0;
|
|
1410
1508
|
/* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */
|
|
1411
1509
|
seal |= 0x6u << seal_bits;
|
|
1412
1510
|
seal_bits += 6;
|
|
@@ -1420,6 +1518,7 @@ static void InjectBytePaddingBlock(BrotliEncoderState* s) {
|
|
|
1420
1518
|
}
|
|
1421
1519
|
destination[0] = (uint8_t)seal;
|
|
1422
1520
|
if (seal_bits > 8) destination[1] = (uint8_t)(seal >> 8);
|
|
1521
|
+
if (seal_bits > 16) destination[2] = (uint8_t)(seal >> 16);
|
|
1423
1522
|
s->available_out_ += (seal_bits + 7) >> 3;
|
|
1424
1523
|
}
|
|
1425
1524
|
|
|
@@ -1428,7 +1527,7 @@ static void InjectBytePaddingBlock(BrotliEncoderState* s) {
|
|
|
1428
1527
|
static BROTLI_BOOL InjectFlushOrPushOutput(BrotliEncoderState* s,
|
|
1429
1528
|
size_t* available_out, uint8_t** next_out, size_t* total_out) {
|
|
1430
1529
|
if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&
|
|
1431
|
-
s->
|
|
1530
|
+
s->last_bytes_bits_ != 0) {
|
|
1432
1531
|
InjectBytePaddingBlock(s);
|
|
1433
1532
|
return BROTLI_TRUE;
|
|
1434
1533
|
}
|
|
@@ -1509,10 +1608,10 @@ static BROTLI_BOOL BrotliEncoderCompressStreamFast(
|
|
|
1509
1608
|
(*available_in == block_size) && (op == BROTLI_OPERATION_FINISH);
|
|
1510
1609
|
BROTLI_BOOL force_flush =
|
|
1511
1610
|
(*available_in == block_size) && (op == BROTLI_OPERATION_FLUSH);
|
|
1512
|
-
size_t max_out_size = 2 * block_size +
|
|
1611
|
+
size_t max_out_size = 2 * block_size + 503;
|
|
1513
1612
|
BROTLI_BOOL inplace = BROTLI_TRUE;
|
|
1514
1613
|
uint8_t* storage = NULL;
|
|
1515
|
-
size_t storage_ix = s->
|
|
1614
|
+
size_t storage_ix = s->last_bytes_bits_;
|
|
1516
1615
|
size_t table_size;
|
|
1517
1616
|
int* table;
|
|
1518
1617
|
|
|
@@ -1527,7 +1626,8 @@ static BROTLI_BOOL BrotliEncoderCompressStreamFast(
|
|
|
1527
1626
|
storage = GetBrotliStorage(s, max_out_size);
|
|
1528
1627
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
1529
1628
|
}
|
|
1530
|
-
storage[0] = s->
|
|
1629
|
+
storage[0] = (uint8_t)s->last_bytes_;
|
|
1630
|
+
storage[1] = (uint8_t)(s->last_bytes_ >> 8);
|
|
1531
1631
|
table = GetHashTable(s, s->params.quality, block_size, &table_size);
|
|
1532
1632
|
if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
|
|
1533
1633
|
|
|
@@ -1546,8 +1646,8 @@ static BROTLI_BOOL BrotliEncoderCompressStreamFast(
|
|
|
1546
1646
|
*available_in -= block_size;
|
|
1547
1647
|
if (inplace) {
|
|
1548
1648
|
size_t out_bytes = storage_ix >> 3;
|
|
1549
|
-
|
|
1550
|
-
|
|
1649
|
+
BROTLI_DCHECK(out_bytes <= *available_out);
|
|
1650
|
+
BROTLI_DCHECK((storage_ix & 7) == 0 || out_bytes < *available_out);
|
|
1551
1651
|
*next_out += out_bytes;
|
|
1552
1652
|
*available_out -= out_bytes;
|
|
1553
1653
|
s->total_out_ += out_bytes;
|
|
@@ -1557,8 +1657,8 @@ static BROTLI_BOOL BrotliEncoderCompressStreamFast(
|
|
|
1557
1657
|
s->next_out_ = storage;
|
|
1558
1658
|
s->available_out_ = out_bytes;
|
|
1559
1659
|
}
|
|
1560
|
-
s->
|
|
1561
|
-
s->
|
|
1660
|
+
s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);
|
|
1661
|
+
s->last_bytes_bits_ = storage_ix & 7u;
|
|
1562
1662
|
|
|
1563
1663
|
if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;
|
|
1564
1664
|
if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;
|