brotli 0.2.3 → 0.5.0
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 +4 -4
- data/.github/workflows/main.yml +37 -0
- data/.github/workflows/publish.yml +24 -0
- data/.gitmodules +1 -1
- data/Gemfile +6 -3
- data/README.md +2 -2
- data/Rakefile +16 -9
- data/brotli.gemspec +7 -13
- data/ext/brotli/brotli.c +210 -31
- data/ext/brotli/buffer.c +1 -7
- data/ext/brotli/buffer.h +1 -1
- data/ext/brotli/extconf.rb +25 -17
- data/lib/brotli/version.rb +1 -1
- data/test/brotli_test.rb +107 -0
- data/test/brotli_writer_test.rb +36 -0
- data/test/test_helper.rb +8 -0
- data/vendor/brotli/c/common/constants.c +15 -0
- data/vendor/brotli/c/common/constants.h +137 -0
- data/vendor/brotli/c/common/context.c +156 -0
- data/vendor/brotli/c/common/context.h +4 -152
- data/vendor/brotli/c/common/dictionary.bin.br +0 -0
- data/vendor/brotli/c/common/dictionary.c +14 -3
- data/vendor/brotli/c/common/platform.c +23 -0
- data/vendor/brotli/c/common/platform.h +95 -122
- data/vendor/brotli/c/common/shared_dictionary.c +521 -0
- data/vendor/brotli/c/common/shared_dictionary_internal.h +75 -0
- data/vendor/brotli/c/common/transform.c +60 -4
- data/vendor/brotli/c/common/transform.h +5 -0
- data/vendor/brotli/c/common/version.h +31 -6
- data/vendor/brotli/c/dec/bit_reader.c +34 -4
- data/vendor/brotli/c/dec/bit_reader.h +221 -107
- data/vendor/brotli/c/dec/decode.c +772 -403
- data/vendor/brotli/c/dec/huffman.c +7 -4
- data/vendor/brotli/c/dec/huffman.h +8 -13
- data/vendor/brotli/c/dec/prefix.h +1 -18
- data/vendor/brotli/c/dec/state.c +40 -21
- data/vendor/brotli/c/dec/state.h +201 -59
- data/vendor/brotli/c/enc/backward_references.c +88 -25
- data/vendor/brotli/c/enc/backward_references.h +10 -8
- data/vendor/brotli/c/enc/backward_references_hq.c +194 -80
- data/vendor/brotli/c/enc/backward_references_hq.h +17 -13
- data/vendor/brotli/c/enc/backward_references_inc.h +52 -16
- data/vendor/brotli/c/enc/bit_cost.c +8 -7
- data/vendor/brotli/c/enc/bit_cost.h +5 -4
- data/vendor/brotli/c/enc/block_splitter.c +40 -17
- data/vendor/brotli/c/enc/block_splitter.h +5 -4
- data/vendor/brotli/c/enc/block_splitter_inc.h +99 -49
- data/vendor/brotli/c/enc/brotli_bit_stream.c +142 -137
- data/vendor/brotli/c/enc/brotli_bit_stream.h +11 -6
- data/vendor/brotli/c/enc/cluster.c +10 -9
- data/vendor/brotli/c/enc/cluster.h +7 -6
- data/vendor/brotli/c/enc/cluster_inc.h +30 -22
- data/vendor/brotli/c/enc/command.c +28 -0
- data/vendor/brotli/c/enc/command.h +17 -16
- data/vendor/brotli/c/enc/compound_dictionary.c +207 -0
- data/vendor/brotli/c/enc/compound_dictionary.h +74 -0
- data/vendor/brotli/c/enc/compress_fragment.c +93 -83
- data/vendor/brotli/c/enc/compress_fragment.h +32 -7
- data/vendor/brotli/c/enc/compress_fragment_two_pass.c +100 -88
- data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
- data/vendor/brotli/c/enc/dictionary_hash.c +1829 -1101
- data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
- data/vendor/brotli/c/enc/encode.c +550 -416
- data/vendor/brotli/c/enc/encoder_dict.c +613 -5
- data/vendor/brotli/c/enc/encoder_dict.h +120 -4
- data/vendor/brotli/c/enc/entropy_encode.c +5 -2
- data/vendor/brotli/c/enc/entropy_encode.h +4 -3
- data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
- data/vendor/brotli/c/enc/fast_log.c +105 -0
- data/vendor/brotli/c/enc/fast_log.h +21 -101
- data/vendor/brotli/c/enc/find_match_length.h +17 -25
- data/vendor/brotli/c/enc/hash.h +350 -120
- data/vendor/brotli/c/enc/hash_composite_inc.h +71 -67
- data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +92 -51
- data/vendor/brotli/c/enc/hash_longest_match64_inc.h +79 -84
- data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -54
- data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +93 -62
- data/vendor/brotli/c/enc/hash_rolling_inc.h +25 -29
- data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +42 -40
- data/vendor/brotli/c/enc/histogram.c +4 -4
- data/vendor/brotli/c/enc/histogram.h +7 -6
- data/vendor/brotli/c/enc/literal_cost.c +20 -15
- data/vendor/brotli/c/enc/literal_cost.h +4 -2
- data/vendor/brotli/c/enc/memory.c +29 -5
- data/vendor/brotli/c/enc/memory.h +43 -14
- data/vendor/brotli/c/enc/metablock.c +95 -85
- data/vendor/brotli/c/enc/metablock.h +9 -8
- data/vendor/brotli/c/enc/metablock_inc.h +9 -7
- data/vendor/brotli/c/enc/params.h +7 -4
- data/vendor/brotli/c/enc/prefix.h +3 -2
- data/vendor/brotli/c/enc/quality.h +40 -3
- data/vendor/brotli/c/enc/ringbuffer.h +8 -4
- data/vendor/brotli/c/enc/state.h +104 -0
- data/vendor/brotli/c/enc/static_dict.c +60 -4
- data/vendor/brotli/c/enc/static_dict.h +3 -2
- data/vendor/brotli/c/enc/static_dict_lut.h +2 -0
- data/vendor/brotli/c/enc/utf8_util.c +2 -2
- data/vendor/brotli/c/enc/utf8_util.h +2 -1
- data/vendor/brotli/c/enc/write_bits.h +29 -26
- data/vendor/brotli/c/include/brotli/decode.h +67 -2
- data/vendor/brotli/c/include/brotli/encode.h +77 -3
- data/vendor/brotli/c/include/brotli/port.h +34 -3
- data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
- metadata +23 -97
- data/.travis.yml +0 -31
- data/docs/Brotli/Error.html +0 -124
- data/docs/Brotli.html +0 -485
- data/docs/_index.html +0 -122
- data/docs/class_list.html +0 -51
- data/docs/css/common.css +0 -1
- data/docs/css/full_list.css +0 -58
- data/docs/css/style.css +0 -496
- data/docs/file.README.html +0 -127
- data/docs/file_list.html +0 -56
- data/docs/frames.html +0 -17
- data/docs/index.html +0 -127
- data/docs/js/app.js +0 -292
- data/docs/js/full_list.js +0 -216
- data/docs/js/jquery.js +0 -4
- data/docs/method_list.html +0 -67
- data/docs/top-level-namespace.html +0 -110
- data/spec/brotli_spec.rb +0 -88
- data/spec/inflate_spec.rb +0 -75
- data/spec/spec_helper.rb +0 -4
@@ -8,20 +8,21 @@
|
|
8
8
|
compression algorithms here, just the right ordering of bits to match the
|
9
9
|
specs. */
|
10
10
|
|
11
|
-
#include "
|
11
|
+
#include "brotli_bit_stream.h"
|
12
12
|
|
13
13
|
#include <string.h> /* memcpy, memset */
|
14
14
|
|
15
|
+
#include <brotli/types.h>
|
16
|
+
|
15
17
|
#include "../common/constants.h"
|
16
18
|
#include "../common/context.h"
|
17
19
|
#include "../common/platform.h"
|
18
|
-
#include
|
19
|
-
#include "
|
20
|
-
#include "
|
21
|
-
#include "
|
22
|
-
#include "
|
23
|
-
#include "
|
24
|
-
#include "./write_bits.h"
|
20
|
+
#include "entropy_encode.h"
|
21
|
+
#include "entropy_encode_static.h"
|
22
|
+
#include "fast_log.h"
|
23
|
+
#include "histogram.h"
|
24
|
+
#include "memory.h"
|
25
|
+
#include "write_bits.h"
|
25
26
|
|
26
27
|
#if defined(__cplusplus) || defined(c_plusplus)
|
27
28
|
extern "C" {
|
@@ -34,33 +35,18 @@ extern "C" {
|
|
34
35
|
BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS)
|
35
36
|
/* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */
|
36
37
|
|
37
|
-
/* Represents the range of values belonging to a prefix code:
|
38
|
-
[offset, offset + 2^nbits) */
|
39
|
-
typedef struct PrefixCodeRange {
|
40
|
-
uint32_t offset;
|
41
|
-
uint32_t nbits;
|
42
|
-
} PrefixCodeRange;
|
43
|
-
|
44
|
-
static const PrefixCodeRange
|
45
|
-
kBlockLengthPrefixCode[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
|
46
|
-
{ 1, 2}, { 5, 2}, { 9, 2}, {13, 2}, {17, 3}, { 25, 3}, { 33, 3},
|
47
|
-
{41, 3}, {49, 4}, {65, 4}, {81, 4}, {97, 4}, {113, 5}, {145, 5},
|
48
|
-
{177, 5}, { 209, 5}, { 241, 6}, { 305, 6}, { 369, 7}, { 497, 8},
|
49
|
-
{753, 9}, {1265, 10}, {2289, 11}, {4337, 12}, {8433, 13}, {16625, 24}
|
50
|
-
};
|
51
|
-
|
52
38
|
static BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) {
|
53
39
|
uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0);
|
54
40
|
while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) &&
|
55
|
-
len >=
|
41
|
+
len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code;
|
56
42
|
return code;
|
57
43
|
}
|
58
44
|
|
59
45
|
static BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code,
|
60
46
|
uint32_t* n_extra, uint32_t* extra) {
|
61
47
|
*code = BlockLengthPrefixCode(len);
|
62
|
-
*n_extra =
|
63
|
-
*extra = len -
|
48
|
+
*n_extra = _kBrotliPrefixCodeRanges[*code].nbits;
|
49
|
+
*extra = len - _kBrotliPrefixCodeRanges[*code].offset;
|
64
50
|
}
|
65
51
|
|
66
52
|
typedef struct BlockTypeCodeCalculator {
|
@@ -301,6 +287,7 @@ void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,
|
|
301
287
|
/* Write the Huffman tree into the brotli-representation.
|
302
288
|
The command alphabet is the largest, so this allocation will fit all
|
303
289
|
alphabets. */
|
290
|
+
/* TODO(eustas): fix me */
|
304
291
|
uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS];
|
305
292
|
uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS];
|
306
293
|
size_t huffman_tree_size = 0;
|
@@ -415,7 +402,7 @@ static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(
|
|
415
402
|
return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);
|
416
403
|
}
|
417
404
|
|
418
|
-
void BrotliBuildAndStoreHuffmanTreeFast(
|
405
|
+
void BrotliBuildAndStoreHuffmanTreeFast(HuffmanTree* tree,
|
419
406
|
const uint32_t* histogram,
|
420
407
|
const size_t histogram_total,
|
421
408
|
const size_t max_bits,
|
@@ -447,10 +434,7 @@ void BrotliBuildAndStoreHuffmanTreeFast(MemoryManager* m,
|
|
447
434
|
|
448
435
|
memset(depth, 0, length * sizeof(depth[0]));
|
449
436
|
{
|
450
|
-
const size_t max_tree_size = 2 * length + 1;
|
451
|
-
HuffmanTree* tree = BROTLI_ALLOC(m, HuffmanTree, max_tree_size);
|
452
437
|
uint32_t count_limit;
|
453
|
-
if (BROTLI_IS_OOM(m)) return;
|
454
438
|
for (count_limit = 1; ; count_limit *= 2) {
|
455
439
|
HuffmanTree* node = tree;
|
456
440
|
size_t l;
|
@@ -515,7 +499,6 @@ void BrotliBuildAndStoreHuffmanTreeFast(MemoryManager* m,
|
|
515
499
|
}
|
516
500
|
}
|
517
501
|
}
|
518
|
-
BROTLI_FREE(m, tree);
|
519
502
|
}
|
520
503
|
BrotliConvertBitDepthsToSymbols(depth, length, bits);
|
521
504
|
if (count <= 4) {
|
@@ -692,7 +675,14 @@ static void RunLengthCodeZeros(const size_t in_size,
|
|
692
675
|
|
693
676
|
#define SYMBOL_BITS 9
|
694
677
|
|
678
|
+
typedef struct EncodeContextMapArena {
|
679
|
+
uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
|
680
|
+
uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
|
681
|
+
uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
|
682
|
+
} EncodeContextMapArena;
|
683
|
+
|
695
684
|
static void EncodeContextMap(MemoryManager* m,
|
685
|
+
EncodeContextMapArena* arena,
|
696
686
|
const uint32_t* context_map,
|
697
687
|
size_t context_map_size,
|
698
688
|
size_t num_clusters,
|
@@ -702,10 +692,10 @@ static void EncodeContextMap(MemoryManager* m,
|
|
702
692
|
uint32_t* rle_symbols;
|
703
693
|
uint32_t max_run_length_prefix = 6;
|
704
694
|
size_t num_rle_symbols = 0;
|
705
|
-
uint32_t histogram
|
695
|
+
uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;
|
706
696
|
static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u;
|
707
|
-
uint8_t depths
|
708
|
-
uint16_t bits
|
697
|
+
uint8_t* BROTLI_RESTRICT const depths = arena->depths;
|
698
|
+
uint16_t* BROTLI_RESTRICT const bits = arena->bits;
|
709
699
|
|
710
700
|
StoreVarLenUint8(num_clusters - 1, storage_ix, storage);
|
711
701
|
|
@@ -714,11 +704,11 @@ static void EncodeContextMap(MemoryManager* m,
|
|
714
704
|
}
|
715
705
|
|
716
706
|
rle_symbols = BROTLI_ALLOC(m, uint32_t, context_map_size);
|
717
|
-
if (BROTLI_IS_OOM(m)) return;
|
707
|
+
if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(rle_symbols)) return;
|
718
708
|
MoveToFrontTransform(context_map, context_map_size, rle_symbols);
|
719
709
|
RunLengthCodeZeros(context_map_size, rle_symbols,
|
720
710
|
&num_rle_symbols, &max_run_length_prefix);
|
721
|
-
memset(histogram, 0, sizeof(histogram));
|
711
|
+
memset(histogram, 0, sizeof(arena->histogram));
|
722
712
|
for (i = 0; i < num_rle_symbols; ++i) {
|
723
713
|
++histogram[rle_symbols[i] & kSymbolMask];
|
724
714
|
}
|
@@ -789,7 +779,7 @@ static void BuildAndStoreBlockSplitCode(const uint8_t* types,
|
|
789
779
|
++length_histo[BlockLengthPrefixCode(lengths[i])];
|
790
780
|
}
|
791
781
|
StoreVarLenUint8(num_types - 1, storage_ix, storage);
|
792
|
-
if (num_types > 1) { /* TODO: else? could StoreBlockSwitch occur? */
|
782
|
+
if (num_types > 1) { /* TODO(eustas): else? could StoreBlockSwitch occur? */
|
793
783
|
BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree,
|
794
784
|
&code->type_depths[0], &code->type_bits[0],
|
795
785
|
storage_ix, storage);
|
@@ -802,7 +792,8 @@ static void BuildAndStoreBlockSplitCode(const uint8_t* types,
|
|
802
792
|
}
|
803
793
|
|
804
794
|
/* Stores a context map where the histogram type is always the block type. */
|
805
|
-
static void StoreTrivialContextMap(
|
795
|
+
static void StoreTrivialContextMap(EncodeContextMapArena* arena,
|
796
|
+
size_t num_types,
|
806
797
|
size_t context_bits,
|
807
798
|
HuffmanTree* tree,
|
808
799
|
size_t* storage_ix,
|
@@ -812,9 +803,9 @@ static void StoreTrivialContextMap(size_t num_types,
|
|
812
803
|
size_t repeat_code = context_bits - 1u;
|
813
804
|
size_t repeat_bits = (1u << repeat_code) - 1u;
|
814
805
|
size_t alphabet_size = num_types + repeat_code;
|
815
|
-
uint32_t histogram
|
816
|
-
uint8_t depths
|
817
|
-
uint16_t bits
|
806
|
+
uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;
|
807
|
+
uint8_t* BROTLI_RESTRICT const depths = arena->depths;
|
808
|
+
uint16_t* BROTLI_RESTRICT const bits = arena->bits;
|
818
809
|
size_t i;
|
819
810
|
memset(histogram, 0, alphabet_size * sizeof(histogram[0]));
|
820
811
|
/* Write RLEMAX. */
|
@@ -929,17 +920,17 @@ static void StoreSymbolWithContext(BlockEncoder* self, size_t symbol,
|
|
929
920
|
|
930
921
|
#define FN(X) X ## Literal
|
931
922
|
/* NOLINTNEXTLINE(build/include) */
|
932
|
-
#include "
|
923
|
+
#include "block_encoder_inc.h"
|
933
924
|
#undef FN
|
934
925
|
|
935
926
|
#define FN(X) X ## Command
|
936
927
|
/* NOLINTNEXTLINE(build/include) */
|
937
|
-
#include "
|
928
|
+
#include "block_encoder_inc.h"
|
938
929
|
#undef FN
|
939
930
|
|
940
931
|
#define FN(X) X ## Distance
|
941
932
|
/* NOLINTNEXTLINE(build/include) */
|
942
|
-
#include "
|
933
|
+
#include "block_encoder_inc.h"
|
943
934
|
#undef FN
|
944
935
|
|
945
936
|
static void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {
|
@@ -947,6 +938,13 @@ static void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {
|
|
947
938
|
storage[*storage_ix >> 3] = 0;
|
948
939
|
}
|
949
940
|
|
941
|
+
typedef struct StoreMetablockArena {
|
942
|
+
BlockEncoder literal_enc;
|
943
|
+
BlockEncoder command_enc;
|
944
|
+
BlockEncoder distance_enc;
|
945
|
+
EncodeContextMapArena context_map_arena;
|
946
|
+
} StoreMetablockArena;
|
947
|
+
|
950
948
|
void BrotliStoreMetaBlock(MemoryManager* m,
|
951
949
|
const uint8_t* input, size_t start_pos, size_t length, size_t mask,
|
952
950
|
uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,
|
@@ -956,37 +954,39 @@ void BrotliStoreMetaBlock(MemoryManager* m,
|
|
956
954
|
|
957
955
|
size_t pos = start_pos;
|
958
956
|
size_t i;
|
959
|
-
uint32_t num_distance_symbols = params->dist.
|
960
|
-
uint32_t num_effective_distance_symbols =
|
957
|
+
uint32_t num_distance_symbols = params->dist.alphabet_size_max;
|
958
|
+
uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit;
|
961
959
|
HuffmanTree* tree;
|
962
960
|
ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
|
963
|
-
|
964
|
-
BlockEncoder
|
965
|
-
BlockEncoder
|
961
|
+
StoreMetablockArena* arena = NULL;
|
962
|
+
BlockEncoder* literal_enc = NULL;
|
963
|
+
BlockEncoder* command_enc = NULL;
|
964
|
+
BlockEncoder* distance_enc = NULL;
|
966
965
|
const BrotliDistanceParams* dist = ¶ms->dist;
|
967
|
-
|
968
|
-
num_effective_distance_symbols
|
969
|
-
num_effective_distance_symbols = BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS;
|
970
|
-
}
|
966
|
+
BROTLI_DCHECK(
|
967
|
+
num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS);
|
971
968
|
|
972
969
|
StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
|
973
970
|
|
974
971
|
tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);
|
975
|
-
|
976
|
-
|
972
|
+
arena = BROTLI_ALLOC(m, StoreMetablockArena, 1);
|
973
|
+
if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree) || BROTLI_IS_NULL(arena)) return;
|
974
|
+
literal_enc = &arena->literal_enc;
|
975
|
+
command_enc = &arena->command_enc;
|
976
|
+
distance_enc = &arena->distance_enc;
|
977
|
+
InitBlockEncoder(literal_enc, BROTLI_NUM_LITERAL_SYMBOLS,
|
977
978
|
mb->literal_split.num_types, mb->literal_split.types,
|
978
979
|
mb->literal_split.lengths, mb->literal_split.num_blocks);
|
979
|
-
InitBlockEncoder(
|
980
|
+
InitBlockEncoder(command_enc, BROTLI_NUM_COMMAND_SYMBOLS,
|
980
981
|
mb->command_split.num_types, mb->command_split.types,
|
981
982
|
mb->command_split.lengths, mb->command_split.num_blocks);
|
982
|
-
InitBlockEncoder(
|
983
|
+
InitBlockEncoder(distance_enc, num_effective_distance_symbols,
|
983
984
|
mb->distance_split.num_types, mb->distance_split.types,
|
984
985
|
mb->distance_split.lengths, mb->distance_split.num_blocks);
|
985
986
|
|
986
|
-
BuildAndStoreBlockSwitchEntropyCodes(
|
987
|
-
BuildAndStoreBlockSwitchEntropyCodes(
|
988
|
-
BuildAndStoreBlockSwitchEntropyCodes(
|
989
|
-
&distance_enc, tree, storage_ix, storage);
|
987
|
+
BuildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage);
|
988
|
+
BuildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage);
|
989
|
+
BuildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage);
|
990
990
|
|
991
991
|
BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage);
|
992
992
|
BrotliWriteBits(
|
@@ -997,34 +997,36 @@ void BrotliStoreMetaBlock(MemoryManager* m,
|
|
997
997
|
}
|
998
998
|
|
999
999
|
if (mb->literal_context_map_size == 0) {
|
1000
|
-
StoreTrivialContextMap(
|
1000
|
+
StoreTrivialContextMap(
|
1001
|
+
&arena->context_map_arena, mb->literal_histograms_size,
|
1001
1002
|
BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage);
|
1002
1003
|
} else {
|
1003
|
-
EncodeContextMap(m,
|
1004
|
+
EncodeContextMap(m, &arena->context_map_arena,
|
1004
1005
|
mb->literal_context_map, mb->literal_context_map_size,
|
1005
1006
|
mb->literal_histograms_size, tree, storage_ix, storage);
|
1006
1007
|
if (BROTLI_IS_OOM(m)) return;
|
1007
1008
|
}
|
1008
1009
|
|
1009
1010
|
if (mb->distance_context_map_size == 0) {
|
1010
|
-
StoreTrivialContextMap(
|
1011
|
+
StoreTrivialContextMap(
|
1012
|
+
&arena->context_map_arena, mb->distance_histograms_size,
|
1011
1013
|
BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage);
|
1012
1014
|
} else {
|
1013
|
-
EncodeContextMap(m,
|
1015
|
+
EncodeContextMap(m, &arena->context_map_arena,
|
1014
1016
|
mb->distance_context_map, mb->distance_context_map_size,
|
1015
1017
|
mb->distance_histograms_size, tree, storage_ix, storage);
|
1016
1018
|
if (BROTLI_IS_OOM(m)) return;
|
1017
1019
|
}
|
1018
1020
|
|
1019
|
-
BuildAndStoreEntropyCodesLiteral(m,
|
1021
|
+
BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms,
|
1020
1022
|
mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,
|
1021
1023
|
storage_ix, storage);
|
1022
1024
|
if (BROTLI_IS_OOM(m)) return;
|
1023
|
-
BuildAndStoreEntropyCodesCommand(m,
|
1025
|
+
BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms,
|
1024
1026
|
mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree,
|
1025
1027
|
storage_ix, storage);
|
1026
1028
|
if (BROTLI_IS_OOM(m)) return;
|
1027
|
-
BuildAndStoreEntropyCodesDistance(m,
|
1029
|
+
BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms,
|
1028
1030
|
mb->distance_histograms_size, num_distance_symbols, tree,
|
1029
1031
|
storage_ix, storage);
|
1030
1032
|
if (BROTLI_IS_OOM(m)) return;
|
@@ -1033,12 +1035,12 @@ void BrotliStoreMetaBlock(MemoryManager* m,
|
|
1033
1035
|
for (i = 0; i < n_commands; ++i) {
|
1034
1036
|
const Command cmd = commands[i];
|
1035
1037
|
size_t cmd_code = cmd.cmd_prefix_;
|
1036
|
-
StoreSymbol(
|
1038
|
+
StoreSymbol(command_enc, cmd_code, storage_ix, storage);
|
1037
1039
|
StoreCommandExtra(&cmd, storage_ix, storage);
|
1038
1040
|
if (mb->literal_context_map_size == 0) {
|
1039
1041
|
size_t j;
|
1040
1042
|
for (j = cmd.insert_len_; j != 0; --j) {
|
1041
|
-
StoreSymbol(
|
1043
|
+
StoreSymbol(literal_enc, input[pos & mask], storage_ix, storage);
|
1042
1044
|
++pos;
|
1043
1045
|
}
|
1044
1046
|
} else {
|
@@ -1047,7 +1049,7 @@ void BrotliStoreMetaBlock(MemoryManager* m,
|
|
1047
1049
|
size_t context =
|
1048
1050
|
BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);
|
1049
1051
|
uint8_t literal = input[pos & mask];
|
1050
|
-
StoreSymbolWithContext(
|
1052
|
+
StoreSymbolWithContext(literal_enc, literal, context,
|
1051
1053
|
mb->literal_context_map, storage_ix, storage,
|
1052
1054
|
BROTLI_LITERAL_CONTEXT_BITS);
|
1053
1055
|
prev_byte2 = prev_byte;
|
@@ -1064,10 +1066,10 @@ void BrotliStoreMetaBlock(MemoryManager* m,
|
|
1064
1066
|
uint32_t distnumextra = cmd.dist_prefix_ >> 10;
|
1065
1067
|
uint64_t distextra = cmd.dist_extra_;
|
1066
1068
|
if (mb->distance_context_map_size == 0) {
|
1067
|
-
StoreSymbol(
|
1069
|
+
StoreSymbol(distance_enc, dist_code, storage_ix, storage);
|
1068
1070
|
} else {
|
1069
1071
|
size_t context = CommandDistanceContext(&cmd);
|
1070
|
-
StoreSymbolWithContext(
|
1072
|
+
StoreSymbolWithContext(distance_enc, dist_code, context,
|
1071
1073
|
mb->distance_context_map, storage_ix, storage,
|
1072
1074
|
BROTLI_DISTANCE_CONTEXT_BITS);
|
1073
1075
|
}
|
@@ -1075,9 +1077,10 @@ void BrotliStoreMetaBlock(MemoryManager* m,
|
|
1075
1077
|
}
|
1076
1078
|
}
|
1077
1079
|
}
|
1078
|
-
CleanupBlockEncoder(m,
|
1079
|
-
CleanupBlockEncoder(m,
|
1080
|
-
CleanupBlockEncoder(m,
|
1080
|
+
CleanupBlockEncoder(m, distance_enc);
|
1081
|
+
CleanupBlockEncoder(m, command_enc);
|
1082
|
+
CleanupBlockEncoder(m, literal_enc);
|
1083
|
+
BROTLI_FREE(m, arena);
|
1081
1084
|
if (is_last) {
|
1082
1085
|
JumpToByteBoundary(storage_ix, storage);
|
1083
1086
|
}
|
@@ -1148,54 +1151,60 @@ static void StoreDataWithHuffmanCodes(const uint8_t* input,
|
|
1148
1151
|
}
|
1149
1152
|
}
|
1150
1153
|
|
1151
|
-
|
1152
|
-
|
1153
|
-
BROTLI_BOOL is_last, const BrotliEncoderParams* params,
|
1154
|
-
const Command* commands, size_t n_commands,
|
1155
|
-
size_t* storage_ix, uint8_t* storage) {
|
1154
|
+
/* TODO(eustas): pull alloc/dealloc to caller? */
|
1155
|
+
typedef struct MetablockArena {
|
1156
1156
|
HistogramLiteral lit_histo;
|
1157
1157
|
HistogramCommand cmd_histo;
|
1158
1158
|
HistogramDistance dist_histo;
|
1159
|
+
/* TODO(eustas): merge bits and depth? */
|
1159
1160
|
uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
|
1160
1161
|
uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
|
1161
1162
|
uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];
|
1162
1163
|
uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];
|
1163
1164
|
uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
|
1164
1165
|
uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
|
1165
|
-
HuffmanTree
|
1166
|
-
|
1166
|
+
HuffmanTree tree[MAX_HUFFMAN_TREE_SIZE];
|
1167
|
+
} MetablockArena;
|
1168
|
+
|
1169
|
+
void BrotliStoreMetaBlockTrivial(MemoryManager* m,
|
1170
|
+
const uint8_t* input, size_t start_pos, size_t length, size_t mask,
|
1171
|
+
BROTLI_BOOL is_last, const BrotliEncoderParams* params,
|
1172
|
+
const Command* commands, size_t n_commands,
|
1173
|
+
size_t* storage_ix, uint8_t* storage) {
|
1174
|
+
MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);
|
1175
|
+
uint32_t num_distance_symbols = params->dist.alphabet_size_max;
|
1176
|
+
if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
|
1167
1177
|
|
1168
1178
|
StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
|
1169
1179
|
|
1170
|
-
HistogramClearLiteral(&lit_histo);
|
1171
|
-
HistogramClearCommand(&cmd_histo);
|
1172
|
-
HistogramClearDistance(&dist_histo);
|
1180
|
+
HistogramClearLiteral(&arena->lit_histo);
|
1181
|
+
HistogramClearCommand(&arena->cmd_histo);
|
1182
|
+
HistogramClearDistance(&arena->dist_histo);
|
1173
1183
|
|
1174
1184
|
BuildHistograms(input, start_pos, mask, commands, n_commands,
|
1175
|
-
&lit_histo, &cmd_histo, &dist_histo);
|
1185
|
+
&arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);
|
1176
1186
|
|
1177
1187
|
BrotliWriteBits(13, 0, storage_ix, storage);
|
1178
1188
|
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
BROTLI_NUM_LITERAL_SYMBOLS, tree,
|
1183
|
-
lit_depth, lit_bits,
|
1189
|
+
BuildAndStoreHuffmanTree(arena->lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS,
|
1190
|
+
BROTLI_NUM_LITERAL_SYMBOLS, arena->tree,
|
1191
|
+
arena->lit_depth, arena->lit_bits,
|
1184
1192
|
storage_ix, storage);
|
1185
|
-
BuildAndStoreHuffmanTree(cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS,
|
1186
|
-
BROTLI_NUM_COMMAND_SYMBOLS, tree,
|
1187
|
-
cmd_depth, cmd_bits,
|
1193
|
+
BuildAndStoreHuffmanTree(arena->cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS,
|
1194
|
+
BROTLI_NUM_COMMAND_SYMBOLS, arena->tree,
|
1195
|
+
arena->cmd_depth, arena->cmd_bits,
|
1188
1196
|
storage_ix, storage);
|
1189
|
-
BuildAndStoreHuffmanTree(dist_histo.data_,
|
1190
|
-
|
1191
|
-
|
1197
|
+
BuildAndStoreHuffmanTree(arena->dist_histo.data_,
|
1198
|
+
MAX_SIMPLE_DISTANCE_ALPHABET_SIZE,
|
1199
|
+
num_distance_symbols, arena->tree,
|
1200
|
+
arena->dist_depth, arena->dist_bits,
|
1192
1201
|
storage_ix, storage);
|
1193
|
-
BROTLI_FREE(m, tree);
|
1194
1202
|
StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
|
1195
|
-
n_commands, lit_depth, lit_bits,
|
1196
|
-
cmd_depth, cmd_bits,
|
1197
|
-
dist_depth, dist_bits,
|
1203
|
+
n_commands, arena->lit_depth, arena->lit_bits,
|
1204
|
+
arena->cmd_depth, arena->cmd_bits,
|
1205
|
+
arena->dist_depth, arena->dist_bits,
|
1198
1206
|
storage_ix, storage);
|
1207
|
+
BROTLI_FREE(m, arena);
|
1199
1208
|
if (is_last) {
|
1200
1209
|
JumpToByteBoundary(storage_ix, storage);
|
1201
1210
|
}
|
@@ -1206,9 +1215,11 @@ void BrotliStoreMetaBlockFast(MemoryManager* m,
|
|
1206
1215
|
BROTLI_BOOL is_last, const BrotliEncoderParams* params,
|
1207
1216
|
const Command* commands, size_t n_commands,
|
1208
1217
|
size_t* storage_ix, uint8_t* storage) {
|
1209
|
-
|
1218
|
+
MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);
|
1219
|
+
uint32_t num_distance_symbols = params->dist.alphabet_size_max;
|
1210
1220
|
uint32_t distance_alphabet_bits =
|
1211
1221
|
Log2FloorNonZero(num_distance_symbols - 1) + 1;
|
1222
|
+
if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
|
1212
1223
|
|
1213
1224
|
StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
|
1214
1225
|
|
@@ -1219,8 +1230,6 @@ void BrotliStoreMetaBlockFast(MemoryManager* m,
|
|
1219
1230
|
size_t pos = start_pos;
|
1220
1231
|
size_t num_literals = 0;
|
1221
1232
|
size_t i;
|
1222
|
-
uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
|
1223
|
-
uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
|
1224
1233
|
for (i = 0; i < n_commands; ++i) {
|
1225
1234
|
const Command cmd = commands[i];
|
1226
1235
|
size_t j;
|
@@ -1231,61 +1240,50 @@ void BrotliStoreMetaBlockFast(MemoryManager* m,
|
|
1231
1240
|
num_literals += cmd.insert_len_;
|
1232
1241
|
pos += CommandCopyLen(&cmd);
|
1233
1242
|
}
|
1234
|
-
BrotliBuildAndStoreHuffmanTreeFast(
|
1243
|
+
BrotliBuildAndStoreHuffmanTreeFast(arena->tree, histogram, num_literals,
|
1235
1244
|
/* max_bits = */ 8,
|
1236
|
-
lit_depth, lit_bits,
|
1245
|
+
arena->lit_depth, arena->lit_bits,
|
1237
1246
|
storage_ix, storage);
|
1238
|
-
if (BROTLI_IS_OOM(m)) return;
|
1239
1247
|
StoreStaticCommandHuffmanTree(storage_ix, storage);
|
1240
1248
|
StoreStaticDistanceHuffmanTree(storage_ix, storage);
|
1241
1249
|
StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
|
1242
|
-
n_commands, lit_depth, lit_bits,
|
1250
|
+
n_commands, arena->lit_depth, arena->lit_bits,
|
1243
1251
|
kStaticCommandCodeDepth,
|
1244
1252
|
kStaticCommandCodeBits,
|
1245
1253
|
kStaticDistanceCodeDepth,
|
1246
1254
|
kStaticDistanceCodeBits,
|
1247
1255
|
storage_ix, storage);
|
1248
1256
|
} else {
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
|
1253
|
-
uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
|
1254
|
-
uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];
|
1255
|
-
uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];
|
1256
|
-
uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
|
1257
|
-
uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
|
1258
|
-
HistogramClearLiteral(&lit_histo);
|
1259
|
-
HistogramClearCommand(&cmd_histo);
|
1260
|
-
HistogramClearDistance(&dist_histo);
|
1257
|
+
HistogramClearLiteral(&arena->lit_histo);
|
1258
|
+
HistogramClearCommand(&arena->cmd_histo);
|
1259
|
+
HistogramClearDistance(&arena->dist_histo);
|
1261
1260
|
BuildHistograms(input, start_pos, mask, commands, n_commands,
|
1262
|
-
&lit_histo, &cmd_histo, &dist_histo);
|
1263
|
-
BrotliBuildAndStoreHuffmanTreeFast(
|
1264
|
-
lit_histo.total_count_,
|
1261
|
+
&arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);
|
1262
|
+
BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->lit_histo.data_,
|
1263
|
+
arena->lit_histo.total_count_,
|
1265
1264
|
/* max_bits = */ 8,
|
1266
|
-
lit_depth, lit_bits,
|
1265
|
+
arena->lit_depth, arena->lit_bits,
|
1267
1266
|
storage_ix, storage);
|
1268
|
-
|
1269
|
-
|
1270
|
-
cmd_histo.total_count_,
|
1267
|
+
BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->cmd_histo.data_,
|
1268
|
+
arena->cmd_histo.total_count_,
|
1271
1269
|
/* max_bits = */ 10,
|
1272
|
-
cmd_depth, cmd_bits,
|
1270
|
+
arena->cmd_depth, arena->cmd_bits,
|
1273
1271
|
storage_ix, storage);
|
1274
|
-
|
1275
|
-
|
1276
|
-
dist_histo.total_count_,
|
1272
|
+
BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->dist_histo.data_,
|
1273
|
+
arena->dist_histo.total_count_,
|
1277
1274
|
/* max_bits = */
|
1278
1275
|
distance_alphabet_bits,
|
1279
|
-
dist_depth, dist_bits,
|
1276
|
+
arena->dist_depth, arena->dist_bits,
|
1280
1277
|
storage_ix, storage);
|
1281
|
-
if (BROTLI_IS_OOM(m)) return;
|
1282
1278
|
StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
|
1283
|
-
n_commands, lit_depth, lit_bits,
|
1284
|
-
cmd_depth, cmd_bits,
|
1285
|
-
dist_depth, dist_bits,
|
1279
|
+
n_commands, arena->lit_depth, arena->lit_bits,
|
1280
|
+
arena->cmd_depth, arena->cmd_bits,
|
1281
|
+
arena->dist_depth, arena->dist_bits,
|
1286
1282
|
storage_ix, storage);
|
1287
1283
|
}
|
1288
1284
|
|
1285
|
+
BROTLI_FREE(m, arena);
|
1286
|
+
|
1289
1287
|
if (is_last) {
|
1290
1288
|
JumpToByteBoundary(storage_ix, storage);
|
1291
1289
|
}
|
@@ -1326,6 +1324,13 @@ void BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block,
|
|
1326
1324
|
}
|
1327
1325
|
}
|
1328
1326
|
|
1327
|
+
#if defined(BROTLI_TEST)
|
1328
|
+
void GetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code,
|
1329
|
+
uint32_t* n_extra, uint32_t* extra) {
|
1330
|
+
GetBlockLengthPrefixCode(len, code, n_extra, extra);
|
1331
|
+
}
|
1332
|
+
#endif
|
1333
|
+
|
1329
1334
|
#if defined(__cplusplus) || defined(c_plusplus)
|
1330
1335
|
} /* extern "C" */
|
1331
1336
|
#endif
|
@@ -16,13 +16,14 @@
|
|
16
16
|
#ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
17
17
|
#define BROTLI_ENC_BROTLI_BIT_STREAM_H_
|
18
18
|
|
19
|
+
#include <brotli/types.h>
|
20
|
+
|
19
21
|
#include "../common/context.h"
|
20
22
|
#include "../common/platform.h"
|
21
|
-
#include
|
22
|
-
#include "
|
23
|
-
#include "
|
24
|
-
#include "
|
25
|
-
#include "./metablock.h"
|
23
|
+
#include "command.h"
|
24
|
+
#include "entropy_encode.h"
|
25
|
+
#include "memory.h"
|
26
|
+
#include "metablock.h"
|
26
27
|
|
27
28
|
#if defined(__cplusplus) || defined(c_plusplus)
|
28
29
|
extern "C" {
|
@@ -35,7 +36,7 @@ BROTLI_INTERNAL void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,
|
|
35
36
|
HuffmanTree* tree, size_t* storage_ix, uint8_t* storage);
|
36
37
|
|
37
38
|
BROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast(
|
38
|
-
|
39
|
+
HuffmanTree* tree, const uint32_t* histogram, const size_t histogram_total,
|
39
40
|
const size_t max_bits, uint8_t* depth, uint16_t* bits, size_t* storage_ix,
|
40
41
|
uint8_t* storage);
|
41
42
|
|
@@ -77,6 +78,10 @@ BROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock(
|
|
77
78
|
size_t position, size_t mask, size_t len,
|
78
79
|
size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage);
|
79
80
|
|
81
|
+
#if defined(BROTLI_TEST)
|
82
|
+
void GetBlockLengthPrefixCodeForTest(uint32_t, size_t*, uint32_t*, uint32_t*);
|
83
|
+
#endif
|
84
|
+
|
80
85
|
#if defined(__cplusplus) || defined(c_plusplus)
|
81
86
|
} /* extern "C" */
|
82
87
|
#endif
|
@@ -6,14 +6,15 @@
|
|
6
6
|
|
7
7
|
/* Functions for clustering similar histograms together. */
|
8
8
|
|
9
|
-
#include "
|
9
|
+
#include "cluster.h"
|
10
10
|
|
11
|
-
#include "../common/platform.h"
|
12
11
|
#include <brotli/types.h>
|
13
|
-
|
14
|
-
#include "
|
15
|
-
#include "
|
16
|
-
#include "
|
12
|
+
|
13
|
+
#include "../common/platform.h"
|
14
|
+
#include "bit_cost.h" /* BrotliPopulationCost */
|
15
|
+
#include "fast_log.h"
|
16
|
+
#include "histogram.h"
|
17
|
+
#include "memory.h"
|
17
18
|
|
18
19
|
#if defined(__cplusplus) || defined(c_plusplus)
|
19
20
|
extern "C" {
|
@@ -38,15 +39,15 @@ static BROTLI_INLINE double ClusterCostDiff(size_t size_a, size_t size_b) {
|
|
38
39
|
#define CODE(X) X
|
39
40
|
|
40
41
|
#define FN(X) X ## Literal
|
41
|
-
#include "
|
42
|
+
#include "cluster_inc.h" /* NOLINT(build/include) */
|
42
43
|
#undef FN
|
43
44
|
|
44
45
|
#define FN(X) X ## Command
|
45
|
-
#include "
|
46
|
+
#include "cluster_inc.h" /* NOLINT(build/include) */
|
46
47
|
#undef FN
|
47
48
|
|
48
49
|
#define FN(X) X ## Distance
|
49
|
-
#include "
|
50
|
+
#include "cluster_inc.h" /* NOLINT(build/include) */
|
50
51
|
#undef FN
|
51
52
|
|
52
53
|
#undef CODE
|