brotli 0.2.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +34 -0
  3. data/.github/workflows/publish.yml +34 -0
  4. data/Gemfile +6 -3
  5. data/Rakefile +16 -9
  6. data/brotli.gemspec +7 -13
  7. data/ext/brotli/brotli.c +209 -31
  8. data/ext/brotli/buffer.c +1 -7
  9. data/ext/brotli/buffer.h +1 -1
  10. data/ext/brotli/extconf.rb +20 -18
  11. data/lib/brotli/version.rb +1 -1
  12. data/test/brotli_test.rb +104 -0
  13. data/test/brotli_writer_test.rb +36 -0
  14. data/test/test_helper.rb +8 -0
  15. data/vendor/brotli/c/common/constants.c +15 -0
  16. data/vendor/brotli/c/common/constants.h +136 -0
  17. data/vendor/brotli/c/common/context.c +156 -0
  18. data/vendor/brotli/c/common/context.h +4 -152
  19. data/vendor/brotli/c/common/dictionary.bin.br +0 -0
  20. data/vendor/brotli/c/common/dictionary.c +10 -1
  21. data/vendor/brotli/c/common/platform.c +22 -0
  22. data/vendor/brotli/c/common/platform.h +43 -17
  23. data/vendor/brotli/c/common/transform.c +59 -3
  24. data/vendor/brotli/c/common/transform.h +5 -0
  25. data/vendor/brotli/c/common/version.h +2 -2
  26. data/vendor/brotli/c/dec/bit_reader.c +28 -0
  27. data/vendor/brotli/c/dec/bit_reader.h +58 -16
  28. data/vendor/brotli/c/dec/decode.c +353 -251
  29. data/vendor/brotli/c/dec/huffman.h +6 -12
  30. data/vendor/brotli/c/dec/prefix.h +0 -18
  31. data/vendor/brotli/c/dec/state.c +9 -14
  32. data/vendor/brotli/c/dec/state.h +144 -37
  33. data/vendor/brotli/c/enc/backward_references.c +8 -7
  34. data/vendor/brotli/c/enc/backward_references.h +5 -4
  35. data/vendor/brotli/c/enc/backward_references_hq.c +51 -33
  36. data/vendor/brotli/c/enc/backward_references_hq.h +11 -8
  37. data/vendor/brotli/c/enc/backward_references_inc.h +24 -14
  38. data/vendor/brotli/c/enc/block_splitter.c +3 -3
  39. data/vendor/brotli/c/enc/block_splitter_inc.h +15 -6
  40. data/vendor/brotli/c/enc/brotli_bit_stream.c +13 -30
  41. data/vendor/brotli/c/enc/cluster_inc.h +6 -3
  42. data/vendor/brotli/c/enc/command.c +28 -0
  43. data/vendor/brotli/c/enc/command.h +12 -12
  44. data/vendor/brotli/c/enc/compress_fragment_two_pass.c +1 -1
  45. data/vendor/brotli/c/enc/dictionary_hash.c +1826 -1100
  46. data/vendor/brotli/c/enc/dictionary_hash.h +2 -1
  47. data/vendor/brotli/c/enc/encode.c +104 -39
  48. data/vendor/brotli/c/enc/encoder_dict.c +3 -2
  49. data/vendor/brotli/c/enc/encoder_dict.h +3 -1
  50. data/vendor/brotli/c/enc/entropy_encode.c +2 -0
  51. data/vendor/brotli/c/enc/entropy_encode.h +2 -2
  52. data/vendor/brotli/c/enc/fast_log.c +105 -0
  53. data/vendor/brotli/c/enc/fast_log.h +19 -100
  54. data/vendor/brotli/c/enc/find_match_length.h +2 -3
  55. data/vendor/brotli/c/enc/hash.h +80 -90
  56. data/vendor/brotli/c/enc/hash_composite_inc.h +52 -63
  57. data/vendor/brotli/c/enc/hash_forgetful_chain_inc.h +88 -49
  58. data/vendor/brotli/c/enc/hash_longest_match64_inc.h +50 -50
  59. data/vendor/brotli/c/enc/hash_longest_match_inc.h +53 -50
  60. data/vendor/brotli/c/enc/hash_longest_match_quickly_inc.h +91 -60
  61. data/vendor/brotli/c/enc/hash_rolling_inc.h +23 -27
  62. data/vendor/brotli/c/enc/hash_to_binary_tree_inc.h +39 -38
  63. data/vendor/brotli/c/enc/memory.h +24 -12
  64. data/vendor/brotli/c/enc/metablock.c +23 -27
  65. data/vendor/brotli/c/enc/metablock_inc.h +1 -1
  66. data/vendor/brotli/c/enc/params.h +3 -1
  67. data/vendor/brotli/c/enc/ringbuffer.h +4 -1
  68. data/vendor/brotli/c/enc/utf8_util.c +1 -1
  69. data/vendor/brotli/c/enc/write_bits.h +27 -25
  70. data/vendor/brotli/c/include/brotli/encode.h +22 -1
  71. data/vendor/brotli/c/include/brotli/port.h +14 -0
  72. metadata +17 -97
  73. data/.travis.yml +0 -31
  74. data/docs/Brotli.html +0 -485
  75. data/docs/Brotli/Error.html +0 -124
  76. data/docs/_index.html +0 -122
  77. data/docs/class_list.html +0 -51
  78. data/docs/css/common.css +0 -1
  79. data/docs/css/full_list.css +0 -58
  80. data/docs/css/style.css +0 -496
  81. data/docs/file.README.html +0 -127
  82. data/docs/file_list.html +0 -56
  83. data/docs/frames.html +0 -17
  84. data/docs/index.html +0 -127
  85. data/docs/js/app.js +0 -292
  86. data/docs/js/full_list.js +0 -216
  87. data/docs/js/jquery.js +0 -4
  88. data/docs/method_list.html +0 -67
  89. data/docs/top-level-namespace.html +0 -110
  90. data/spec/brotli_spec.rb +0 -88
  91. data/spec/inflate_spec.rb +0 -75
  92. data/spec/spec_helper.rb +0 -4
@@ -18,12 +18,6 @@ extern "C" {
18
18
 
19
19
  #define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15
20
20
 
21
- /* Maximum possible Huffman table size for an alphabet size of (index * 32),
22
- max code length 15 and root table bits 8. */
23
- static const uint16_t kMaxHuffmanTableSize[] = {
24
- 256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
25
- 854, 886, 920, 952, 984, 1016, 1048, 1080, 1112, 1144, 1176, 1208, 1240, 1272,
26
- 1304, 1336, 1368, 1400, 1432, 1464, 1496, 1528};
27
21
  /* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */
28
22
  #define BROTLI_HUFFMAN_MAX_SIZE_26 396
29
23
  /* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */
@@ -82,7 +76,7 @@ typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;
82
76
 
83
77
  static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
84
78
  const uint16_t value) {
85
- return ((value & 0xFFFF) << 16) | (bits & 0xFF);
79
+ return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);
86
80
  }
87
81
 
88
82
  #define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)
@@ -100,7 +94,7 @@ BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
100
94
  /* Builds Huffman lookup table assuming code lengths are in symbol order.
101
95
  Returns size of resulting table. */
102
96
  BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
103
- int root_bits, const uint16_t* const symbol_lists, uint16_t* count_arg);
97
+ int root_bits, const uint16_t* const symbol_lists, uint16_t* count);
104
98
 
105
99
  /* Builds a simple Huffman table. The |num_symbols| parameter is to be
106
100
  interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,
@@ -110,13 +104,13 @@ BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
110
104
  int root_bits, uint16_t* symbols, uint32_t num_symbols);
111
105
 
112
106
  /* Contains a collection of Huffman trees with the same alphabet size. */
113
- /* max_symbol is needed due to simple codes since log2(alphabet_size) could be
114
- greater than log2(max_symbol). */
107
+ /* alphabet_size_limit is needed due to simple codes, since
108
+ log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */
115
109
  typedef struct {
116
110
  HuffmanCode** htrees;
117
111
  HuffmanCode* codes;
118
- uint16_t alphabet_size;
119
- uint16_t max_symbol;
112
+ uint16_t alphabet_size_max;
113
+ uint16_t alphabet_size_limit;
120
114
  uint16_t num_htrees;
121
115
  } HuffmanTreeGroup;
122
116
 
@@ -13,24 +13,6 @@
13
13
  #include "../common/constants.h"
14
14
  #include <brotli/types.h>
15
15
 
16
- /* Represents the range of values belonging to a prefix code:
17
- [offset, offset + 2^nbits) */
18
- struct PrefixCodeRange {
19
- uint16_t offset;
20
- uint8_t nbits;
21
- };
22
-
23
- static const struct PrefixCodeRange
24
- kBlockLengthPrefixCode[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
25
- { 1, 2}, { 5, 2}, { 9, 2}, { 13, 2},
26
- { 17, 3}, { 25, 3}, { 33, 3}, { 41, 3},
27
- { 49, 4}, { 65, 4}, { 81, 4}, { 97, 4},
28
- { 113, 5}, { 145, 5}, { 177, 5}, { 209, 5},
29
- { 241, 6}, { 305, 6}, { 369, 7}, { 497, 8},
30
- { 753, 9}, { 1265, 10}, {2289, 11}, {4337, 12},
31
- {8433, 13}, {16625, 24}
32
- };
33
-
34
16
  typedef struct CmdLutElement {
35
17
  uint8_t insert_len_extra_bits;
36
18
  uint8_t copy_len_extra_bits;
@@ -33,10 +33,7 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
33
33
  s->state = BROTLI_STATE_UNINITED;
34
34
  s->large_window = 0;
35
35
  s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
36
- s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
37
- s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
38
36
  s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
39
- s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
40
37
  s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
41
38
  s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
42
39
 
@@ -59,8 +56,6 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
59
56
  s->context_map_slice = NULL;
60
57
  s->dist_context_map_slice = NULL;
61
58
 
62
- s->sub_loop_counter = 0;
63
-
64
59
  s->literal_hgroup.codes = NULL;
65
60
  s->literal_hgroup.htrees = NULL;
66
61
  s->insert_copy_hgroup.codes = NULL;
@@ -84,9 +79,6 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
84
79
  s->block_type_trees = NULL;
85
80
  s->block_len_trees = NULL;
86
81
 
87
- /* Make small negative indexes addressable. */
88
- s->symbol_lists = &s->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
89
-
90
82
  s->mtf_upper_bound = 63;
91
83
 
92
84
  s->dictionary = BrotliGetDictionary();
@@ -142,17 +134,20 @@ void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
142
134
  }
143
135
 
144
136
  BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,
145
- HuffmanTreeGroup* group, uint32_t alphabet_size, uint32_t max_symbol,
146
- uint32_t ntrees) {
147
- /* Pack two allocations into one */
148
- const size_t max_table_size = kMaxHuffmanTableSize[(alphabet_size + 31) >> 5];
137
+ HuffmanTreeGroup* group, uint32_t alphabet_size_max,
138
+ uint32_t alphabet_size_limit, uint32_t ntrees) {
139
+ /* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)
140
+ This number is discovered "unlimited" "enough" calculator; it is actually
141
+ a wee bigger than required in several cases (especially for alphabets with
142
+ less than 16 symbols). */
143
+ const size_t max_table_size = alphabet_size_limit + 376;
149
144
  const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
150
145
  const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
151
146
  /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */
152
147
  HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,
153
148
  code_size + htree_size);
154
- group->alphabet_size = (uint16_t)alphabet_size;
155
- group->max_symbol = (uint16_t)max_symbol;
149
+ group->alphabet_size_max = (uint16_t)alphabet_size_max;
150
+ group->alphabet_size_limit = (uint16_t)alphabet_size_limit;
156
151
  group->num_htrees = (uint16_t)ntrees;
157
152
  group->htrees = p;
158
153
  group->codes = (HuffmanCode*)(&p[ntrees]);
@@ -21,6 +21,95 @@
21
21
  extern "C" {
22
22
  #endif
23
23
 
24
+ /* Graphviz diagram that describes state transitions:
25
+
26
+ digraph States {
27
+ graph [compound=true]
28
+ concentrate=true
29
+ node [shape="box"]
30
+
31
+ UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}
32
+ subgraph cluster_metablock_workflow {
33
+ style="rounded"
34
+ label=< <B>METABLOCK CYCLE</B> >
35
+ METABLOCK_BEGIN -> METABLOCK_HEADER
36
+ METABLOCK_HEADER:sw -> METADATA
37
+ METABLOCK_HEADER:s -> UNCOMPRESSED
38
+ METABLOCK_HEADER:se -> METABLOCK_DONE:ne
39
+ METADATA:s -> METABLOCK_DONE:w
40
+ UNCOMPRESSED:s -> METABLOCK_DONE:n
41
+ METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint="false"]
42
+ }
43
+ INITIALIZE -> METABLOCK_BEGIN
44
+ METABLOCK_DONE -> DONE
45
+
46
+ subgraph cluster_compressed_metablock {
47
+ style="rounded"
48
+ label=< <B>COMPRESSED METABLOCK</B> >
49
+
50
+ subgraph cluster_command {
51
+ style="rounded"
52
+ label=< <B>HOT LOOP</B> >
53
+
54
+ _METABLOCK_DONE_PORT_ [shape=point style=invis]
55
+
56
+ {
57
+ // Set different shape for nodes returning from "compressed metablock".
58
+ node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;
59
+ CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;
60
+ }
61
+
62
+ CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY
63
+
64
+ // IO ("write") nodes are not in the hot loop!
65
+ CMD_INNER_WRITE [style=dashed]
66
+ CMD_INNER -> CMD_INNER_WRITE
67
+ CMD_POST_WRITE_1 [style=dashed]
68
+ CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1
69
+ CMD_POST_WRITE_2 [style=dashed]
70
+ CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2
71
+
72
+ CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint="false"]
73
+ CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}
74
+ [constraint="false"]
75
+ CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint="false"]
76
+ CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint="false"]
77
+ CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint="false"]
78
+ CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint="false"]
79
+ {rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;
80
+ CMD_POST_WRAP_COPY}
81
+ {rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}
82
+
83
+ {CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->
84
+ _METABLOCK_DONE_PORT_ [style=invis]
85
+ {CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_
86
+ [constraint="false" style=invis]
87
+ }
88
+
89
+ BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n
90
+ HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3
91
+ HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1
92
+ CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP
93
+ TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e
94
+ BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n
95
+
96
+ HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint="false"]
97
+ {rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}
98
+ {rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;
99
+ TREE_GROUP}
100
+ }
101
+ METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n
102
+
103
+ _METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se
104
+ [constraint="false" ltail=cluster_command]
105
+
106
+ UNINITED [shape=Mdiamond];
107
+ DONE [shape=Msquare];
108
+ }
109
+
110
+
111
+ */
112
+
24
113
  typedef enum {
25
114
  BROTLI_STATE_UNINITED,
26
115
  BROTLI_STATE_LARGE_WINDOW_BITS,
@@ -39,6 +128,7 @@ typedef enum {
39
128
  BROTLI_STATE_METABLOCK_DONE,
40
129
  BROTLI_STATE_COMMAND_POST_WRITE_1,
41
130
  BROTLI_STATE_COMMAND_POST_WRITE_2,
131
+ BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,
42
132
  BROTLI_STATE_HUFFMAN_CODE_0,
43
133
  BROTLI_STATE_HUFFMAN_CODE_1,
44
134
  BROTLI_STATE_HUFFMAN_CODE_2,
@@ -46,6 +136,7 @@ typedef enum {
46
136
  BROTLI_STATE_CONTEXT_MAP_1,
47
137
  BROTLI_STATE_CONTEXT_MAP_2,
48
138
  BROTLI_STATE_TREE_GROUP,
139
+ BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,
49
140
  BROTLI_STATE_DONE
50
141
  } BrotliRunningState;
51
142
 
@@ -98,6 +189,50 @@ typedef enum {
98
189
  BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
99
190
  } BrotliRunningReadBlockLengthState;
100
191
 
192
+ typedef struct BrotliMetablockHeaderArena {
193
+ BrotliRunningTreeGroupState substate_tree_group;
194
+ BrotliRunningContextMapState substate_context_map;
195
+ BrotliRunningHuffmanState substate_huffman;
196
+
197
+ uint32_t sub_loop_counter;
198
+
199
+ uint32_t repeat_code_len;
200
+ uint32_t prev_code_len;
201
+
202
+ /* For ReadHuffmanCode. */
203
+ uint32_t symbol;
204
+ uint32_t repeat;
205
+ uint32_t space;
206
+
207
+ /* Huffman table for "histograms". */
208
+ HuffmanCode table[32];
209
+ /* List of heads of symbol chains. */
210
+ uint16_t* symbol_lists;
211
+ /* Storage from symbol_lists. */
212
+ uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
213
+ BROTLI_NUM_COMMAND_SYMBOLS];
214
+ /* Tails of symbol chains. */
215
+ int next_symbol[32];
216
+ uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
217
+ /* Population counts for the code lengths. */
218
+ uint16_t code_length_histo[16];
219
+
220
+ /* For HuffmanTreeGroupDecode. */
221
+ int htree_index;
222
+ HuffmanCode* next;
223
+
224
+ /* For DecodeContextMap. */
225
+ uint32_t context_index;
226
+ uint32_t max_run_length_prefix;
227
+ uint32_t code;
228
+ HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
229
+ } BrotliMetablockHeaderArena;
230
+
231
+ typedef struct BrotliMetablockBodyArena {
232
+ uint8_t dist_extra_bits[544];
233
+ uint32_t dist_offset[544];
234
+ } BrotliMetablockBodyArena;
235
+
101
236
  struct BrotliDecoderStateStruct {
102
237
  BrotliRunningState state;
103
238
 
@@ -110,7 +245,8 @@ struct BrotliDecoderStateStruct {
110
245
  brotli_free_func free_func;
111
246
  void* memory_manager_opaque;
112
247
 
113
- /* Temporary storage for remaining input. */
248
+ /* Temporary storage for remaining input. Brotli stream format is designed in
249
+ a way, that 64 bits are enough to make progress in decoding. */
114
250
  union {
115
251
  uint64_t u64;
116
252
  uint8_t u8[8];
@@ -125,7 +261,6 @@ struct BrotliDecoderStateStruct {
125
261
  int dist_rb_idx;
126
262
  int dist_rb[4];
127
263
  int error_code;
128
- uint32_t sub_loop_counter;
129
264
  uint8_t* ringbuffer;
130
265
  uint8_t* ringbuffer_end;
131
266
  HuffmanCode* htree_command;
@@ -153,13 +288,10 @@ struct BrotliDecoderStateStruct {
153
288
  uint32_t block_type_rb[6];
154
289
  uint32_t distance_postfix_bits;
155
290
  uint32_t num_direct_distance_codes;
156
- int distance_postfix_mask;
157
291
  uint32_t num_dist_htrees;
158
292
  uint8_t* dist_context_map;
159
293
  HuffmanCode* literal_htree;
160
294
  uint8_t dist_htree_index;
161
- uint32_t repeat_code_len;
162
- uint32_t prev_code_len;
163
295
 
164
296
  int copy_length;
165
297
  int distance_code;
@@ -168,33 +300,6 @@ struct BrotliDecoderStateStruct {
168
300
  size_t rb_roundtrips; /* how many times we went around the ring-buffer */
169
301
  size_t partial_pos_out; /* how much output to the user in total */
170
302
 
171
- /* For ReadHuffmanCode. */
172
- uint32_t symbol;
173
- uint32_t repeat;
174
- uint32_t space;
175
-
176
- HuffmanCode table[32];
177
- /* List of heads of symbol chains. */
178
- uint16_t* symbol_lists;
179
- /* Storage from symbol_lists. */
180
- uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
181
- BROTLI_NUM_COMMAND_SYMBOLS];
182
- /* Tails of symbol chains. */
183
- int next_symbol[32];
184
- uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
185
- /* Population counts for the code lengths. */
186
- uint16_t code_length_histo[16];
187
-
188
- /* For HuffmanTreeGroupDecode. */
189
- int htree_index;
190
- HuffmanCode* next;
191
-
192
- /* For DecodeContextMap. */
193
- uint32_t context_index;
194
- uint32_t max_run_length_prefix;
195
- uint32_t code;
196
- HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
197
-
198
303
  /* For InverseMoveToFrontTransform. */
199
304
  uint32_t mtf_upper_bound;
200
305
  uint32_t mtf[64 + 1];
@@ -203,10 +308,7 @@ struct BrotliDecoderStateStruct {
203
308
 
204
309
  /* States inside function calls. */
205
310
  BrotliRunningMetablockHeaderState substate_metablock_header;
206
- BrotliRunningTreeGroupState substate_tree_group;
207
- BrotliRunningContextMapState substate_context_map;
208
311
  BrotliRunningUncompressedState substate_uncompressed;
209
- BrotliRunningHuffmanState substate_huffman;
210
312
  BrotliRunningDecodeUint8State substate_decode_uint8;
211
313
  BrotliRunningReadBlockLengthState substate_read_block_length;
212
314
 
@@ -229,6 +331,11 @@ struct BrotliDecoderStateStruct {
229
331
  const BrotliTransforms* transforms;
230
332
 
231
333
  uint32_t trivial_literal_contexts[8]; /* 256 bits */
334
+
335
+ union {
336
+ BrotliMetablockHeaderArena header;
337
+ BrotliMetablockBodyArena body;
338
+ } arena;
232
339
  };
233
340
 
234
341
  typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;
@@ -241,8 +348,8 @@ BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);
241
348
  BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(
242
349
  BrotliDecoderState* s);
243
350
  BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
244
- BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size,
245
- uint32_t max_symbol, uint32_t ntrees);
351
+ BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size_max,
352
+ uint32_t alphabet_size_limit, uint32_t ntrees);
246
353
 
247
354
  #define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
248
355
 
@@ -9,6 +9,7 @@
9
9
  #include "./backward_references.h"
10
10
 
11
11
  #include "../common/constants.h"
12
+ #include "../common/context.h"
12
13
  #include "../common/dictionary.h"
13
14
  #include "../common/platform.h"
14
15
  #include <brotli/types.h>
@@ -119,17 +120,17 @@ static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance,
119
120
  #undef CAT
120
121
  #undef EXPAND_CAT
121
122
 
122
- void BrotliCreateBackwardReferences(
123
- size_t num_bytes, size_t position, const uint8_t* ringbuffer,
124
- size_t ringbuffer_mask, const BrotliEncoderParams* params,
125
- HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
123
+ void BrotliCreateBackwardReferences(size_t num_bytes,
124
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
125
+ ContextLut literal_context_lut, const BrotliEncoderParams* params,
126
+ Hasher* hasher, int* dist_cache, size_t* last_insert_len,
126
127
  Command* commands, size_t* num_commands, size_t* num_literals) {
127
128
  switch (params->hasher.type) {
128
129
  #define CASE_(N) \
129
130
  case N: \
130
- CreateBackwardReferencesNH ## N( \
131
- num_bytes, position, ringbuffer, \
132
- ringbuffer_mask, params, hasher, dist_cache, \
131
+ CreateBackwardReferencesNH ## N(num_bytes, \
132
+ position, ringbuffer, ringbuffer_mask, \
133
+ literal_context_lut, params, hasher, dist_cache, \
133
134
  last_insert_len, commands, num_commands, num_literals); \
134
135
  return;
135
136
  FOR_GENERIC_HASHERS(CASE_)
@@ -10,6 +10,7 @@
10
10
  #define BROTLI_ENC_BACKWARD_REFERENCES_H_
11
11
 
12
12
  #include "../common/constants.h"
13
+ #include "../common/context.h"
13
14
  #include "../common/dictionary.h"
14
15
  #include "../common/platform.h"
15
16
  #include <brotli/types.h>
@@ -25,10 +26,10 @@ extern "C" {
25
26
  initially the total amount of commands output by previous
26
27
  CreateBackwardReferences calls, and must be incremented by the amount written
27
28
  by this call. */
28
- BROTLI_INTERNAL void BrotliCreateBackwardReferences(
29
- size_t num_bytes, size_t position, const uint8_t* ringbuffer,
30
- size_t ringbuffer_mask, const BrotliEncoderParams* params,
31
- HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
29
+ BROTLI_INTERNAL void BrotliCreateBackwardReferences(size_t num_bytes,
30
+ size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
31
+ ContextLut literal_context_lut, const BrotliEncoderParams* params,
32
+ Hasher* hasher, int* dist_cache, size_t* last_insert_len,
32
33
  Command* commands, size_t* num_commands, size_t* num_literals);
33
34
 
34
35
  #if defined(__cplusplus) || defined(c_plusplus)
@@ -11,6 +11,7 @@
11
11
  #include <string.h> /* memcpy, memset */
12
12
 
13
13
  #include "../common/constants.h"
14
+ #include "../common/context.h"
14
15
  #include "../common/platform.h"
15
16
  #include <brotli/types.h>
16
17
  #include "./command.h"
@@ -26,6 +27,7 @@
26
27
  extern "C" {
27
28
  #endif
28
29
 
30
+ /* BrotliCalculateDistanceCodeLimit(BROTLI_MAX_ALLOWED_DISTANCE, 3, 120). */
29
31
  #define BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE 544
30
32
 
31
33
  static const float kInfinity = 1.7e38f; /* ~= 2 ^ 127 */
@@ -86,14 +88,10 @@ typedef struct ZopfliCostModel {
86
88
  static void InitZopfliCostModel(
87
89
  MemoryManager* m, ZopfliCostModel* self, const BrotliDistanceParams* dist,
88
90
  size_t num_bytes) {
89
- uint32_t distance_histogram_size = dist->alphabet_size;
90
- if (distance_histogram_size > BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE) {
91
- distance_histogram_size = BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE;
92
- }
93
91
  self->num_bytes_ = num_bytes;
94
92
  self->literal_costs_ = BROTLI_ALLOC(m, float, num_bytes + 2);
95
- self->cost_dist_ = BROTLI_ALLOC(m, float, dist->alphabet_size);
96
- self->distance_histogram_size = distance_histogram_size;
93
+ self->cost_dist_ = BROTLI_ALLOC(m, float, dist->alphabet_size_limit);
94
+ self->distance_histogram_size = dist->alphabet_size_limit;
97
95
  if (BROTLI_IS_OOM(m)) return;
98
96
  }
99
97
 
@@ -408,9 +406,12 @@ static size_t UpdateNodes(
408
406
  const int* starting_dist_cache, const size_t num_matches,
409
407
  const BackwardMatch* matches, const ZopfliCostModel* model,
410
408
  StartPosQueue* queue, ZopfliNode* nodes) {
409
+ const size_t stream_offset = params->stream_offset;
411
410
  const size_t cur_ix = block_start + pos;
412
411
  const size_t cur_ix_masked = cur_ix & ringbuffer_mask;
413
412
  const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit);
413
+ const size_t dictionary_start = BROTLI_MIN(size_t,
414
+ cur_ix + stream_offset, max_backward_limit);
414
415
  const size_t max_len = num_bytes - pos;
415
416
  const size_t max_zopfli_len = MaxZopfliLen(params);
416
417
  const size_t max_iters = MaxZopfliCandidates(params);
@@ -419,8 +420,8 @@ static size_t UpdateNodes(
419
420
  size_t k;
420
421
  size_t gap = 0;
421
422
 
422
- EvaluateNode(block_start, pos, max_backward_limit, gap, starting_dist_cache,
423
- model, queue, nodes);
423
+ EvaluateNode(block_start + stream_offset, pos, max_backward_limit, gap,
424
+ starting_dist_cache, model, queue, nodes);
424
425
 
425
426
  {
426
427
  const PosData* posdata = StartPosQueueAt(queue, 0);
@@ -453,7 +454,7 @@ static size_t UpdateNodes(
453
454
  if (cur_ix_masked + best_len > ringbuffer_mask) {
454
455
  break;
455
456
  }
456
- if (BROTLI_PREDICT_FALSE(backward > max_distance + gap)) {
457
+ if (BROTLI_PREDICT_FALSE(backward > dictionary_start + gap)) {
457
458
  /* Word dictionary -> ignore. */
458
459
  continue;
459
460
  }
@@ -472,6 +473,8 @@ static size_t UpdateNodes(
472
473
  &ringbuffer[cur_ix_masked],
473
474
  max_len);
474
475
  } else {
476
+ /* "Gray" area. It is addressable by decoder, but this encoder
477
+ instance does not have that data -> should not touch it. */
475
478
  continue;
476
479
  }
477
480
  {
@@ -506,7 +509,7 @@ static size_t UpdateNodes(
506
509
  BackwardMatch match = matches[j];
507
510
  size_t dist = match.distance;
508
511
  BROTLI_BOOL is_dictionary_match =
509
- TO_BROTLI_BOOL(dist > max_distance + gap);
512
+ TO_BROTLI_BOOL(dist > dictionary_start + gap);
510
513
  /* We already tried all possible last distance matches, so we can use
511
514
  normal distance code here. */
512
515
  size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;
@@ -569,6 +572,7 @@ void BrotliZopfliCreateCommands(const size_t num_bytes,
569
572
  const size_t block_start, const ZopfliNode* nodes, int* dist_cache,
570
573
  size_t* last_insert_len, const BrotliEncoderParams* params,
571
574
  Command* commands, size_t* num_literals) {
575
+ const size_t stream_offset = params->stream_offset;
572
576
  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
573
577
  size_t pos = 0;
574
578
  uint32_t offset = nodes[0].u.next;
@@ -587,9 +591,10 @@ void BrotliZopfliCreateCommands(const size_t num_bytes,
587
591
  {
588
592
  size_t distance = ZopfliNodeCopyDistance(next);
589
593
  size_t len_code = ZopfliNodeLengthCode(next);
590
- size_t max_distance =
591
- BROTLI_MIN(size_t, block_start + pos, max_backward_limit);
592
- BROTLI_BOOL is_dictionary = TO_BROTLI_BOOL(distance > max_distance + gap);
594
+ size_t dictionary_start = BROTLI_MIN(size_t,
595
+ block_start + pos + stream_offset, max_backward_limit);
596
+ BROTLI_BOOL is_dictionary =
597
+ TO_BROTLI_BOOL(distance > dictionary_start + gap);
593
598
  size_t dist_code = ZopfliNodeDistanceCode(next);
594
599
  InitCommand(&commands[i], &params->dist, insert_length,
595
600
  copy_length, (int)len_code - (int)copy_length, dist_code);
@@ -613,6 +618,7 @@ static size_t ZopfliIterate(size_t num_bytes, size_t position,
613
618
  const BrotliEncoderParams* params, const size_t gap, const int* dist_cache,
614
619
  const ZopfliCostModel* model, const uint32_t* num_matches,
615
620
  const BackwardMatch* matches, ZopfliNode* nodes) {
621
+ const size_t stream_offset = params->stream_offset;
616
622
  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
617
623
  const size_t max_zopfli_len = MaxZopfliLen(params);
618
624
  StartPosQueue queue;
@@ -637,7 +643,7 @@ static size_t ZopfliIterate(size_t num_bytes, size_t position,
637
643
  while (skip) {
638
644
  i++;
639
645
  if (i + 3 >= num_bytes) break;
640
- EvaluateNode(position, i, max_backward_limit, gap,
646
+ EvaluateNode(position + stream_offset, i, max_backward_limit, gap,
641
647
  dist_cache, model, &queue, nodes);
642
648
  cur_match_pos += num_matches[i];
643
649
  skip--;
@@ -650,8 +656,9 @@ static size_t ZopfliIterate(size_t num_bytes, size_t position,
650
656
  /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */
651
657
  size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,
652
658
  size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
653
- const BrotliEncoderParams* params,
654
- const int* dist_cache, HasherHandle hasher, ZopfliNode* nodes) {
659
+ ContextLut literal_context_lut, const BrotliEncoderParams* params,
660
+ const int* dist_cache, Hasher* hasher, ZopfliNode* nodes) {
661
+ const size_t stream_offset = params->stream_offset;
655
662
  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
656
663
  const size_t max_zopfli_len = MaxZopfliLen(params);
657
664
  ZopfliCostModel model;
@@ -662,6 +669,7 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,
662
669
  size_t i;
663
670
  size_t gap = 0;
664
671
  size_t lz_matches_offset = 0;
672
+ BROTLI_UNUSED(literal_context_lut);
665
673
  nodes[0].length = 0;
666
674
  nodes[0].u.cost = 0;
667
675
  InitZopfliCostModel(m, &model, &params->dist, num_bytes);
@@ -672,12 +680,14 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,
672
680
  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) {
673
681
  const size_t pos = position + i;
674
682
  const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
683
+ const size_t dictionary_start = BROTLI_MIN(size_t,
684
+ pos + stream_offset, max_backward_limit);
675
685
  size_t skip;
676
686
  size_t num_matches;
677
- num_matches = FindAllMatchesH10(hasher,
687
+ num_matches = FindAllMatchesH10(&hasher->privat._H10,
678
688
  &params->dictionary,
679
689
  ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance,
680
- gap, params, &matches[lz_matches_offset]);
690
+ dictionary_start + gap, params, &matches[lz_matches_offset]);
681
691
  if (num_matches > 0 &&
682
692
  BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) {
683
693
  matches[0] = matches[num_matches - 1];
@@ -692,13 +702,14 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,
692
702
  }
693
703
  if (skip > 1) {
694
704
  /* Add the tail of the copy to the hasher. */
695
- StoreRangeH10(hasher, ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(
705
+ StoreRangeH10(&hasher->privat._H10,
706
+ ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(
696
707
  size_t, pos + skip, store_end));
697
708
  skip--;
698
709
  while (skip) {
699
710
  i++;
700
711
  if (i + HashTypeLengthH10() - 1 >= num_bytes) break;
701
- EvaluateNode(position, i, max_backward_limit, gap,
712
+ EvaluateNode(position + stream_offset, i, max_backward_limit, gap,
702
713
  dist_cache, &model, &queue, nodes);
703
714
  skip--;
704
715
  }
@@ -710,15 +721,14 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,
710
721
 
711
722
  void BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
712
723
  size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
713
- const BrotliEncoderParams* params,
714
- HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
724
+ ContextLut literal_context_lut, const BrotliEncoderParams* params,
725
+ Hasher* hasher, int* dist_cache, size_t* last_insert_len,
715
726
  Command* commands, size_t* num_commands, size_t* num_literals) {
716
- ZopfliNode* nodes;
717
- nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
718
- if (BROTLI_IS_OOM(m)) return;
727
+ ZopfliNode* nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
728
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return;
719
729
  BrotliInitZopfliNodes(nodes, num_bytes + 1);
720
730
  *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes,
721
- position, ringbuffer, ringbuffer_mask, params,
731
+ position, ringbuffer, ringbuffer_mask, literal_context_lut, params,
722
732
  dist_cache, hasher, nodes);
723
733
  if (BROTLI_IS_OOM(m)) return;
724
734
  BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,
@@ -728,9 +738,10 @@ void BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
728
738
 
729
739
  void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
730
740
  size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,
731
- const BrotliEncoderParams* params,
732
- HasherHandle hasher, int* dist_cache, size_t* last_insert_len,
741
+ ContextLut literal_context_lut, const BrotliEncoderParams* params,
742
+ Hasher* hasher, int* dist_cache, size_t* last_insert_len,
733
743
  Command* commands, size_t* num_commands, size_t* num_literals) {
744
+ const size_t stream_offset = params->stream_offset;
734
745
  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);
735
746
  uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes);
736
747
  size_t matches_size = 4 * num_bytes;
@@ -747,10 +758,16 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
747
758
  BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size);
748
759
  size_t gap = 0;
749
760
  size_t shadow_matches = 0;
750
- if (BROTLI_IS_OOM(m)) return;
761
+ BROTLI_UNUSED(literal_context_lut);
762
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(num_matches) ||
763
+ BROTLI_IS_NULL(matches)) {
764
+ return;
765
+ }
751
766
  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) {
752
767
  const size_t pos = position + i;
753
768
  size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);
769
+ size_t dictionary_start = BROTLI_MIN(size_t,
770
+ pos + stream_offset, max_backward_limit);
754
771
  size_t max_length = num_bytes - i;
755
772
  size_t num_found_matches;
756
773
  size_t cur_match_end;
@@ -759,10 +776,10 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
759
776
  BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size,
760
777
  cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches);
761
778
  if (BROTLI_IS_OOM(m)) return;
762
- num_found_matches = FindAllMatchesH10(hasher,
779
+ num_found_matches = FindAllMatchesH10(&hasher->privat._H10,
763
780
  &params->dictionary,
764
781
  ringbuffer, ringbuffer_mask, pos, max_length,
765
- max_distance, gap, params,
782
+ max_distance, dictionary_start + gap, params,
766
783
  &matches[cur_match_pos + shadow_matches]);
767
784
  cur_match_end = cur_match_pos + num_found_matches;
768
785
  for (j = cur_match_pos; j + 1 < cur_match_end; ++j) {
@@ -777,7 +794,8 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
777
794
  matches[cur_match_pos++] = matches[cur_match_end - 1];
778
795
  num_matches[i] = 1;
779
796
  /* Add the tail of the copy to the hasher. */
780
- StoreRangeH10(hasher, ringbuffer, ringbuffer_mask, pos + 1,
797
+ StoreRangeH10(&hasher->privat._H10,
798
+ ringbuffer, ringbuffer_mask, pos + 1,
781
799
  BROTLI_MIN(size_t, pos + match_len, store_end));
782
800
  memset(&num_matches[i + 1], 0, skip * sizeof(num_matches[0]));
783
801
  i += skip;
@@ -791,7 +809,7 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,
791
809
  memcpy(orig_dist_cache, dist_cache, 4 * sizeof(dist_cache[0]));
792
810
  orig_num_commands = *num_commands;
793
811
  nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);
794
- if (BROTLI_IS_OOM(m)) return;
812
+ if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return;
795
813
  InitZopfliCostModel(m, &model, &params->dist, num_bytes);
796
814
  if (BROTLI_IS_OOM(m)) return;
797
815
  for (i = 0; i < 2; i++) {