296 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Go
		
	
	
	
package brotli
 | 
						|
 | 
						|
import "io"
 | 
						|
 | 
						|
/* Copyright 2015 Google Inc. All Rights Reserved.
 | 
						|
 | 
						|
   Distributed under MIT license.
 | 
						|
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
 | 
						|
*/
 | 
						|
 | 
						|
/* Brotli state for partial streaming decoding. */
 | 
						|
const (
 | 
						|
	stateUninited = iota
 | 
						|
	stateLargeWindowBits
 | 
						|
	stateInitialize
 | 
						|
	stateMetablockBegin
 | 
						|
	stateMetablockHeader
 | 
						|
	stateMetablockHeader2
 | 
						|
	stateContextModes
 | 
						|
	stateCommandBegin
 | 
						|
	stateCommandInner
 | 
						|
	stateCommandPostDecodeLiterals
 | 
						|
	stateCommandPostWrapCopy
 | 
						|
	stateUncompressed
 | 
						|
	stateMetadata
 | 
						|
	stateCommandInnerWrite
 | 
						|
	stateMetablockDone
 | 
						|
	stateCommandPostWrite1
 | 
						|
	stateCommandPostWrite2
 | 
						|
	stateHuffmanCode0
 | 
						|
	stateHuffmanCode1
 | 
						|
	stateHuffmanCode2
 | 
						|
	stateHuffmanCode3
 | 
						|
	stateContextMap1
 | 
						|
	stateContextMap2
 | 
						|
	stateTreeGroup
 | 
						|
	stateDone
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateMetablockHeaderNone = iota
 | 
						|
	stateMetablockHeaderEmpty
 | 
						|
	stateMetablockHeaderNibbles
 | 
						|
	stateMetablockHeaderSize
 | 
						|
	stateMetablockHeaderUncompressed
 | 
						|
	stateMetablockHeaderReserved
 | 
						|
	stateMetablockHeaderBytes
 | 
						|
	stateMetablockHeaderMetadata
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateUncompressedNone = iota
 | 
						|
	stateUncompressedWrite
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateTreeGroupNone = iota
 | 
						|
	stateTreeGroupLoop
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateContextMapNone = iota
 | 
						|
	stateContextMapReadPrefix
 | 
						|
	stateContextMapHuffman
 | 
						|
	stateContextMapDecode
 | 
						|
	stateContextMapTransform
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateHuffmanNone = iota
 | 
						|
	stateHuffmanSimpleSize
 | 
						|
	stateHuffmanSimpleRead
 | 
						|
	stateHuffmanSimpleBuild
 | 
						|
	stateHuffmanComplex
 | 
						|
	stateHuffmanLengthSymbols
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateDecodeUint8None = iota
 | 
						|
	stateDecodeUint8Short
 | 
						|
	stateDecodeUint8Long
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	stateReadBlockLengthNone = iota
 | 
						|
	stateReadBlockLengthSuffix
 | 
						|
)
 | 
						|
 | 
						|
type Reader struct {
 | 
						|
	src io.Reader
 | 
						|
	buf []byte // scratch space for reading from src
 | 
						|
	in  []byte // current chunk to decode; usually aliases buf
 | 
						|
 | 
						|
	state        int
 | 
						|
	loop_counter int
 | 
						|
	br           bitReader
 | 
						|
	buffer       struct {
 | 
						|
		u64 uint64
 | 
						|
		u8  [8]byte
 | 
						|
	}
 | 
						|
	buffer_length               uint32
 | 
						|
	pos                         int
 | 
						|
	max_backward_distance       int
 | 
						|
	max_distance                int
 | 
						|
	ringbuffer_size             int
 | 
						|
	ringbuffer_mask             int
 | 
						|
	dist_rb_idx                 int
 | 
						|
	dist_rb                     [4]int
 | 
						|
	error_code                  int
 | 
						|
	sub_loop_counter            uint32
 | 
						|
	ringbuffer                  []byte
 | 
						|
	ringbuffer_end              []byte
 | 
						|
	htree_command               []huffmanCode
 | 
						|
	context_lookup              []byte
 | 
						|
	context_map_slice           []byte
 | 
						|
	dist_context_map_slice      []byte
 | 
						|
	literal_hgroup              huffmanTreeGroup
 | 
						|
	insert_copy_hgroup          huffmanTreeGroup
 | 
						|
	distance_hgroup             huffmanTreeGroup
 | 
						|
	block_type_trees            []huffmanCode
 | 
						|
	block_len_trees             []huffmanCode
 | 
						|
	trivial_literal_context     int
 | 
						|
	distance_context            int
 | 
						|
	meta_block_remaining_len    int
 | 
						|
	block_length_index          uint32
 | 
						|
	block_length                [3]uint32
 | 
						|
	num_block_types             [3]uint32
 | 
						|
	block_type_rb               [6]uint32
 | 
						|
	distance_postfix_bits       uint32
 | 
						|
	num_direct_distance_codes   uint32
 | 
						|
	distance_postfix_mask       int
 | 
						|
	num_dist_htrees             uint32
 | 
						|
	dist_context_map            []byte
 | 
						|
	literal_htree               []huffmanCode
 | 
						|
	dist_htree_index            byte
 | 
						|
	repeat_code_len             uint32
 | 
						|
	prev_code_len               uint32
 | 
						|
	copy_length                 int
 | 
						|
	distance_code               int
 | 
						|
	rb_roundtrips               uint
 | 
						|
	partial_pos_out             uint
 | 
						|
	symbol                      uint32
 | 
						|
	repeat                      uint32
 | 
						|
	space                       uint32
 | 
						|
	table                       [32]huffmanCode
 | 
						|
	symbol_lists                symbolList
 | 
						|
	symbols_lists_array         [huffmanMaxCodeLength + 1 + numCommandSymbols]uint16
 | 
						|
	next_symbol                 [32]int
 | 
						|
	code_length_code_lengths    [codeLengthCodes]byte
 | 
						|
	code_length_histo           [16]uint16
 | 
						|
	htree_index                 int
 | 
						|
	next                        []huffmanCode
 | 
						|
	context_index               uint32
 | 
						|
	max_run_length_prefix       uint32
 | 
						|
	code                        uint32
 | 
						|
	context_map_table           [huffmanMaxSize272]huffmanCode
 | 
						|
	substate_metablock_header   int
 | 
						|
	substate_tree_group         int
 | 
						|
	substate_context_map        int
 | 
						|
	substate_uncompressed       int
 | 
						|
	substate_huffman            int
 | 
						|
	substate_decode_uint8       int
 | 
						|
	substate_read_block_length  int
 | 
						|
	is_last_metablock           uint
 | 
						|
	is_uncompressed             uint
 | 
						|
	is_metadata                 uint
 | 
						|
	should_wrap_ringbuffer      uint
 | 
						|
	canny_ringbuffer_allocation uint
 | 
						|
	large_window                bool
 | 
						|
	size_nibbles                uint
 | 
						|
	window_bits                 uint32
 | 
						|
	new_ringbuffer_size         int
 | 
						|
	num_literal_htrees          uint32
 | 
						|
	context_map                 []byte
 | 
						|
	context_modes               []byte
 | 
						|
	dictionary                  *dictionary
 | 
						|
	transforms                  *transforms
 | 
						|
	trivial_literal_contexts    [8]uint32
 | 
						|
}
 | 
						|
 | 
						|
func decoderStateInit(s *Reader) bool {
 | 
						|
	s.error_code = 0 /* BROTLI_DECODER_NO_ERROR */
 | 
						|
 | 
						|
	initBitReader(&s.br)
 | 
						|
	s.state = stateUninited
 | 
						|
	s.large_window = false
 | 
						|
	s.substate_metablock_header = stateMetablockHeaderNone
 | 
						|
	s.substate_tree_group = stateTreeGroupNone
 | 
						|
	s.substate_context_map = stateContextMapNone
 | 
						|
	s.substate_uncompressed = stateUncompressedNone
 | 
						|
	s.substate_huffman = stateHuffmanNone
 | 
						|
	s.substate_decode_uint8 = stateDecodeUint8None
 | 
						|
	s.substate_read_block_length = stateReadBlockLengthNone
 | 
						|
 | 
						|
	s.buffer_length = 0
 | 
						|
	s.loop_counter = 0
 | 
						|
	s.pos = 0
 | 
						|
	s.rb_roundtrips = 0
 | 
						|
	s.partial_pos_out = 0
 | 
						|
 | 
						|
	s.block_type_trees = nil
 | 
						|
	s.block_len_trees = nil
 | 
						|
	s.ringbuffer = nil
 | 
						|
	s.ringbuffer_size = 0
 | 
						|
	s.new_ringbuffer_size = 0
 | 
						|
	s.ringbuffer_mask = 0
 | 
						|
 | 
						|
	s.context_map = nil
 | 
						|
	s.context_modes = nil
 | 
						|
	s.dist_context_map = nil
 | 
						|
	s.context_map_slice = nil
 | 
						|
	s.dist_context_map_slice = nil
 | 
						|
 | 
						|
	s.sub_loop_counter = 0
 | 
						|
 | 
						|
	s.literal_hgroup.codes = nil
 | 
						|
	s.literal_hgroup.htrees = nil
 | 
						|
	s.insert_copy_hgroup.codes = nil
 | 
						|
	s.insert_copy_hgroup.htrees = nil
 | 
						|
	s.distance_hgroup.codes = nil
 | 
						|
	s.distance_hgroup.htrees = nil
 | 
						|
 | 
						|
	s.is_last_metablock = 0
 | 
						|
	s.is_uncompressed = 0
 | 
						|
	s.is_metadata = 0
 | 
						|
	s.should_wrap_ringbuffer = 0
 | 
						|
	s.canny_ringbuffer_allocation = 1
 | 
						|
 | 
						|
	s.window_bits = 0
 | 
						|
	s.max_distance = 0
 | 
						|
	s.dist_rb[0] = 16
 | 
						|
	s.dist_rb[1] = 15
 | 
						|
	s.dist_rb[2] = 11
 | 
						|
	s.dist_rb[3] = 4
 | 
						|
	s.dist_rb_idx = 0
 | 
						|
	s.block_type_trees = nil
 | 
						|
	s.block_len_trees = nil
 | 
						|
 | 
						|
	s.symbol_lists.storage = s.symbols_lists_array[:]
 | 
						|
	s.symbol_lists.offset = huffmanMaxCodeLength + 1
 | 
						|
 | 
						|
	s.dictionary = getDictionary()
 | 
						|
	s.transforms = getTransforms()
 | 
						|
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func decoderStateMetablockBegin(s *Reader) {
 | 
						|
	s.meta_block_remaining_len = 0
 | 
						|
	s.block_length[0] = 1 << 24
 | 
						|
	s.block_length[1] = 1 << 24
 | 
						|
	s.block_length[2] = 1 << 24
 | 
						|
	s.num_block_types[0] = 1
 | 
						|
	s.num_block_types[1] = 1
 | 
						|
	s.num_block_types[2] = 1
 | 
						|
	s.block_type_rb[0] = 1
 | 
						|
	s.block_type_rb[1] = 0
 | 
						|
	s.block_type_rb[2] = 1
 | 
						|
	s.block_type_rb[3] = 0
 | 
						|
	s.block_type_rb[4] = 1
 | 
						|
	s.block_type_rb[5] = 0
 | 
						|
	s.context_map = nil
 | 
						|
	s.context_modes = nil
 | 
						|
	s.dist_context_map = nil
 | 
						|
	s.context_map_slice = nil
 | 
						|
	s.literal_htree = nil
 | 
						|
	s.dist_context_map_slice = nil
 | 
						|
	s.dist_htree_index = 0
 | 
						|
	s.context_lookup = nil
 | 
						|
	s.literal_hgroup.codes = nil
 | 
						|
	s.literal_hgroup.htrees = nil
 | 
						|
	s.insert_copy_hgroup.codes = nil
 | 
						|
	s.insert_copy_hgroup.htrees = nil
 | 
						|
	s.distance_hgroup.codes = nil
 | 
						|
	s.distance_hgroup.htrees = nil
 | 
						|
}
 | 
						|
 | 
						|
func decoderStateCleanupAfterMetablock(s *Reader) {
 | 
						|
	s.context_modes = nil
 | 
						|
	s.context_map = nil
 | 
						|
	s.dist_context_map = nil
 | 
						|
	s.literal_hgroup.htrees = nil
 | 
						|
	s.insert_copy_hgroup.htrees = nil
 | 
						|
	s.distance_hgroup.htrees = nil
 | 
						|
}
 | 
						|
 | 
						|
func decoderHuffmanTreeGroupInit(s *Reader, group *huffmanTreeGroup, alphabet_size uint32, max_symbol uint32, ntrees uint32) bool {
 | 
						|
	var max_table_size uint = uint(kMaxHuffmanTableSize[(alphabet_size+31)>>5])
 | 
						|
	group.alphabet_size = uint16(alphabet_size)
 | 
						|
	group.max_symbol = uint16(max_symbol)
 | 
						|
	group.num_htrees = uint16(ntrees)
 | 
						|
	group.htrees = make([][]huffmanCode, ntrees)
 | 
						|
	group.codes = make([]huffmanCode, (uint(ntrees) * max_table_size))
 | 
						|
	return !(group.codes == nil)
 | 
						|
}
 |