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
@@ -7,27 +7,27 @@
7
7
  /* Algorithms for distributing the literals and commands of a metablock between
8
8
  block types and contexts. */
9
9
 
10
- #include "./metablock.h"
10
+ #include "metablock.h"
11
+
12
+ #include <brotli/types.h>
11
13
 
12
14
  #include "../common/constants.h"
13
15
  #include "../common/context.h"
14
16
  #include "../common/platform.h"
15
- #include <brotli/types.h>
16
- #include "./bit_cost.h"
17
- #include "./block_splitter.h"
18
- #include "./cluster.h"
19
- #include "./entropy_encode.h"
20
- #include "./histogram.h"
21
- #include "./memory.h"
22
- #include "./quality.h"
17
+ #include "bit_cost.h"
18
+ #include "block_splitter.h"
19
+ #include "cluster.h"
20
+ #include "entropy_encode.h"
21
+ #include "histogram.h"
22
+ #include "memory.h"
23
+ #include "quality.h"
23
24
 
24
25
  #if defined(__cplusplus) || defined(c_plusplus)
25
26
  extern "C" {
26
27
  #endif
27
28
 
28
- void BrotliInitDistanceParams(BrotliEncoderParams* params,
29
- uint32_t npostfix, uint32_t ndirect) {
30
- BrotliDistanceParams* dist_params = &params->dist;
29
+ void BrotliInitDistanceParams(BrotliDistanceParams* dist_params,
30
+ uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) {
31
31
  uint32_t alphabet_size_max;
32
32
  uint32_t alphabet_size_limit;
33
33
  uint32_t max_distance;
@@ -41,7 +41,7 @@ void BrotliInitDistanceParams(BrotliEncoderParams* params,
41
41
  max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) -
42
42
  (1U << (npostfix + 2));
43
43
 
44
- if (params->large_window) {
44
+ if (large_window) {
45
45
  BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
46
46
  BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);
47
47
  alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
@@ -83,14 +83,14 @@ static BROTLI_BOOL ComputeDistanceCost(const Command* cmds,
83
83
  size_t num_commands,
84
84
  const BrotliDistanceParams* orig_params,
85
85
  const BrotliDistanceParams* new_params,
86
- double* cost) {
86
+ double* cost,
87
+ HistogramDistance* tmp) {
87
88
  size_t i;
88
89
  BROTLI_BOOL equal_params = BROTLI_FALSE;
89
90
  uint16_t dist_prefix;
90
91
  uint32_t dist_extra;
91
92
  double extra_bits = 0.0;
92
- HistogramDistance histo;
93
- HistogramClearDistance(&histo);
93
+ HistogramClearDistance(tmp);
94
94
 
95
95
  if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&
96
96
  orig_params->num_direct_distance_codes ==
@@ -114,12 +114,12 @@ static BROTLI_BOOL ComputeDistanceCost(const Command* cmds,
114
114
  &dist_prefix,
115
115
  &dist_extra);
116
116
  }
117
- HistogramAddDistance(&histo, dist_prefix & 0x3FF);
117
+ HistogramAddDistance(tmp, dist_prefix & 0x3FF);
118
118
  extra_bits += dist_prefix >> 10;
119
119
  }
120
120
  }
121
121
 
122
- *cost = BrotliPopulationCostDistance(&histo) + extra_bits;
122
+ *cost = BrotliPopulationCostDistance(tmp) + extra_bits;
123
123
  return BROTLI_TRUE;
124
124
  }
125
125
 
@@ -147,43 +147,46 @@ void BrotliBuildMetaBlock(MemoryManager* m,
147
147
  uint32_t ndirect_msb = 0;
148
148
  BROTLI_BOOL check_orig = BROTLI_TRUE;
149
149
  double best_dist_cost = 1e99;
150
- BrotliEncoderParams orig_params = *params;
151
- BrotliEncoderParams new_params = *params;
150
+ BrotliDistanceParams orig_params = params->dist;
151
+ BrotliDistanceParams new_params = params->dist;
152
+ HistogramDistance* tmp = BROTLI_ALLOC(m, HistogramDistance, 1);
153
+
154
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return;
152
155
 
153
156
  for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX; npostfix++) {
154
157
  for (; ndirect_msb < 16; ndirect_msb++) {
155
158
  uint32_t ndirect = ndirect_msb << npostfix;
156
159
  BROTLI_BOOL skip;
157
160
  double dist_cost;
158
- BrotliInitDistanceParams(&new_params, npostfix, ndirect);
159
- if (npostfix == orig_params.dist.distance_postfix_bits &&
160
- ndirect == orig_params.dist.num_direct_distance_codes) {
161
+ BrotliInitDistanceParams(&new_params, npostfix, ndirect,
162
+ params->large_window);
163
+ if (npostfix == orig_params.distance_postfix_bits &&
164
+ ndirect == orig_params.num_direct_distance_codes) {
161
165
  check_orig = BROTLI_FALSE;
162
166
  }
163
167
  skip = !ComputeDistanceCost(
164
- cmds, num_commands,
165
- &orig_params.dist, &new_params.dist, &dist_cost);
168
+ cmds, num_commands, &orig_params, &new_params, &dist_cost, tmp);
166
169
  if (skip || (dist_cost > best_dist_cost)) {
167
170
  break;
168
171
  }
169
172
  best_dist_cost = dist_cost;
170
- params->dist = new_params.dist;
173
+ params->dist = new_params;
171
174
  }
172
175
  if (ndirect_msb > 0) ndirect_msb--;
173
176
  ndirect_msb /= 2;
174
177
  }
175
178
  if (check_orig) {
176
179
  double dist_cost;
177
- ComputeDistanceCost(cmds, num_commands,
178
- &orig_params.dist, &orig_params.dist, &dist_cost);
180
+ ComputeDistanceCost(cmds, num_commands, &orig_params, &orig_params,
181
+ &dist_cost, tmp);
179
182
  if (dist_cost < best_dist_cost) {
180
183
  /* NB: currently unused; uncomment when more param tuning is added. */
181
184
  /* best_dist_cost = dist_cost; */
182
- params->dist = orig_params.dist;
185
+ params->dist = orig_params;
183
186
  }
184
187
  }
185
- RecomputeDistancePrefixes(cmds, num_commands,
186
- &orig_params.dist, &params->dist);
188
+ BROTLI_FREE(m, tmp);
189
+ RecomputeDistancePrefixes(cmds, num_commands, &orig_params, &params->dist);
187
190
 
188
191
  BrotliSplitBlock(m, cmds, num_commands,
189
192
  ringbuffer, pos, mask, params,
@@ -284,15 +287,15 @@ void BrotliBuildMetaBlock(MemoryManager* m,
284
287
  }
285
288
 
286
289
  #define FN(X) X ## Literal
287
- #include "./metablock_inc.h" /* NOLINT(build/include) */
290
+ #include "metablock_inc.h" /* NOLINT(build/include) */
288
291
  #undef FN
289
292
 
290
293
  #define FN(X) X ## Command
291
- #include "./metablock_inc.h" /* NOLINT(build/include) */
294
+ #include "metablock_inc.h" /* NOLINT(build/include) */
292
295
  #undef FN
293
296
 
294
297
  #define FN(X) X ## Distance
295
- #include "./metablock_inc.h" /* NOLINT(build/include) */
298
+ #include "metablock_inc.h" /* NOLINT(build/include) */
296
299
  #undef FN
297
300
 
298
301
  #define BROTLI_MAX_STATIC_CONTEXTS 13
@@ -535,17 +538,21 @@ static void MapStaticContexts(MemoryManager* m,
535
538
  }
536
539
  }
537
540
 
538
- static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
539
- MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,
540
- uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,
541
- const size_t num_contexts, const uint32_t* static_context_map,
542
- const Command* commands, size_t n_commands, MetaBlockSplit* mb) {
541
+ typedef struct GreedyMetablockArena {
543
542
  union {
544
543
  BlockSplitterLiteral plain;
545
544
  ContextBlockSplitter ctx;
546
545
  } lit_blocks;
547
546
  BlockSplitterCommand cmd_blocks;
548
547
  BlockSplitterDistance dist_blocks;
548
+ } GreedyMetablockArena;
549
+
550
+ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
551
+ MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer,
552
+ size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2,
553
+ ContextLut literal_context_lut, const size_t num_contexts,
554
+ const uint32_t* static_context_map, const Command* commands,
555
+ size_t n_commands, MetaBlockSplit* mb) {
549
556
  size_t num_literals = 0;
550
557
  size_t i;
551
558
  for (i = 0; i < n_commands; ++i) {
@@ -553,20 +560,20 @@ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
553
560
  }
554
561
 
555
562
  if (num_contexts == 1) {
556
- InitBlockSplitterLiteral(m, &lit_blocks.plain, 256, 512, 400.0,
563
+ InitBlockSplitterLiteral(m, &arena->lit_blocks.plain, 256, 512, 400.0,
557
564
  num_literals, &mb->literal_split, &mb->literal_histograms,
558
565
  &mb->literal_histograms_size);
559
566
  } else {
560
- InitContextBlockSplitter(m, &lit_blocks.ctx, 256, num_contexts, 512, 400.0,
561
- num_literals, &mb->literal_split, &mb->literal_histograms,
567
+ InitContextBlockSplitter(m, &arena->lit_blocks.ctx, 256, num_contexts, 512,
568
+ 400.0, num_literals, &mb->literal_split, &mb->literal_histograms,
562
569
  &mb->literal_histograms_size);
563
570
  }
564
571
  if (BROTLI_IS_OOM(m)) return;
565
- InitBlockSplitterCommand(m, &cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS, 1024,
566
- 500.0, n_commands, &mb->command_split, &mb->command_histograms,
572
+ InitBlockSplitterCommand(m, &arena->cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS,
573
+ 1024, 500.0, n_commands, &mb->command_split, &mb->command_histograms,
567
574
  &mb->command_histograms_size);
568
575
  if (BROTLI_IS_OOM(m)) return;
569
- InitBlockSplitterDistance(m, &dist_blocks, 64, 512, 100.0, n_commands,
576
+ InitBlockSplitterDistance(m, &arena->dist_blocks, 64, 512, 100.0, n_commands,
570
577
  &mb->distance_split, &mb->distance_histograms,
571
578
  &mb->distance_histograms_size);
572
579
  if (BROTLI_IS_OOM(m)) return;
@@ -574,15 +581,15 @@ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
574
581
  for (i = 0; i < n_commands; ++i) {
575
582
  const Command cmd = commands[i];
576
583
  size_t j;
577
- BlockSplitterAddSymbolCommand(&cmd_blocks, cmd.cmd_prefix_);
584
+ BlockSplitterAddSymbolCommand(&arena->cmd_blocks, cmd.cmd_prefix_);
578
585
  for (j = cmd.insert_len_; j != 0; --j) {
579
586
  uint8_t literal = ringbuffer[pos & mask];
580
587
  if (num_contexts == 1) {
581
- BlockSplitterAddSymbolLiteral(&lit_blocks.plain, literal);
588
+ BlockSplitterAddSymbolLiteral(&arena->lit_blocks.plain, literal);
582
589
  } else {
583
590
  size_t context =
584
591
  BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);
585
- ContextBlockSplitterAddSymbol(&lit_blocks.ctx, m, literal,
592
+ ContextBlockSplitterAddSymbol(&arena->lit_blocks.ctx, m, literal,
586
593
  static_context_map[context]);
587
594
  if (BROTLI_IS_OOM(m)) return;
588
595
  }
@@ -595,21 +602,24 @@ static BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(
595
602
  prev_byte2 = ringbuffer[(pos - 2) & mask];
596
603
  prev_byte = ringbuffer[(pos - 1) & mask];
597
604
  if (cmd.cmd_prefix_ >= 128) {
598
- BlockSplitterAddSymbolDistance(&dist_blocks, cmd.dist_prefix_ & 0x3FF);
605
+ BlockSplitterAddSymbolDistance(
606
+ &arena->dist_blocks, cmd.dist_prefix_ & 0x3FF);
599
607
  }
600
608
  }
601
609
  }
602
610
 
603
611
  if (num_contexts == 1) {
604
612
  BlockSplitterFinishBlockLiteral(
605
- &lit_blocks.plain, /* is_final = */ BROTLI_TRUE);
613
+ &arena->lit_blocks.plain, /* is_final = */ BROTLI_TRUE);
606
614
  } else {
607
615
  ContextBlockSplitterFinishBlock(
608
- &lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);
616
+ &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);
609
617
  if (BROTLI_IS_OOM(m)) return;
610
618
  }
611
- BlockSplitterFinishBlockCommand(&cmd_blocks, /* is_final = */ BROTLI_TRUE);
612
- BlockSplitterFinishBlockDistance(&dist_blocks, /* is_final = */ BROTLI_TRUE);
619
+ BlockSplitterFinishBlockCommand(
620
+ &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE);
621
+ BlockSplitterFinishBlockDistance(
622
+ &arena->dist_blocks, /* is_final = */ BROTLI_TRUE);
613
623
 
614
624
  if (num_contexts > 1) {
615
625
  MapStaticContexts(m, num_contexts, static_context_map, mb);
@@ -628,14 +638,18 @@ void BrotliBuildMetaBlockGreedy(MemoryManager* m,
628
638
  const Command* commands,
629
639
  size_t n_commands,
630
640
  MetaBlockSplit* mb) {
641
+ GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1);
642
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;
631
643
  if (num_contexts == 1) {
632
- BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
633
- prev_byte2, literal_context_lut, 1, NULL, commands, n_commands, mb);
644
+ BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,
645
+ prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands,
646
+ n_commands, mb);
634
647
  } else {
635
- BrotliBuildMetaBlockGreedyInternal(m, ringbuffer, pos, mask, prev_byte,
636
- prev_byte2, literal_context_lut, num_contexts, static_context_map,
637
- commands, n_commands, mb);
648
+ BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,
649
+ prev_byte, prev_byte2, literal_context_lut, num_contexts,
650
+ static_context_map, commands, n_commands, mb);
638
651
  }
652
+ BROTLI_FREE(m, arena);
639
653
  }
640
654
 
641
655
  void BrotliOptimizeHistograms(uint32_t num_distance_codes,
@@ -10,14 +10,15 @@
10
10
  #ifndef BROTLI_ENC_METABLOCK_H_
11
11
  #define BROTLI_ENC_METABLOCK_H_
12
12
 
13
+ #include <brotli/types.h>
14
+
13
15
  #include "../common/context.h"
14
16
  #include "../common/platform.h"
15
- #include <brotli/types.h>
16
- #include "./block_splitter.h"
17
- #include "./command.h"
18
- #include "./histogram.h"
19
- #include "./memory.h"
20
- #include "./quality.h"
17
+ #include "block_splitter.h"
18
+ #include "command.h"
19
+ #include "histogram.h"
20
+ #include "memory.h"
21
+ #include "quality.h"
21
22
 
22
23
  #if defined(__cplusplus) || defined(c_plusplus)
23
24
  extern "C" {
@@ -95,8 +96,8 @@ BROTLI_INTERNAL void BrotliBuildMetaBlockGreedy(
95
96
  BROTLI_INTERNAL void BrotliOptimizeHistograms(uint32_t num_distance_codes,
96
97
  MetaBlockSplit* mb);
97
98
 
98
- BROTLI_INTERNAL void BrotliInitDistanceParams(BrotliEncoderParams* params,
99
- uint32_t npostfix, uint32_t ndirect);
99
+ BROTLI_INTERNAL void BrotliInitDistanceParams(BrotliDistanceParams* params,
100
+ uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window);
100
101
 
101
102
  #if defined(__cplusplus) || defined(c_plusplus)
102
103
  } /* extern "C" */
@@ -27,6 +27,9 @@ typedef struct FN(BlockSplitter) {
27
27
  HistogramType* histograms_; /* not owned */
28
28
  size_t* histograms_size_; /* not owned */
29
29
 
30
+ /* Temporary storage for BlockSplitterFinishBlock. */
31
+ HistogramType combined_histo[2];
32
+
30
33
  /* The number of symbols that we want to collect before deciding on whether
31
34
  or not to merge the block with a previous one or emit a new block. */
32
35
  size_t target_block_size_;
@@ -104,17 +107,16 @@ static void FN(BlockSplitterFinishBlock)(
104
107
  } else if (self->block_size_ > 0) {
105
108
  double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_,
106
109
  self->alphabet_size_);
107
- HistogramType combined_histo[2];
108
110
  double combined_entropy[2];
109
111
  double diff[2];
110
112
  size_t j;
111
113
  for (j = 0; j < 2; ++j) {
112
114
  size_t last_histogram_ix = self->last_histogram_ix_[j];
113
- combined_histo[j] = histograms[self->curr_histogram_ix_];
114
- FN(HistogramAddHistogram)(&combined_histo[j],
115
+ self->combined_histo[j] = histograms[self->curr_histogram_ix_];
116
+ FN(HistogramAddHistogram)(&self->combined_histo[j],
115
117
  &histograms[last_histogram_ix]);
116
118
  combined_entropy[j] = BitsEntropy(
117
- &combined_histo[j].data_[0], self->alphabet_size_);
119
+ &self->combined_histo[j].data_[0], self->alphabet_size_);
118
120
  diff[j] = combined_entropy[j] - entropy - last_entropy[j];
119
121
  }
120
122
 
@@ -141,7 +143,7 @@ static void FN(BlockSplitterFinishBlock)(
141
143
  split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;
142
144
  split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];
143
145
  BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1);
144
- histograms[self->last_histogram_ix_[0]] = combined_histo[1];
146
+ histograms[self->last_histogram_ix_[0]] = self->combined_histo[1];
145
147
  last_entropy[1] = last_entropy[0];
146
148
  last_entropy[0] = combined_entropy[1];
147
149
  ++self->num_blocks_;
@@ -152,7 +154,7 @@ static void FN(BlockSplitterFinishBlock)(
152
154
  } else {
153
155
  /* Combine this block with last block. */
154
156
  split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;
155
- histograms[self->last_histogram_ix_[0]] = combined_histo[0];
157
+ histograms[self->last_histogram_ix_[0]] = self->combined_histo[0];
156
158
  last_entropy[0] = combined_entropy[0];
157
159
  if (split->num_types == 1) {
158
160
  last_entropy[1] = last_entropy[0];
@@ -10,13 +10,13 @@
10
10
  #define BROTLI_ENC_PARAMS_H_
11
11
 
12
12
  #include <brotli/encode.h>
13
- #include "./encoder_dict.h"
13
+
14
+ #include "encoder_dict.h"
14
15
 
15
16
  typedef struct BrotliHasherParams {
16
17
  int type;
17
18
  int bucket_bits;
18
19
  int block_bits;
19
- int hash_len;
20
20
  int num_last_distances_to_check;
21
21
  } BrotliHasherParams;
22
22
 
@@ -40,7 +40,8 @@ typedef struct BrotliEncoderParams {
40
40
  BROTLI_BOOL large_window;
41
41
  BrotliHasherParams hasher;
42
42
  BrotliDistanceParams dist;
43
- BrotliEncoderDictionary dictionary;
43
+ /* TODO(eustas): rename to BrotliShared... */
44
+ SharedEncoderDictionary dictionary;
44
45
  } BrotliEncoderParams;
45
46
 
46
47
  #endif /* BROTLI_ENC_PARAMS_H_ */
@@ -10,10 +10,11 @@
10
10
  #ifndef BROTLI_ENC_PREFIX_H_
11
11
  #define BROTLI_ENC_PREFIX_H_
12
12
 
13
+ #include <brotli/types.h>
14
+
13
15
  #include "../common/constants.h"
14
16
  #include "../common/platform.h"
15
- #include <brotli/types.h>
16
- #include "./fast_log.h"
17
+ #include "fast_log.h"
17
18
 
18
19
  #if defined(__cplusplus) || defined(c_plusplus)
19
20
  extern "C" {
@@ -10,9 +10,10 @@
10
10
  #ifndef BROTLI_ENC_QUALITY_H_
11
11
  #define BROTLI_ENC_QUALITY_H_
12
12
 
13
- #include "../common/platform.h"
14
13
  #include <brotli/encode.h>
15
- #include "./params.h"
14
+
15
+ #include "../common/platform.h"
16
+ #include "params.h"
16
17
 
17
18
  #define FAST_ONE_PASS_COMPRESSION_QUALITY 0
18
19
  #define FAST_TWO_PASS_COMPRESSION_QUALITY 1
@@ -118,6 +119,41 @@ static BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch(
118
119
  return params->quality < 9 ? 64 : 512;
119
120
  }
120
121
 
122
+ /* Quality to hasher mapping:
123
+
124
+ - q02: h02 (longest_match_quickly), b16, l5
125
+
126
+ - q03: h03 (longest_match_quickly), b17, l5
127
+
128
+ - q04: h04 (longest_match_quickly), b17, l5
129
+ - q04: h54 (longest_match_quickly), b20, l7 | for large files
130
+
131
+ - q05: h05 (longest_match ), b14, l4
132
+ - q05: h06 (longest_match64 ), b15, l5 | for large files
133
+ - q05: h40 (forgetful_chain ), b15, l4 | for small window
134
+
135
+ - q06: h05 (longest_match ), b14, l4
136
+ - q06: h06 (longest_match64 ), b15, l5 | for large files
137
+ - q06: h40 (forgetful_chain ), b15, l4 | for small window
138
+
139
+ - q07: h05 (longest_match ), b15, l4
140
+ - q07: h06 (longest_match64 ), b15, l5 | for large files
141
+ - q07: h41 (forgetful_chain ), b15, l4 | for small window
142
+
143
+ - q08: h05 (longest_match ), b15, l4
144
+ - q08: h06 (longest_match64 ), b15, l5 | for large files
145
+ - q08: h41 (forgetful_chain ), b15, l4 | for small window
146
+
147
+ - q09: h05 (longest_match ), b15, l4
148
+ - q09: h06 (longest_match64 ), b15, l5 | for large files
149
+ - q09: h42 (forgetful_chain ), b15, l4 | for small window
150
+
151
+ - q10: t10 (to_binary_tree ), b17, l128
152
+
153
+ - q11: t10 (to_binary_tree ), b17, l128
154
+
155
+ Where "q" is quality, "h" is hasher type, "b" is bucket bits,
156
+ "l" is source len. */
121
157
  static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
122
158
  BrotliHasherParams* hparams) {
123
159
  if (params->quality > 9) {
@@ -132,10 +168,11 @@ static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
132
168
  hparams->type = 6;
133
169
  hparams->block_bits = params->quality - 1;
134
170
  hparams->bucket_bits = 15;
135
- hparams->hash_len = 5;
136
171
  hparams->num_last_distances_to_check =
137
172
  params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;
138
173
  } else {
174
+ /* TODO(eustas): often previous setting (H6) is faster and denser; consider
175
+ adding an option to use it. */
139
176
  hparams->type = 5;
140
177
  hparams->block_bits = params->quality - 1;
141
178
  hparams->bucket_bits = params->quality < 7 ? 14 : 15;
@@ -11,10 +11,11 @@
11
11
 
12
12
  #include <string.h> /* memcpy */
13
13
 
14
- #include "../common/platform.h"
15
14
  #include <brotli/types.h>
16
- #include "./memory.h"
17
- #include "./quality.h"
15
+
16
+ #include "../common/platform.h"
17
+ #include "memory.h"
18
+ #include "quality.h"
18
19
 
19
20
  #if defined(__cplusplus) || defined(c_plusplus)
20
21
  extern "C" {
@@ -0,0 +1,104 @@
1
+ /* Copyright 2022 Google Inc. All Rights Reserved.
2
+
3
+ Distributed under MIT license.
4
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5
+ */
6
+
7
+ /* Encoder state. */
8
+
9
+ #ifndef BROTLI_ENC_STATE_H_
10
+ #define BROTLI_ENC_STATE_H_
11
+
12
+ #include <brotli/types.h>
13
+
14
+ #include "command.h"
15
+ #include "compress_fragment.h"
16
+ #include "compress_fragment_two_pass.h"
17
+ #include "hash.h"
18
+ #include "memory.h"
19
+ #include "params.h"
20
+ #include "ringbuffer.h"
21
+
22
+ typedef enum BrotliEncoderStreamState {
23
+ /* Default state. */
24
+ BROTLI_STREAM_PROCESSING = 0,
25
+ /* Intermediate state; after next block is emitted, byte-padding should be
26
+ performed before getting back to default state. */
27
+ BROTLI_STREAM_FLUSH_REQUESTED = 1,
28
+ /* Last metablock was produced; no more input is acceptable. */
29
+ BROTLI_STREAM_FINISHED = 2,
30
+ /* Flushing compressed block and writing meta-data block header. */
31
+ BROTLI_STREAM_METADATA_HEAD = 3,
32
+ /* Writing metadata block body. */
33
+ BROTLI_STREAM_METADATA_BODY = 4
34
+ } BrotliEncoderStreamState;
35
+
36
+ typedef enum BrotliEncoderFlintState {
37
+ BROTLI_FLINT_NEEDS_2_BYTES = 2,
38
+ BROTLI_FLINT_NEEDS_1_BYTE = 1,
39
+ BROTLI_FLINT_WAITING_FOR_PROCESSING = 0,
40
+ BROTLI_FLINT_WAITING_FOR_FLUSHING = -1,
41
+ BROTLI_FLINT_DONE = -2
42
+ } BrotliEncoderFlintState;
43
+
44
+ typedef struct BrotliEncoderStateStruct {
45
+ BrotliEncoderParams params;
46
+
47
+ MemoryManager memory_manager_;
48
+
49
+ uint64_t input_pos_;
50
+ RingBuffer ringbuffer_;
51
+ size_t cmd_alloc_size_;
52
+ Command* commands_;
53
+ size_t num_commands_;
54
+ size_t num_literals_;
55
+ size_t last_insert_len_;
56
+ uint64_t last_flush_pos_;
57
+ uint64_t last_processed_pos_;
58
+ int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES];
59
+ int saved_dist_cache_[4];
60
+ uint16_t last_bytes_;
61
+ uint8_t last_bytes_bits_;
62
+ /* "Flint" is a tiny uncompressed block emitted before the continuation
63
+ block to unwire literal context from previous data. Despite being int8_t,
64
+ field is actually BrotliEncoderFlintState enum. */
65
+ int8_t flint_;
66
+ uint8_t prev_byte_;
67
+ uint8_t prev_byte2_;
68
+ size_t storage_size_;
69
+ uint8_t* storage_;
70
+
71
+ Hasher hasher_;
72
+
73
+ /* Hash table for FAST_ONE_PASS_COMPRESSION_QUALITY mode. */
74
+ int small_table_[1 << 10]; /* 4KiB */
75
+ int* large_table_; /* Allocated only when needed */
76
+ size_t large_table_size_;
77
+
78
+ BrotliOnePassArena* one_pass_arena_;
79
+ BrotliTwoPassArena* two_pass_arena_;
80
+
81
+ /* Command and literal buffers for FAST_TWO_PASS_COMPRESSION_QUALITY. */
82
+ uint32_t* command_buf_;
83
+ uint8_t* literal_buf_;
84
+
85
+ uint64_t total_in_;
86
+ uint8_t* next_out_;
87
+ size_t available_out_;
88
+ uint64_t total_out_;
89
+ /* Temporary buffer for padding flush bits or metadata block header / body. */
90
+ union {
91
+ uint64_t u64[2];
92
+ uint8_t u8[16];
93
+ } tiny_buf_;
94
+ uint32_t remaining_metadata_bytes_;
95
+ BrotliEncoderStreamState stream_state_;
96
+
97
+ BROTLI_BOOL is_last_block_emitted_;
98
+ BROTLI_BOOL is_initialized_;
99
+ } BrotliEncoderStateStruct;
100
+
101
+ typedef struct BrotliEncoderStateStruct BrotliEncoderStateInternal;
102
+ #define BrotliEncoderState BrotliEncoderStateInternal
103
+
104
+ #endif // BROTLI_ENC_STATE_H_