brotli 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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++) {