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
@@ -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;
|