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.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +37 -0
  3. data/.github/workflows/publish.yml +24 -0
  4. data/.gitmodules +1 -1
  5. data/Gemfile +6 -3
  6. data/README.md +2 -2
  7. data/Rakefile +16 -9
  8. data/brotli.gemspec +7 -13
  9. data/ext/brotli/brotli.c +210 -31
  10. data/ext/brotli/buffer.c +1 -7
  11. data/ext/brotli/buffer.h +1 -1
  12. data/ext/brotli/extconf.rb +25 -17
  13. data/lib/brotli/version.rb +1 -1
  14. data/test/brotli_test.rb +107 -0
  15. data/test/brotli_writer_test.rb +36 -0
  16. data/test/test_helper.rb +8 -0
  17. data/vendor/brotli/c/common/constants.c +15 -0
  18. data/vendor/brotli/c/common/constants.h +137 -0
  19. data/vendor/brotli/c/common/context.c +156 -0
  20. data/vendor/brotli/c/common/context.h +4 -152
  21. data/vendor/brotli/c/common/dictionary.bin.br +0 -0
  22. data/vendor/brotli/c/common/dictionary.c +14 -3
  23. data/vendor/brotli/c/common/platform.c +23 -0
  24. data/vendor/brotli/c/common/platform.h +95 -122
  25. data/vendor/brotli/c/common/shared_dictionary.c +521 -0
  26. data/vendor/brotli/c/common/shared_dictionary_internal.h +75 -0
  27. data/vendor/brotli/c/common/transform.c +60 -4
  28. data/vendor/brotli/c/common/transform.h +5 -0
  29. data/vendor/brotli/c/common/version.h +31 -6
  30. data/vendor/brotli/c/dec/bit_reader.c +34 -4
  31. data/vendor/brotli/c/dec/bit_reader.h +221 -107
  32. data/vendor/brotli/c/dec/decode.c +772 -403
  33. data/vendor/brotli/c/dec/huffman.c +7 -4
  34. data/vendor/brotli/c/dec/huffman.h +8 -13
  35. data/vendor/brotli/c/dec/prefix.h +1 -18
  36. data/vendor/brotli/c/dec/state.c +40 -21
  37. data/vendor/brotli/c/dec/state.h +201 -59
  38. data/vendor/brotli/c/enc/backward_references.c +88 -25
  39. data/vendor/brotli/c/enc/backward_references.h +10 -8
  40. data/vendor/brotli/c/enc/backward_references_hq.c +194 -80
  41. data/vendor/brotli/c/enc/backward_references_hq.h +17 -13
  42. data/vendor/brotli/c/enc/backward_references_inc.h +52 -16
  43. data/vendor/brotli/c/enc/bit_cost.c +8 -7
  44. data/vendor/brotli/c/enc/bit_cost.h +5 -4
  45. data/vendor/brotli/c/enc/block_splitter.c +40 -17
  46. data/vendor/brotli/c/enc/block_splitter.h +5 -4
  47. data/vendor/brotli/c/enc/block_splitter_inc.h +99 -49
  48. data/vendor/brotli/c/enc/brotli_bit_stream.c +142 -137
  49. data/vendor/brotli/c/enc/brotli_bit_stream.h +11 -6
  50. data/vendor/brotli/c/enc/cluster.c +10 -9
  51. data/vendor/brotli/c/enc/cluster.h +7 -6
  52. data/vendor/brotli/c/enc/cluster_inc.h +30 -22
  53. data/vendor/brotli/c/enc/command.c +28 -0
  54. data/vendor/brotli/c/enc/command.h +17 -16
  55. data/vendor/brotli/c/enc/compound_dictionary.c +207 -0
  56. data/vendor/brotli/c/enc/compound_dictionary.h +74 -0
  57. data/vendor/brotli/c/enc/compress_fragment.c +93 -83
  58. data/vendor/brotli/c/enc/compress_fragment.h +32 -7
  59. data/vendor/brotli/c/enc/compress_fragment_two_pass.c +100 -88
  60. data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
  61. data/vendor/brotli/c/enc/dictionary_hash.c +1829 -1101
  62. data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
  63. data/vendor/brotli/c/enc/encode.c +550 -416
  64. data/vendor/brotli/c/enc/encoder_dict.c +613 -5
  65. data/vendor/brotli/c/enc/encoder_dict.h +120 -4
  66. data/vendor/brotli/c/enc/entropy_encode.c +5 -2
  67. data/vendor/brotli/c/enc/entropy_encode.h +4 -3
  68. data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
  69. data/vendor/brotli/c/enc/fast_log.c +105 -0
  70. data/vendor/brotli/c/enc/fast_log.h +21 -101
  71. data/vendor/brotli/c/enc/find_match_length.h +17 -25
  72. data/vendor/brotli/c/enc/hash.h +350 -120
  73. data/vendor/brotli/c/enc/hash_composite_inc.h +71 -67
  74. data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +92 -51
  75. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +79 -84
  76. data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -54
  77. data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +93 -62
  78. data/vendor/brotli/c/enc/hash_rolling_inc.h +25 -29
  79. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +42 -40
  80. data/vendor/brotli/c/enc/histogram.c +4 -4
  81. data/vendor/brotli/c/enc/histogram.h +7 -6
  82. data/vendor/brotli/c/enc/literal_cost.c +20 -15
  83. data/vendor/brotli/c/enc/literal_cost.h +4 -2
  84. data/vendor/brotli/c/enc/memory.c +29 -5
  85. data/vendor/brotli/c/enc/memory.h +43 -14
  86. data/vendor/brotli/c/enc/metablock.c +95 -85
  87. data/vendor/brotli/c/enc/metablock.h +9 -8
  88. data/vendor/brotli/c/enc/metablock_inc.h +9 -7
  89. data/vendor/brotli/c/enc/params.h +7 -4
  90. data/vendor/brotli/c/enc/prefix.h +3 -2
  91. data/vendor/brotli/c/enc/quality.h +40 -3
  92. data/vendor/brotli/c/enc/ringbuffer.h +8 -4
  93. data/vendor/brotli/c/enc/state.h +104 -0
  94. data/vendor/brotli/c/enc/static_dict.c +60 -4
  95. data/vendor/brotli/c/enc/static_dict.h +3 -2
  96. data/vendor/brotli/c/enc/static_dict_lut.h +2 -0
  97. data/vendor/brotli/c/enc/utf8_util.c +2 -2
  98. data/vendor/brotli/c/enc/utf8_util.h +2 -1
  99. data/vendor/brotli/c/enc/write_bits.h +29 -26
  100. data/vendor/brotli/c/include/brotli/decode.h +67 -2
  101. data/vendor/brotli/c/include/brotli/encode.h +77 -3
  102. data/vendor/brotli/c/include/brotli/port.h +34 -3
  103. data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
  104. metadata +23 -97
  105. data/.travis.yml +0 -31
  106. data/docs/Brotli/Error.html +0 -124
  107. data/docs/Brotli.html +0 -485
  108. data/docs/_index.html +0 -122
  109. data/docs/class_list.html +0 -51
  110. data/docs/css/common.css +0 -1
  111. data/docs/css/full_list.css +0 -58
  112. data/docs/css/style.css +0 -496
  113. data/docs/file.README.html +0 -127
  114. data/docs/file_list.html +0 -56
  115. data/docs/frames.html +0 -17
  116. data/docs/index.html +0 -127
  117. data/docs/js/app.js +0 -292
  118. data/docs/js/full_list.js +0 -216
  119. data/docs/js/jquery.js +0 -4
  120. data/docs/method_list.html +0 -67
  121. data/docs/top-level-namespace.html +0 -110
  122. data/spec/brotli_spec.rb +0 -88
  123. data/spec/inflate_spec.rb +0 -75
  124. 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 "./brotli_bit_stream.h"
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 <brotli/types.h>
19
- #include "./entropy_encode.h"
20
- #include "./entropy_encode_static.h"
21
- #include "./fast_log.h"
22
- #include "./histogram.h"
23
- #include "./memory.h"
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 >= kBlockLengthPrefixCode[code + 1].offset) ++code;
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 = kBlockLengthPrefixCode[*code].nbits;
63
- *extra = len - kBlockLengthPrefixCode[*code].offset;
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(MemoryManager* m,
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[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
695
+ uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;
706
696
  static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u;
707
- uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
708
- uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
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(size_t num_types,
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[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
816
- uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
817
- uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
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 "./block_encoder_inc.h"
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 "./block_encoder_inc.h"
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 "./block_encoder_inc.h"
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.alphabet_size;
960
- uint32_t num_effective_distance_symbols = num_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
- BlockEncoder literal_enc;
964
- BlockEncoder command_enc;
965
- BlockEncoder distance_enc;
961
+ StoreMetablockArena* arena = NULL;
962
+ BlockEncoder* literal_enc = NULL;
963
+ BlockEncoder* command_enc = NULL;
964
+ BlockEncoder* distance_enc = NULL;
966
965
  const BrotliDistanceParams* dist = &params->dist;
967
- if (params->large_window &&
968
- num_effective_distance_symbols > BROTLI_NUM_HISTOGRAM_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
- if (BROTLI_IS_OOM(m)) return;
976
- InitBlockEncoder(&literal_enc, BROTLI_NUM_LITERAL_SYMBOLS,
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(&command_enc, BROTLI_NUM_COMMAND_SYMBOLS,
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(&distance_enc, num_effective_distance_symbols,
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(&literal_enc, tree, storage_ix, storage);
987
- BuildAndStoreBlockSwitchEntropyCodes(&command_enc, tree, storage_ix, storage);
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(mb->literal_histograms_size,
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(mb->distance_histograms_size,
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, &literal_enc, mb->literal_histograms,
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, &command_enc, mb->command_histograms,
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, &distance_enc, mb->distance_histograms,
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(&command_enc, cmd_code, storage_ix, storage);
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(&literal_enc, input[pos & mask], storage_ix, storage);
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(&literal_enc, literal, context,
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(&distance_enc, dist_code, storage_ix, storage);
1069
+ StoreSymbol(distance_enc, dist_code, storage_ix, storage);
1068
1070
  } else {
1069
1071
  size_t context = CommandDistanceContext(&cmd);
1070
- StoreSymbolWithContext(&distance_enc, dist_code, context,
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, &distance_enc);
1079
- CleanupBlockEncoder(m, &command_enc);
1080
- CleanupBlockEncoder(m, &literal_enc);
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
- void BrotliStoreMetaBlockTrivial(MemoryManager* m,
1152
- const uint8_t* input, size_t start_pos, size_t length, size_t mask,
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* tree;
1166
- uint32_t num_distance_symbols = params->dist.alphabet_size;
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
- tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);
1180
- if (BROTLI_IS_OOM(m)) return;
1181
- BuildAndStoreHuffmanTree(lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS,
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_, MAX_SIMPLE_DISTANCE_ALPHABET_SIZE,
1190
- num_distance_symbols, tree,
1191
- dist_depth, dist_bits,
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
- uint32_t num_distance_symbols = params->dist.alphabet_size;
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(m, histogram, num_literals,
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
- HistogramLiteral lit_histo;
1250
- HistogramCommand cmd_histo;
1251
- HistogramDistance dist_histo;
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(m, lit_histo.data_,
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
- if (BROTLI_IS_OOM(m)) return;
1269
- BrotliBuildAndStoreHuffmanTreeFast(m, cmd_histo.data_,
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
- if (BROTLI_IS_OOM(m)) return;
1275
- BrotliBuildAndStoreHuffmanTreeFast(m, dist_histo.data_,
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 <brotli/types.h>
22
- #include "./command.h"
23
- #include "./entropy_encode.h"
24
- #include "./memory.h"
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
- MemoryManager* m, const uint32_t* histogram, const size_t histogram_total,
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 "./cluster.h"
9
+ #include "cluster.h"
10
10
 
11
- #include "../common/platform.h"
12
11
  #include <brotli/types.h>
13
- #include "./bit_cost.h" /* BrotliPopulationCost */
14
- #include "./fast_log.h"
15
- #include "./histogram.h"
16
- #include "./memory.h"
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 "./cluster_inc.h" /* NOLINT(build/include) */
42
+ #include "cluster_inc.h" /* NOLINT(build/include) */
42
43
  #undef FN
43
44
 
44
45
  #define FN(X) X ## Command
45
- #include "./cluster_inc.h" /* NOLINT(build/include) */
46
+ #include "cluster_inc.h" /* NOLINT(build/include) */
46
47
  #undef FN
47
48
 
48
49
  #define FN(X) X ## Distance
49
- #include "./cluster_inc.h" /* NOLINT(build/include) */
50
+ #include "cluster_inc.h" /* NOLINT(build/include) */
50
51
  #undef FN
51
52
 
52
53
  #undef CODE