brotli 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +6 -3
  3. data/.github/workflows/publish.yml +7 -17
  4. data/.gitmodules +1 -1
  5. data/README.md +2 -2
  6. data/ext/brotli/brotli.c +1 -0
  7. data/ext/brotli/extconf.rb +6 -0
  8. data/lib/brotli/version.rb +1 -1
  9. data/test/brotli_test.rb +4 -1
  10. data/vendor/brotli/c/common/constants.c +1 -1
  11. data/vendor/brotli/c/common/constants.h +2 -1
  12. data/vendor/brotli/c/common/context.c +1 -1
  13. data/vendor/brotli/c/common/dictionary.c +5 -3
  14. data/vendor/brotli/c/common/platform.c +2 -1
  15. data/vendor/brotli/c/common/platform.h +60 -113
  16. data/vendor/brotli/c/common/shared_dictionary.c +521 -0
  17. data/vendor/brotli/c/common/shared_dictionary_internal.h +75 -0
  18. data/vendor/brotli/c/common/transform.c +1 -1
  19. data/vendor/brotli/c/common/version.h +31 -6
  20. data/vendor/brotli/c/dec/bit_reader.c +10 -8
  21. data/vendor/brotli/c/dec/bit_reader.h +172 -100
  22. data/vendor/brotli/c/dec/decode.c +467 -200
  23. data/vendor/brotli/c/dec/huffman.c +7 -4
  24. data/vendor/brotli/c/dec/huffman.h +2 -1
  25. data/vendor/brotli/c/dec/prefix.h +2 -1
  26. data/vendor/brotli/c/dec/state.c +33 -9
  27. data/vendor/brotli/c/dec/state.h +70 -35
  28. data/vendor/brotli/c/enc/backward_references.c +81 -19
  29. data/vendor/brotli/c/enc/backward_references.h +5 -4
  30. data/vendor/brotli/c/enc/backward_references_hq.c +148 -52
  31. data/vendor/brotli/c/enc/backward_references_hq.h +6 -5
  32. data/vendor/brotli/c/enc/backward_references_inc.h +31 -5
  33. data/vendor/brotli/c/enc/bit_cost.c +8 -7
  34. data/vendor/brotli/c/enc/bit_cost.h +5 -4
  35. data/vendor/brotli/c/enc/block_splitter.c +37 -14
  36. data/vendor/brotli/c/enc/block_splitter.h +5 -4
  37. data/vendor/brotli/c/enc/block_splitter_inc.h +86 -45
  38. data/vendor/brotli/c/enc/brotli_bit_stream.c +132 -110
  39. data/vendor/brotli/c/enc/brotli_bit_stream.h +11 -6
  40. data/vendor/brotli/c/enc/cluster.c +10 -9
  41. data/vendor/brotli/c/enc/cluster.h +7 -6
  42. data/vendor/brotli/c/enc/cluster_inc.h +25 -20
  43. data/vendor/brotli/c/enc/command.c +1 -1
  44. data/vendor/brotli/c/enc/command.h +5 -4
  45. data/vendor/brotli/c/enc/compound_dictionary.c +207 -0
  46. data/vendor/brotli/c/enc/compound_dictionary.h +74 -0
  47. data/vendor/brotli/c/enc/compress_fragment.c +93 -83
  48. data/vendor/brotli/c/enc/compress_fragment.h +32 -7
  49. data/vendor/brotli/c/enc/compress_fragment_two_pass.c +99 -87
  50. data/vendor/brotli/c/enc/compress_fragment_two_pass.h +21 -3
  51. data/vendor/brotli/c/enc/dictionary_hash.c +3 -1
  52. data/vendor/brotli/c/enc/encode.c +473 -404
  53. data/vendor/brotli/c/enc/encoder_dict.c +611 -4
  54. data/vendor/brotli/c/enc/encoder_dict.h +117 -3
  55. data/vendor/brotli/c/enc/entropy_encode.c +3 -2
  56. data/vendor/brotli/c/enc/entropy_encode.h +2 -1
  57. data/vendor/brotli/c/enc/entropy_encode_static.h +5 -2
  58. data/vendor/brotli/c/enc/fast_log.c +1 -1
  59. data/vendor/brotli/c/enc/fast_log.h +2 -1
  60. data/vendor/brotli/c/enc/find_match_length.h +15 -22
  61. data/vendor/brotli/c/enc/hash.h +285 -45
  62. data/vendor/brotli/c/enc/hash_composite_inc.h +26 -11
  63. data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +20 -18
  64. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +34 -39
  65. data/vendor/brotli/c/enc/hash_longest_match_inc.h +6 -10
  66. data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +4 -4
  67. data/vendor/brotli/c/enc/hash_rolling_inc.h +4 -4
  68. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +6 -5
  69. data/vendor/brotli/c/enc/histogram.c +4 -4
  70. data/vendor/brotli/c/enc/histogram.h +7 -6
  71. data/vendor/brotli/c/enc/literal_cost.c +20 -15
  72. data/vendor/brotli/c/enc/literal_cost.h +4 -2
  73. data/vendor/brotli/c/enc/memory.c +29 -5
  74. data/vendor/brotli/c/enc/memory.h +19 -2
  75. data/vendor/brotli/c/enc/metablock.c +72 -58
  76. data/vendor/brotli/c/enc/metablock.h +9 -8
  77. data/vendor/brotli/c/enc/metablock_inc.h +8 -6
  78. data/vendor/brotli/c/enc/params.h +4 -3
  79. data/vendor/brotli/c/enc/prefix.h +3 -2
  80. data/vendor/brotli/c/enc/quality.h +40 -3
  81. data/vendor/brotli/c/enc/ringbuffer.h +4 -3
  82. data/vendor/brotli/c/enc/state.h +104 -0
  83. data/vendor/brotli/c/enc/static_dict.c +60 -4
  84. data/vendor/brotli/c/enc/static_dict.h +3 -2
  85. data/vendor/brotli/c/enc/static_dict_lut.h +2 -0
  86. data/vendor/brotli/c/enc/utf8_util.c +1 -1
  87. data/vendor/brotli/c/enc/utf8_util.h +2 -1
  88. data/vendor/brotli/c/enc/write_bits.h +2 -1
  89. data/vendor/brotli/c/include/brotli/decode.h +67 -2
  90. data/vendor/brotli/c/include/brotli/encode.h +55 -2
  91. data/vendor/brotli/c/include/brotli/port.h +28 -11
  92. data/vendor/brotli/c/include/brotli/shared_dictionary.h +100 -0
  93. metadata +9 -3
@@ -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" {
@@ -286,6 +287,7 @@ void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,
286
287
  /* Write the Huffman tree into the brotli-representation.
287
288
  The command alphabet is the largest, so this allocation will fit all
288
289
  alphabets. */
290
+ /* TODO(eustas): fix me */
289
291
  uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS];
290
292
  uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS];
291
293
  size_t huffman_tree_size = 0;
@@ -400,7 +402,7 @@ static BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(
400
402
  return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);
401
403
  }
402
404
 
403
- void BrotliBuildAndStoreHuffmanTreeFast(MemoryManager* m,
405
+ void BrotliBuildAndStoreHuffmanTreeFast(HuffmanTree* tree,
404
406
  const uint32_t* histogram,
405
407
  const size_t histogram_total,
406
408
  const size_t max_bits,
@@ -432,10 +434,7 @@ void BrotliBuildAndStoreHuffmanTreeFast(MemoryManager* m,
432
434
 
433
435
  memset(depth, 0, length * sizeof(depth[0]));
434
436
  {
435
- const size_t max_tree_size = 2 * length + 1;
436
- HuffmanTree* tree = BROTLI_ALLOC(m, HuffmanTree, max_tree_size);
437
437
  uint32_t count_limit;
438
- if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree)) return;
439
438
  for (count_limit = 1; ; count_limit *= 2) {
440
439
  HuffmanTree* node = tree;
441
440
  size_t l;
@@ -500,7 +499,6 @@ void BrotliBuildAndStoreHuffmanTreeFast(MemoryManager* m,
500
499
  }
501
500
  }
502
501
  }
503
- BROTLI_FREE(m, tree);
504
502
  }
505
503
  BrotliConvertBitDepthsToSymbols(depth, length, bits);
506
504
  if (count <= 4) {
@@ -677,7 +675,14 @@ static void RunLengthCodeZeros(const size_t in_size,
677
675
 
678
676
  #define SYMBOL_BITS 9
679
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
+
680
684
  static void EncodeContextMap(MemoryManager* m,
685
+ EncodeContextMapArena* arena,
681
686
  const uint32_t* context_map,
682
687
  size_t context_map_size,
683
688
  size_t num_clusters,
@@ -687,10 +692,10 @@ static void EncodeContextMap(MemoryManager* m,
687
692
  uint32_t* rle_symbols;
688
693
  uint32_t max_run_length_prefix = 6;
689
694
  size_t num_rle_symbols = 0;
690
- uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
695
+ uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;
691
696
  static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u;
692
- uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
693
- 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;
694
699
 
695
700
  StoreVarLenUint8(num_clusters - 1, storage_ix, storage);
696
701
 
@@ -703,7 +708,7 @@ static void EncodeContextMap(MemoryManager* m,
703
708
  MoveToFrontTransform(context_map, context_map_size, rle_symbols);
704
709
  RunLengthCodeZeros(context_map_size, rle_symbols,
705
710
  &num_rle_symbols, &max_run_length_prefix);
706
- memset(histogram, 0, sizeof(histogram));
711
+ memset(histogram, 0, sizeof(arena->histogram));
707
712
  for (i = 0; i < num_rle_symbols; ++i) {
708
713
  ++histogram[rle_symbols[i] & kSymbolMask];
709
714
  }
@@ -774,7 +779,7 @@ static void BuildAndStoreBlockSplitCode(const uint8_t* types,
774
779
  ++length_histo[BlockLengthPrefixCode(lengths[i])];
775
780
  }
776
781
  StoreVarLenUint8(num_types - 1, storage_ix, storage);
777
- if (num_types > 1) { /* TODO: else? could StoreBlockSwitch occur? */
782
+ if (num_types > 1) { /* TODO(eustas): else? could StoreBlockSwitch occur? */
778
783
  BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree,
779
784
  &code->type_depths[0], &code->type_bits[0],
780
785
  storage_ix, storage);
@@ -787,7 +792,8 @@ static void BuildAndStoreBlockSplitCode(const uint8_t* types,
787
792
  }
788
793
 
789
794
  /* Stores a context map where the histogram type is always the block type. */
790
- static void StoreTrivialContextMap(size_t num_types,
795
+ static void StoreTrivialContextMap(EncodeContextMapArena* arena,
796
+ size_t num_types,
791
797
  size_t context_bits,
792
798
  HuffmanTree* tree,
793
799
  size_t* storage_ix,
@@ -797,9 +803,9 @@ static void StoreTrivialContextMap(size_t num_types,
797
803
  size_t repeat_code = context_bits - 1u;
798
804
  size_t repeat_bits = (1u << repeat_code) - 1u;
799
805
  size_t alphabet_size = num_types + repeat_code;
800
- uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
801
- uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];
802
- 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;
803
809
  size_t i;
804
810
  memset(histogram, 0, alphabet_size * sizeof(histogram[0]));
805
811
  /* Write RLEMAX. */
@@ -914,17 +920,17 @@ static void StoreSymbolWithContext(BlockEncoder* self, size_t symbol,
914
920
 
915
921
  #define FN(X) X ## Literal
916
922
  /* NOLINTNEXTLINE(build/include) */
917
- #include "./block_encoder_inc.h"
923
+ #include "block_encoder_inc.h"
918
924
  #undef FN
919
925
 
920
926
  #define FN(X) X ## Command
921
927
  /* NOLINTNEXTLINE(build/include) */
922
- #include "./block_encoder_inc.h"
928
+ #include "block_encoder_inc.h"
923
929
  #undef FN
924
930
 
925
931
  #define FN(X) X ## Distance
926
932
  /* NOLINTNEXTLINE(build/include) */
927
- #include "./block_encoder_inc.h"
933
+ #include "block_encoder_inc.h"
928
934
  #undef FN
929
935
 
930
936
  static void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {
@@ -932,6 +938,13 @@ static void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {
932
938
  storage[*storage_ix >> 3] = 0;
933
939
  }
934
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
+
935
948
  void BrotliStoreMetaBlock(MemoryManager* m,
936
949
  const uint8_t* input, size_t start_pos, size_t length, size_t mask,
937
950
  uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,
@@ -945,9 +958,10 @@ void BrotliStoreMetaBlock(MemoryManager* m,
945
958
  uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit;
946
959
  HuffmanTree* tree;
947
960
  ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);
948
- BlockEncoder literal_enc;
949
- BlockEncoder command_enc;
950
- BlockEncoder distance_enc;
961
+ StoreMetablockArena* arena = NULL;
962
+ BlockEncoder* literal_enc = NULL;
963
+ BlockEncoder* command_enc = NULL;
964
+ BlockEncoder* distance_enc = NULL;
951
965
  const BrotliDistanceParams* dist = &params->dist;
952
966
  BROTLI_DCHECK(
953
967
  num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS);
@@ -955,21 +969,24 @@ void BrotliStoreMetaBlock(MemoryManager* m,
955
969
  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
956
970
 
957
971
  tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);
958
- if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree)) return;
959
- 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,
960
978
  mb->literal_split.num_types, mb->literal_split.types,
961
979
  mb->literal_split.lengths, mb->literal_split.num_blocks);
962
- InitBlockEncoder(&command_enc, BROTLI_NUM_COMMAND_SYMBOLS,
980
+ InitBlockEncoder(command_enc, BROTLI_NUM_COMMAND_SYMBOLS,
963
981
  mb->command_split.num_types, mb->command_split.types,
964
982
  mb->command_split.lengths, mb->command_split.num_blocks);
965
- InitBlockEncoder(&distance_enc, num_effective_distance_symbols,
983
+ InitBlockEncoder(distance_enc, num_effective_distance_symbols,
966
984
  mb->distance_split.num_types, mb->distance_split.types,
967
985
  mb->distance_split.lengths, mb->distance_split.num_blocks);
968
986
 
969
- BuildAndStoreBlockSwitchEntropyCodes(&literal_enc, tree, storage_ix, storage);
970
- BuildAndStoreBlockSwitchEntropyCodes(&command_enc, tree, storage_ix, storage);
971
- BuildAndStoreBlockSwitchEntropyCodes(
972
- &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);
973
990
 
974
991
  BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage);
975
992
  BrotliWriteBits(
@@ -980,34 +997,36 @@ void BrotliStoreMetaBlock(MemoryManager* m,
980
997
  }
981
998
 
982
999
  if (mb->literal_context_map_size == 0) {
983
- StoreTrivialContextMap(mb->literal_histograms_size,
1000
+ StoreTrivialContextMap(
1001
+ &arena->context_map_arena, mb->literal_histograms_size,
984
1002
  BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage);
985
1003
  } else {
986
- EncodeContextMap(m,
1004
+ EncodeContextMap(m, &arena->context_map_arena,
987
1005
  mb->literal_context_map, mb->literal_context_map_size,
988
1006
  mb->literal_histograms_size, tree, storage_ix, storage);
989
1007
  if (BROTLI_IS_OOM(m)) return;
990
1008
  }
991
1009
 
992
1010
  if (mb->distance_context_map_size == 0) {
993
- StoreTrivialContextMap(mb->distance_histograms_size,
1011
+ StoreTrivialContextMap(
1012
+ &arena->context_map_arena, mb->distance_histograms_size,
994
1013
  BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage);
995
1014
  } else {
996
- EncodeContextMap(m,
1015
+ EncodeContextMap(m, &arena->context_map_arena,
997
1016
  mb->distance_context_map, mb->distance_context_map_size,
998
1017
  mb->distance_histograms_size, tree, storage_ix, storage);
999
1018
  if (BROTLI_IS_OOM(m)) return;
1000
1019
  }
1001
1020
 
1002
- BuildAndStoreEntropyCodesLiteral(m, &literal_enc, mb->literal_histograms,
1021
+ BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms,
1003
1022
  mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,
1004
1023
  storage_ix, storage);
1005
1024
  if (BROTLI_IS_OOM(m)) return;
1006
- BuildAndStoreEntropyCodesCommand(m, &command_enc, mb->command_histograms,
1025
+ BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms,
1007
1026
  mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree,
1008
1027
  storage_ix, storage);
1009
1028
  if (BROTLI_IS_OOM(m)) return;
1010
- BuildAndStoreEntropyCodesDistance(m, &distance_enc, mb->distance_histograms,
1029
+ BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms,
1011
1030
  mb->distance_histograms_size, num_distance_symbols, tree,
1012
1031
  storage_ix, storage);
1013
1032
  if (BROTLI_IS_OOM(m)) return;
@@ -1016,12 +1035,12 @@ void BrotliStoreMetaBlock(MemoryManager* m,
1016
1035
  for (i = 0; i < n_commands; ++i) {
1017
1036
  const Command cmd = commands[i];
1018
1037
  size_t cmd_code = cmd.cmd_prefix_;
1019
- StoreSymbol(&command_enc, cmd_code, storage_ix, storage);
1038
+ StoreSymbol(command_enc, cmd_code, storage_ix, storage);
1020
1039
  StoreCommandExtra(&cmd, storage_ix, storage);
1021
1040
  if (mb->literal_context_map_size == 0) {
1022
1041
  size_t j;
1023
1042
  for (j = cmd.insert_len_; j != 0; --j) {
1024
- StoreSymbol(&literal_enc, input[pos & mask], storage_ix, storage);
1043
+ StoreSymbol(literal_enc, input[pos & mask], storage_ix, storage);
1025
1044
  ++pos;
1026
1045
  }
1027
1046
  } else {
@@ -1030,7 +1049,7 @@ void BrotliStoreMetaBlock(MemoryManager* m,
1030
1049
  size_t context =
1031
1050
  BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);
1032
1051
  uint8_t literal = input[pos & mask];
1033
- StoreSymbolWithContext(&literal_enc, literal, context,
1052
+ StoreSymbolWithContext(literal_enc, literal, context,
1034
1053
  mb->literal_context_map, storage_ix, storage,
1035
1054
  BROTLI_LITERAL_CONTEXT_BITS);
1036
1055
  prev_byte2 = prev_byte;
@@ -1047,10 +1066,10 @@ void BrotliStoreMetaBlock(MemoryManager* m,
1047
1066
  uint32_t distnumextra = cmd.dist_prefix_ >> 10;
1048
1067
  uint64_t distextra = cmd.dist_extra_;
1049
1068
  if (mb->distance_context_map_size == 0) {
1050
- StoreSymbol(&distance_enc, dist_code, storage_ix, storage);
1069
+ StoreSymbol(distance_enc, dist_code, storage_ix, storage);
1051
1070
  } else {
1052
1071
  size_t context = CommandDistanceContext(&cmd);
1053
- StoreSymbolWithContext(&distance_enc, dist_code, context,
1072
+ StoreSymbolWithContext(distance_enc, dist_code, context,
1054
1073
  mb->distance_context_map, storage_ix, storage,
1055
1074
  BROTLI_DISTANCE_CONTEXT_BITS);
1056
1075
  }
@@ -1058,9 +1077,10 @@ void BrotliStoreMetaBlock(MemoryManager* m,
1058
1077
  }
1059
1078
  }
1060
1079
  }
1061
- CleanupBlockEncoder(m, &distance_enc);
1062
- CleanupBlockEncoder(m, &command_enc);
1063
- CleanupBlockEncoder(m, &literal_enc);
1080
+ CleanupBlockEncoder(m, distance_enc);
1081
+ CleanupBlockEncoder(m, command_enc);
1082
+ CleanupBlockEncoder(m, literal_enc);
1083
+ BROTLI_FREE(m, arena);
1064
1084
  if (is_last) {
1065
1085
  JumpToByteBoundary(storage_ix, storage);
1066
1086
  }
@@ -1131,54 +1151,60 @@ static void StoreDataWithHuffmanCodes(const uint8_t* input,
1131
1151
  }
1132
1152
  }
1133
1153
 
1134
- void BrotliStoreMetaBlockTrivial(MemoryManager* m,
1135
- const uint8_t* input, size_t start_pos, size_t length, size_t mask,
1136
- BROTLI_BOOL is_last, const BrotliEncoderParams* params,
1137
- const Command* commands, size_t n_commands,
1138
- size_t* storage_ix, uint8_t* storage) {
1154
+ /* TODO(eustas): pull alloc/dealloc to caller? */
1155
+ typedef struct MetablockArena {
1139
1156
  HistogramLiteral lit_histo;
1140
1157
  HistogramCommand cmd_histo;
1141
1158
  HistogramDistance dist_histo;
1159
+ /* TODO(eustas): merge bits and depth? */
1142
1160
  uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
1143
1161
  uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
1144
1162
  uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];
1145
1163
  uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];
1146
1164
  uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
1147
1165
  uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
1148
- HuffmanTree* tree;
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);
1149
1175
  uint32_t num_distance_symbols = params->dist.alphabet_size_max;
1176
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
1150
1177
 
1151
1178
  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
1152
1179
 
1153
- HistogramClearLiteral(&lit_histo);
1154
- HistogramClearCommand(&cmd_histo);
1155
- HistogramClearDistance(&dist_histo);
1180
+ HistogramClearLiteral(&arena->lit_histo);
1181
+ HistogramClearCommand(&arena->cmd_histo);
1182
+ HistogramClearDistance(&arena->dist_histo);
1156
1183
 
1157
1184
  BuildHistograms(input, start_pos, mask, commands, n_commands,
1158
- &lit_histo, &cmd_histo, &dist_histo);
1185
+ &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);
1159
1186
 
1160
1187
  BrotliWriteBits(13, 0, storage_ix, storage);
1161
1188
 
1162
- tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);
1163
- if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree)) return;
1164
- BuildAndStoreHuffmanTree(lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS,
1165
- BROTLI_NUM_LITERAL_SYMBOLS, tree,
1166
- 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,
1167
1192
  storage_ix, storage);
1168
- BuildAndStoreHuffmanTree(cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS,
1169
- BROTLI_NUM_COMMAND_SYMBOLS, tree,
1170
- 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,
1171
1196
  storage_ix, storage);
1172
- BuildAndStoreHuffmanTree(dist_histo.data_, MAX_SIMPLE_DISTANCE_ALPHABET_SIZE,
1173
- num_distance_symbols, tree,
1174
- 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,
1175
1201
  storage_ix, storage);
1176
- BROTLI_FREE(m, tree);
1177
1202
  StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
1178
- n_commands, lit_depth, lit_bits,
1179
- cmd_depth, cmd_bits,
1180
- 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,
1181
1206
  storage_ix, storage);
1207
+ BROTLI_FREE(m, arena);
1182
1208
  if (is_last) {
1183
1209
  JumpToByteBoundary(storage_ix, storage);
1184
1210
  }
@@ -1189,9 +1215,11 @@ void BrotliStoreMetaBlockFast(MemoryManager* m,
1189
1215
  BROTLI_BOOL is_last, const BrotliEncoderParams* params,
1190
1216
  const Command* commands, size_t n_commands,
1191
1217
  size_t* storage_ix, uint8_t* storage) {
1218
+ MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);
1192
1219
  uint32_t num_distance_symbols = params->dist.alphabet_size_max;
1193
1220
  uint32_t distance_alphabet_bits =
1194
1221
  Log2FloorNonZero(num_distance_symbols - 1) + 1;
1222
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
1195
1223
 
1196
1224
  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);
1197
1225
 
@@ -1202,8 +1230,6 @@ void BrotliStoreMetaBlockFast(MemoryManager* m,
1202
1230
  size_t pos = start_pos;
1203
1231
  size_t num_literals = 0;
1204
1232
  size_t i;
1205
- uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
1206
- uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
1207
1233
  for (i = 0; i < n_commands; ++i) {
1208
1234
  const Command cmd = commands[i];
1209
1235
  size_t j;
@@ -1214,61 +1240,50 @@ void BrotliStoreMetaBlockFast(MemoryManager* m,
1214
1240
  num_literals += cmd.insert_len_;
1215
1241
  pos += CommandCopyLen(&cmd);
1216
1242
  }
1217
- BrotliBuildAndStoreHuffmanTreeFast(m, histogram, num_literals,
1243
+ BrotliBuildAndStoreHuffmanTreeFast(arena->tree, histogram, num_literals,
1218
1244
  /* max_bits = */ 8,
1219
- lit_depth, lit_bits,
1245
+ arena->lit_depth, arena->lit_bits,
1220
1246
  storage_ix, storage);
1221
- if (BROTLI_IS_OOM(m)) return;
1222
1247
  StoreStaticCommandHuffmanTree(storage_ix, storage);
1223
1248
  StoreStaticDistanceHuffmanTree(storage_ix, storage);
1224
1249
  StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
1225
- n_commands, lit_depth, lit_bits,
1250
+ n_commands, arena->lit_depth, arena->lit_bits,
1226
1251
  kStaticCommandCodeDepth,
1227
1252
  kStaticCommandCodeBits,
1228
1253
  kStaticDistanceCodeDepth,
1229
1254
  kStaticDistanceCodeBits,
1230
1255
  storage_ix, storage);
1231
1256
  } else {
1232
- HistogramLiteral lit_histo;
1233
- HistogramCommand cmd_histo;
1234
- HistogramDistance dist_histo;
1235
- uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];
1236
- uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];
1237
- uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];
1238
- uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];
1239
- uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
1240
- uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];
1241
- HistogramClearLiteral(&lit_histo);
1242
- HistogramClearCommand(&cmd_histo);
1243
- HistogramClearDistance(&dist_histo);
1257
+ HistogramClearLiteral(&arena->lit_histo);
1258
+ HistogramClearCommand(&arena->cmd_histo);
1259
+ HistogramClearDistance(&arena->dist_histo);
1244
1260
  BuildHistograms(input, start_pos, mask, commands, n_commands,
1245
- &lit_histo, &cmd_histo, &dist_histo);
1246
- BrotliBuildAndStoreHuffmanTreeFast(m, lit_histo.data_,
1247
- 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_,
1248
1264
  /* max_bits = */ 8,
1249
- lit_depth, lit_bits,
1265
+ arena->lit_depth, arena->lit_bits,
1250
1266
  storage_ix, storage);
1251
- if (BROTLI_IS_OOM(m)) return;
1252
- BrotliBuildAndStoreHuffmanTreeFast(m, cmd_histo.data_,
1253
- cmd_histo.total_count_,
1267
+ BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->cmd_histo.data_,
1268
+ arena->cmd_histo.total_count_,
1254
1269
  /* max_bits = */ 10,
1255
- cmd_depth, cmd_bits,
1270
+ arena->cmd_depth, arena->cmd_bits,
1256
1271
  storage_ix, storage);
1257
- if (BROTLI_IS_OOM(m)) return;
1258
- BrotliBuildAndStoreHuffmanTreeFast(m, dist_histo.data_,
1259
- dist_histo.total_count_,
1272
+ BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->dist_histo.data_,
1273
+ arena->dist_histo.total_count_,
1260
1274
  /* max_bits = */
1261
1275
  distance_alphabet_bits,
1262
- dist_depth, dist_bits,
1276
+ arena->dist_depth, arena->dist_bits,
1263
1277
  storage_ix, storage);
1264
- if (BROTLI_IS_OOM(m)) return;
1265
1278
  StoreDataWithHuffmanCodes(input, start_pos, mask, commands,
1266
- n_commands, lit_depth, lit_bits,
1267
- cmd_depth, cmd_bits,
1268
- 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,
1269
1282
  storage_ix, storage);
1270
1283
  }
1271
1284
 
1285
+ BROTLI_FREE(m, arena);
1286
+
1272
1287
  if (is_last) {
1273
1288
  JumpToByteBoundary(storage_ix, storage);
1274
1289
  }
@@ -1309,6 +1324,13 @@ void BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block,
1309
1324
  }
1310
1325
  }
1311
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
+
1312
1334
  #if defined(__cplusplus) || defined(c_plusplus)
1313
1335
  } /* extern "C" */
1314
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
@@ -9,10 +9,11 @@
9
9
  #ifndef BROTLI_ENC_CLUSTER_H_
10
10
  #define BROTLI_ENC_CLUSTER_H_
11
11
 
12
- #include "../common/platform.h"
13
12
  #include <brotli/types.h>
14
- #include "./histogram.h"
15
- #include "./memory.h"
13
+
14
+ #include "../common/platform.h"
15
+ #include "histogram.h"
16
+ #include "memory.h"
16
17
 
17
18
  #if defined(__cplusplus) || defined(c_plusplus)
18
19
  extern "C" {
@@ -28,15 +29,15 @@ typedef struct HistogramPair {
28
29
  #define CODE(X) /* Declaration */;
29
30
 
30
31
  #define FN(X) X ## Literal
31
- #include "./cluster_inc.h" /* NOLINT(build/include) */
32
+ #include "cluster_inc.h" /* NOLINT(build/include) */
32
33
  #undef FN
33
34
 
34
35
  #define FN(X) X ## Command
35
- #include "./cluster_inc.h" /* NOLINT(build/include) */
36
+ #include "cluster_inc.h" /* NOLINT(build/include) */
36
37
  #undef FN
37
38
 
38
39
  #define FN(X) X ## Distance
39
- #include "./cluster_inc.h" /* NOLINT(build/include) */
40
+ #include "cluster_inc.h" /* NOLINT(build/include) */
40
41
  #undef FN
41
42
 
42
43
  #undef CODE