1 | package brotli
|
---|
2 |
|
---|
3 | import "io"
|
---|
4 |
|
---|
5 | /* Copyright 2015 Google Inc. All Rights Reserved.
|
---|
6 |
|
---|
7 | Distributed under MIT license.
|
---|
8 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
---|
9 | */
|
---|
10 |
|
---|
11 | /* Brotli state for partial streaming decoding. */
|
---|
12 | const (
|
---|
13 | stateUninited = iota
|
---|
14 | stateLargeWindowBits
|
---|
15 | stateInitialize
|
---|
16 | stateMetablockBegin
|
---|
17 | stateMetablockHeader
|
---|
18 | stateMetablockHeader2
|
---|
19 | stateContextModes
|
---|
20 | stateCommandBegin
|
---|
21 | stateCommandInner
|
---|
22 | stateCommandPostDecodeLiterals
|
---|
23 | stateCommandPostWrapCopy
|
---|
24 | stateUncompressed
|
---|
25 | stateMetadata
|
---|
26 | stateCommandInnerWrite
|
---|
27 | stateMetablockDone
|
---|
28 | stateCommandPostWrite1
|
---|
29 | stateCommandPostWrite2
|
---|
30 | stateHuffmanCode0
|
---|
31 | stateHuffmanCode1
|
---|
32 | stateHuffmanCode2
|
---|
33 | stateHuffmanCode3
|
---|
34 | stateContextMap1
|
---|
35 | stateContextMap2
|
---|
36 | stateTreeGroup
|
---|
37 | stateDone
|
---|
38 | )
|
---|
39 |
|
---|
40 | const (
|
---|
41 | stateMetablockHeaderNone = iota
|
---|
42 | stateMetablockHeaderEmpty
|
---|
43 | stateMetablockHeaderNibbles
|
---|
44 | stateMetablockHeaderSize
|
---|
45 | stateMetablockHeaderUncompressed
|
---|
46 | stateMetablockHeaderReserved
|
---|
47 | stateMetablockHeaderBytes
|
---|
48 | stateMetablockHeaderMetadata
|
---|
49 | )
|
---|
50 |
|
---|
51 | const (
|
---|
52 | stateUncompressedNone = iota
|
---|
53 | stateUncompressedWrite
|
---|
54 | )
|
---|
55 |
|
---|
56 | const (
|
---|
57 | stateTreeGroupNone = iota
|
---|
58 | stateTreeGroupLoop
|
---|
59 | )
|
---|
60 |
|
---|
61 | const (
|
---|
62 | stateContextMapNone = iota
|
---|
63 | stateContextMapReadPrefix
|
---|
64 | stateContextMapHuffman
|
---|
65 | stateContextMapDecode
|
---|
66 | stateContextMapTransform
|
---|
67 | )
|
---|
68 |
|
---|
69 | const (
|
---|
70 | stateHuffmanNone = iota
|
---|
71 | stateHuffmanSimpleSize
|
---|
72 | stateHuffmanSimpleRead
|
---|
73 | stateHuffmanSimpleBuild
|
---|
74 | stateHuffmanComplex
|
---|
75 | stateHuffmanLengthSymbols
|
---|
76 | )
|
---|
77 |
|
---|
78 | const (
|
---|
79 | stateDecodeUint8None = iota
|
---|
80 | stateDecodeUint8Short
|
---|
81 | stateDecodeUint8Long
|
---|
82 | )
|
---|
83 |
|
---|
84 | const (
|
---|
85 | stateReadBlockLengthNone = iota
|
---|
86 | stateReadBlockLengthSuffix
|
---|
87 | )
|
---|
88 |
|
---|
89 | type Reader struct {
|
---|
90 | src io.Reader
|
---|
91 | buf []byte // scratch space for reading from src
|
---|
92 | in []byte // current chunk to decode; usually aliases buf
|
---|
93 |
|
---|
94 | state int
|
---|
95 | loop_counter int
|
---|
96 | br bitReader
|
---|
97 | buffer struct {
|
---|
98 | u64 uint64
|
---|
99 | u8 [8]byte
|
---|
100 | }
|
---|
101 | buffer_length uint32
|
---|
102 | pos int
|
---|
103 | max_backward_distance int
|
---|
104 | max_distance int
|
---|
105 | ringbuffer_size int
|
---|
106 | ringbuffer_mask int
|
---|
107 | dist_rb_idx int
|
---|
108 | dist_rb [4]int
|
---|
109 | error_code int
|
---|
110 | sub_loop_counter uint32
|
---|
111 | ringbuffer []byte
|
---|
112 | ringbuffer_end []byte
|
---|
113 | htree_command []huffmanCode
|
---|
114 | context_lookup []byte
|
---|
115 | context_map_slice []byte
|
---|
116 | dist_context_map_slice []byte
|
---|
117 | literal_hgroup huffmanTreeGroup
|
---|
118 | insert_copy_hgroup huffmanTreeGroup
|
---|
119 | distance_hgroup huffmanTreeGroup
|
---|
120 | block_type_trees []huffmanCode
|
---|
121 | block_len_trees []huffmanCode
|
---|
122 | trivial_literal_context int
|
---|
123 | distance_context int
|
---|
124 | meta_block_remaining_len int
|
---|
125 | block_length_index uint32
|
---|
126 | block_length [3]uint32
|
---|
127 | num_block_types [3]uint32
|
---|
128 | block_type_rb [6]uint32
|
---|
129 | distance_postfix_bits uint32
|
---|
130 | num_direct_distance_codes uint32
|
---|
131 | distance_postfix_mask int
|
---|
132 | num_dist_htrees uint32
|
---|
133 | dist_context_map []byte
|
---|
134 | literal_htree []huffmanCode
|
---|
135 | dist_htree_index byte
|
---|
136 | repeat_code_len uint32
|
---|
137 | prev_code_len uint32
|
---|
138 | copy_length int
|
---|
139 | distance_code int
|
---|
140 | rb_roundtrips uint
|
---|
141 | partial_pos_out uint
|
---|
142 | symbol uint32
|
---|
143 | repeat uint32
|
---|
144 | space uint32
|
---|
145 | table [32]huffmanCode
|
---|
146 | symbol_lists symbolList
|
---|
147 | symbols_lists_array [huffmanMaxCodeLength + 1 + numCommandSymbols]uint16
|
---|
148 | next_symbol [32]int
|
---|
149 | code_length_code_lengths [codeLengthCodes]byte
|
---|
150 | code_length_histo [16]uint16
|
---|
151 | htree_index int
|
---|
152 | next []huffmanCode
|
---|
153 | context_index uint32
|
---|
154 | max_run_length_prefix uint32
|
---|
155 | code uint32
|
---|
156 | context_map_table [huffmanMaxSize272]huffmanCode
|
---|
157 | substate_metablock_header int
|
---|
158 | substate_tree_group int
|
---|
159 | substate_context_map int
|
---|
160 | substate_uncompressed int
|
---|
161 | substate_huffman int
|
---|
162 | substate_decode_uint8 int
|
---|
163 | substate_read_block_length int
|
---|
164 | is_last_metablock uint
|
---|
165 | is_uncompressed uint
|
---|
166 | is_metadata uint
|
---|
167 | should_wrap_ringbuffer uint
|
---|
168 | canny_ringbuffer_allocation uint
|
---|
169 | large_window bool
|
---|
170 | size_nibbles uint
|
---|
171 | window_bits uint32
|
---|
172 | new_ringbuffer_size int
|
---|
173 | num_literal_htrees uint32
|
---|
174 | context_map []byte
|
---|
175 | context_modes []byte
|
---|
176 | dictionary *dictionary
|
---|
177 | transforms *transforms
|
---|
178 | trivial_literal_contexts [8]uint32
|
---|
179 | }
|
---|
180 |
|
---|
181 | func decoderStateInit(s *Reader) bool {
|
---|
182 | s.error_code = 0 /* BROTLI_DECODER_NO_ERROR */
|
---|
183 |
|
---|
184 | initBitReader(&s.br)
|
---|
185 | s.state = stateUninited
|
---|
186 | s.large_window = false
|
---|
187 | s.substate_metablock_header = stateMetablockHeaderNone
|
---|
188 | s.substate_tree_group = stateTreeGroupNone
|
---|
189 | s.substate_context_map = stateContextMapNone
|
---|
190 | s.substate_uncompressed = stateUncompressedNone
|
---|
191 | s.substate_huffman = stateHuffmanNone
|
---|
192 | s.substate_decode_uint8 = stateDecodeUint8None
|
---|
193 | s.substate_read_block_length = stateReadBlockLengthNone
|
---|
194 |
|
---|
195 | s.buffer_length = 0
|
---|
196 | s.loop_counter = 0
|
---|
197 | s.pos = 0
|
---|
198 | s.rb_roundtrips = 0
|
---|
199 | s.partial_pos_out = 0
|
---|
200 |
|
---|
201 | s.block_type_trees = nil
|
---|
202 | s.block_len_trees = nil
|
---|
203 | s.ringbuffer = nil
|
---|
204 | s.ringbuffer_size = 0
|
---|
205 | s.new_ringbuffer_size = 0
|
---|
206 | s.ringbuffer_mask = 0
|
---|
207 |
|
---|
208 | s.context_map = nil
|
---|
209 | s.context_modes = nil
|
---|
210 | s.dist_context_map = nil
|
---|
211 | s.context_map_slice = nil
|
---|
212 | s.dist_context_map_slice = nil
|
---|
213 |
|
---|
214 | s.sub_loop_counter = 0
|
---|
215 |
|
---|
216 | s.literal_hgroup.codes = nil
|
---|
217 | s.literal_hgroup.htrees = nil
|
---|
218 | s.insert_copy_hgroup.codes = nil
|
---|
219 | s.insert_copy_hgroup.htrees = nil
|
---|
220 | s.distance_hgroup.codes = nil
|
---|
221 | s.distance_hgroup.htrees = nil
|
---|
222 |
|
---|
223 | s.is_last_metablock = 0
|
---|
224 | s.is_uncompressed = 0
|
---|
225 | s.is_metadata = 0
|
---|
226 | s.should_wrap_ringbuffer = 0
|
---|
227 | s.canny_ringbuffer_allocation = 1
|
---|
228 |
|
---|
229 | s.window_bits = 0
|
---|
230 | s.max_distance = 0
|
---|
231 | s.dist_rb[0] = 16
|
---|
232 | s.dist_rb[1] = 15
|
---|
233 | s.dist_rb[2] = 11
|
---|
234 | s.dist_rb[3] = 4
|
---|
235 | s.dist_rb_idx = 0
|
---|
236 | s.block_type_trees = nil
|
---|
237 | s.block_len_trees = nil
|
---|
238 |
|
---|
239 | s.symbol_lists.storage = s.symbols_lists_array[:]
|
---|
240 | s.symbol_lists.offset = huffmanMaxCodeLength + 1
|
---|
241 |
|
---|
242 | s.dictionary = getDictionary()
|
---|
243 | s.transforms = getTransforms()
|
---|
244 |
|
---|
245 | return true
|
---|
246 | }
|
---|
247 |
|
---|
248 | func decoderStateMetablockBegin(s *Reader) {
|
---|
249 | s.meta_block_remaining_len = 0
|
---|
250 | s.block_length[0] = 1 << 24
|
---|
251 | s.block_length[1] = 1 << 24
|
---|
252 | s.block_length[2] = 1 << 24
|
---|
253 | s.num_block_types[0] = 1
|
---|
254 | s.num_block_types[1] = 1
|
---|
255 | s.num_block_types[2] = 1
|
---|
256 | s.block_type_rb[0] = 1
|
---|
257 | s.block_type_rb[1] = 0
|
---|
258 | s.block_type_rb[2] = 1
|
---|
259 | s.block_type_rb[3] = 0
|
---|
260 | s.block_type_rb[4] = 1
|
---|
261 | s.block_type_rb[5] = 0
|
---|
262 | s.context_map = nil
|
---|
263 | s.context_modes = nil
|
---|
264 | s.dist_context_map = nil
|
---|
265 | s.context_map_slice = nil
|
---|
266 | s.literal_htree = nil
|
---|
267 | s.dist_context_map_slice = nil
|
---|
268 | s.dist_htree_index = 0
|
---|
269 | s.context_lookup = nil
|
---|
270 | s.literal_hgroup.codes = nil
|
---|
271 | s.literal_hgroup.htrees = nil
|
---|
272 | s.insert_copy_hgroup.codes = nil
|
---|
273 | s.insert_copy_hgroup.htrees = nil
|
---|
274 | s.distance_hgroup.codes = nil
|
---|
275 | s.distance_hgroup.htrees = nil
|
---|
276 | }
|
---|
277 |
|
---|
278 | func decoderStateCleanupAfterMetablock(s *Reader) {
|
---|
279 | s.context_modes = nil
|
---|
280 | s.context_map = nil
|
---|
281 | s.dist_context_map = nil
|
---|
282 | s.literal_hgroup.htrees = nil
|
---|
283 | s.insert_copy_hgroup.htrees = nil
|
---|
284 | s.distance_hgroup.htrees = nil
|
---|
285 | }
|
---|
286 |
|
---|
287 | func decoderHuffmanTreeGroupInit(s *Reader, group *huffmanTreeGroup, alphabet_size uint32, max_symbol uint32, ntrees uint32) bool {
|
---|
288 | var max_table_size uint = uint(kMaxHuffmanTableSize[(alphabet_size+31)>>5])
|
---|
289 | group.alphabet_size = uint16(alphabet_size)
|
---|
290 | group.max_symbol = uint16(max_symbol)
|
---|
291 | group.num_htrees = uint16(ntrees)
|
---|
292 | group.htrees = make([][]huffmanCode, ntrees)
|
---|
293 | group.codes = make([]huffmanCode, (uint(ntrees) * max_table_size))
|
---|
294 | return !(group.codes == nil)
|
---|
295 | }
|
---|