package brotli
const (
decoderResultError = 0
decoderResultSuccess = 1
decoderResultNeedsMoreInput = 2
decoderResultNeedsMoreOutput = 3
)
const (
decoderNoError = 0
decoderSuccess = 1
decoderNeedsMoreInput = 2
decoderNeedsMoreOutput = 3
decoderErrorFormatExuberantNibble = -1
decoderErrorFormatReserved = -2
decoderErrorFormatExuberantMetaNibble = -3
decoderErrorFormatSimpleHuffmanAlphabet = -4
decoderErrorFormatSimpleHuffmanSame = -5
decoderErrorFormatClSpace = -6
decoderErrorFormatHuffmanSpace = -7
decoderErrorFormatContextMapRepeat = -8
decoderErrorFormatBlockLength1 = -9
decoderErrorFormatBlockLength2 = -10
decoderErrorFormatTransform = -11
decoderErrorFormatDictionary = -12
decoderErrorFormatWindowBits = -13
decoderErrorFormatPadding1 = -14
decoderErrorFormatPadding2 = -15
decoderErrorFormatDistance = -16
decoderErrorDictionaryNotSet = -19
decoderErrorInvalidArguments = -20
decoderErrorAllocContextModes = -21
decoderErrorAllocTreeGroups = -22
decoderErrorAllocContextMap = -25
decoderErrorAllocRingBuffer1 = -26
decoderErrorAllocRingBuffer2 = -27
decoderErrorAllocBlockTypeTrees = -30
decoderErrorUnreachable = -31
)
const huffmanTableBits = 8
const huffmanTableMask = 0xFF
const kRingBufferWriteAheadSlack uint32 = 42
var kCodeLengthCodeOrder = [codeLengthCodes ]byte {1 , 2 , 3 , 4 , 0 , 5 , 17 , 6 , 16 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 }
var kCodeLengthPrefixLength = [16 ]byte {2 , 2 , 2 , 3 , 2 , 2 , 2 , 4 , 2 , 2 , 2 , 3 , 2 , 2 , 2 , 4 }
var kCodeLengthPrefixValue = [16 ]byte {0 , 4 , 3 , 2 , 0 , 4 , 3 , 1 , 0 , 4 , 3 , 2 , 0 , 4 , 3 , 5 }
func saveErrorCode(s *Reader , e int ) int {
s .error_code = int (e )
switch e {
case decoderSuccess :
return decoderResultSuccess
case decoderNeedsMoreInput :
return decoderResultNeedsMoreInput
case decoderNeedsMoreOutput :
return decoderResultNeedsMoreOutput
default :
return decoderResultError
}
}
func decodeWindowBits(s *Reader , br *bitReader ) int {
var n uint32
var large_window bool = s .large_window
s .large_window = false
takeBits (br , 1 , &n )
if n == 0 {
s .window_bits = 16
return decoderSuccess
}
takeBits (br , 3 , &n )
if n != 0 {
s .window_bits = 17 + n
return decoderSuccess
}
takeBits (br , 3 , &n )
if n == 1 {
if large_window {
takeBits (br , 1 , &n )
if n == 1 {
return decoderErrorFormatWindowBits
}
s .large_window = true
return decoderSuccess
} else {
return decoderErrorFormatWindowBits
}
}
if n != 0 {
s .window_bits = 8 + n
return decoderSuccess
}
s .window_bits = 17
return decoderSuccess
}
func decodeVarLenUint8(s *Reader , br *bitReader , value *uint32 ) int {
var bits uint32
switch s .substate_decode_uint8 {
case stateDecodeUint8None :
if !safeReadBits (br , 1 , &bits ) {
return decoderNeedsMoreInput
}
if bits == 0 {
*value = 0
return decoderSuccess
}
fallthrough
case stateDecodeUint8Short :
if !safeReadBits (br , 3 , &bits ) {
s .substate_decode_uint8 = stateDecodeUint8Short
return decoderNeedsMoreInput
}
if bits == 0 {
*value = 1
s .substate_decode_uint8 = stateDecodeUint8None
return decoderSuccess
}
*value = bits
fallthrough
case stateDecodeUint8Long :
if !safeReadBits (br , *value , &bits ) {
s .substate_decode_uint8 = stateDecodeUint8Long
return decoderNeedsMoreInput
}
*value = (1 << *value ) + bits
s .substate_decode_uint8 = stateDecodeUint8None
return decoderSuccess
default :
return decoderErrorUnreachable
}
}
func decodeMetaBlockLength(s *Reader , br *bitReader ) int {
var bits uint32
var i int
for {
switch s .substate_metablock_header {
case stateMetablockHeaderNone :
if !safeReadBits (br , 1 , &bits ) {
return decoderNeedsMoreInput
}
if bits != 0 {
s .is_last_metablock = 1
} else {
s .is_last_metablock = 0
}
s .meta_block_remaining_len = 0
s .is_uncompressed = 0
s .is_metadata = 0
if s .is_last_metablock == 0 {
s .substate_metablock_header = stateMetablockHeaderNibbles
break
}
s .substate_metablock_header = stateMetablockHeaderEmpty
fallthrough
case stateMetablockHeaderEmpty :
if !safeReadBits (br , 1 , &bits ) {
return decoderNeedsMoreInput
}
if bits != 0 {
s .substate_metablock_header = stateMetablockHeaderNone
return decoderSuccess
}
s .substate_metablock_header = stateMetablockHeaderNibbles
fallthrough
case stateMetablockHeaderNibbles :
if !safeReadBits (br , 2 , &bits ) {
return decoderNeedsMoreInput
}
s .size_nibbles = uint (byte (bits + 4 ))
s .loop_counter = 0
if bits == 3 {
s .is_metadata = 1
s .substate_metablock_header = stateMetablockHeaderReserved
break
}
s .substate_metablock_header = stateMetablockHeaderSize
fallthrough
case stateMetablockHeaderSize :
i = s .loop_counter
for ; i < int (s .size_nibbles ); i ++ {
if !safeReadBits (br , 4 , &bits ) {
s .loop_counter = i
return decoderNeedsMoreInput
}
if uint (i +1 ) == s .size_nibbles && s .size_nibbles > 4 && bits == 0 {
return decoderErrorFormatExuberantNibble
}
s .meta_block_remaining_len |= int (bits << uint (i *4 ))
}
s .substate_metablock_header = stateMetablockHeaderUncompressed
fallthrough
case stateMetablockHeaderUncompressed :
if s .is_last_metablock == 0 {
if !safeReadBits (br , 1 , &bits ) {
return decoderNeedsMoreInput
}
if bits != 0 {
s .is_uncompressed = 1
} else {
s .is_uncompressed = 0
}
}
s .meta_block_remaining_len ++
s .substate_metablock_header = stateMetablockHeaderNone
return decoderSuccess
case stateMetablockHeaderReserved :
if !safeReadBits (br , 1 , &bits ) {
return decoderNeedsMoreInput
}
if bits != 0 {
return decoderErrorFormatReserved
}
s .substate_metablock_header = stateMetablockHeaderBytes
fallthrough
case stateMetablockHeaderBytes :
if !safeReadBits (br , 2 , &bits ) {
return decoderNeedsMoreInput
}
if bits == 0 {
s .substate_metablock_header = stateMetablockHeaderNone
return decoderSuccess
}
s .size_nibbles = uint (byte (bits ))
s .substate_metablock_header = stateMetablockHeaderMetadata
fallthrough
case stateMetablockHeaderMetadata :
i = s .loop_counter
for ; i < int (s .size_nibbles ); i ++ {
if !safeReadBits (br , 8 , &bits ) {
s .loop_counter = i
return decoderNeedsMoreInput
}
if uint (i +1 ) == s .size_nibbles && s .size_nibbles > 1 && bits == 0 {
return decoderErrorFormatExuberantMetaNibble
}
s .meta_block_remaining_len |= int (bits << uint (i *8 ))
}
s .meta_block_remaining_len ++
s .substate_metablock_header = stateMetablockHeaderNone
return decoderSuccess
default :
return decoderErrorUnreachable
}
}
}
func decodeSymbol(bits uint32 , table []huffmanCode , br *bitReader ) uint32 {
table = table [bits &huffmanTableMask :]
if table [0 ].bits > huffmanTableBits {
var nbits uint32 = uint32 (table [0 ].bits ) - huffmanTableBits
dropBits (br , huffmanTableBits )
table = table [uint32 (table [0 ].value )+((bits >>huffmanTableBits )&bitMask (nbits )):]
}
dropBits (br , uint32 (table [0 ].bits ))
return uint32 (table [0 ].value )
}
func readSymbol(table []huffmanCode , br *bitReader ) uint32 {
return decodeSymbol (get16BitsUnmasked (br ), table , br )
}
func safeDecodeSymbol(table []huffmanCode , br *bitReader , result *uint32 ) bool {
var val uint32
var available_bits uint32 = getAvailableBits (br )
if available_bits == 0 {
if table [0 ].bits == 0 {
*result = uint32 (table [0 ].value )
return true
}
return false
}
val = uint32 (getBitsUnmasked (br ))
table = table [val &huffmanTableMask :]
if table [0 ].bits <= huffmanTableBits {
if uint32 (table [0 ].bits ) <= available_bits {
dropBits (br , uint32 (table [0 ].bits ))
*result = uint32 (table [0 ].value )
return true
} else {
return false
}
}
if available_bits <= huffmanTableBits {
return false
}
val = (val & bitMask (uint32 (table [0 ].bits ))) >> huffmanTableBits
available_bits -= huffmanTableBits
table = table [uint32 (table [0 ].value )+val :]
if available_bits < uint32 (table [0 ].bits ) {
return false
}
dropBits (br , huffmanTableBits +uint32 (table [0 ].bits ))
*result = uint32 (table [0 ].value )
return true
}
func safeReadSymbol(table []huffmanCode , br *bitReader , result *uint32 ) bool {
var val uint32
if safeGetBits (br , 15 , &val ) {
*result = decodeSymbol (val , table , br )
return true
}
return safeDecodeSymbol (table , br , result )
}
func preloadSymbol(safe int , table []huffmanCode , br *bitReader , bits *uint32 , value *uint32 ) {
if safe != 0 {
return
}
table = table [getBits (br , huffmanTableBits ):]
*bits = uint32 (table [0 ].bits )
*value = uint32 (table [0 ].value )
}
func readPreloadedSymbol(table []huffmanCode , br *bitReader , bits *uint32 , value *uint32 ) uint32 {
var result uint32 = *value
var ext []huffmanCode
if *bits > huffmanTableBits {
var val uint32 = get16BitsUnmasked (br )
ext = table [val &huffmanTableMask :][*value :]
var mask uint32 = bitMask ((*bits - huffmanTableBits ))
dropBits (br , huffmanTableBits )
ext = ext [(val >>huffmanTableBits )&mask :]
dropBits (br , uint32 (ext [0 ].bits ))
result = uint32 (ext [0 ].value )
} else {
dropBits (br , *bits )
}
preloadSymbol (0 , table , br , bits , value )
return result
}
func log2Floor(x uint32 ) uint32 {
var result uint32 = 0
for x != 0 {
x >>= 1
result ++
}
return result
}
func readSimpleHuffmanSymbols(alphabet_size uint32 , max_symbol uint32 , s *Reader ) int {
var br *bitReader = &s .br
var max_bits uint32 = log2Floor (alphabet_size - 1 )
var i uint32 = s .sub_loop_counter
var num_symbols uint32 = s .symbol
for i <= num_symbols {
var v uint32
if !safeReadBits (br , max_bits , &v ) {
s .sub_loop_counter = i
s .substate_huffman = stateHuffmanSimpleRead
return decoderNeedsMoreInput
}
if v >= max_symbol {
return decoderErrorFormatSimpleHuffmanAlphabet
}
s .symbols_lists_array [i ] = uint16 (v )
i ++
}
for i = 0 ; i < num_symbols ; i ++ {
var k uint32 = i + 1
for ; k <= num_symbols ; k ++ {
if s .symbols_lists_array [i ] == s .symbols_lists_array [k ] {
return decoderErrorFormatSimpleHuffmanSame
}
}
}
return decoderSuccess
}
func processSingleCodeLength(code_len uint32 , symbol *uint32 , repeat *uint32 , space *uint32 , prev_code_len *uint32 , symbol_lists symbolList , code_length_histo []uint16 , next_symbol []int ) {
*repeat = 0
if code_len != 0 {
symbolListPut (symbol_lists , next_symbol [code_len ], uint16 (*symbol ))
next_symbol [code_len ] = int (*symbol )
*prev_code_len = code_len
*space -= 32768 >> code_len
code_length_histo [code_len ]++
}
(*symbol )++
}
func processRepeatedCodeLength(code_len uint32 , repeat_delta uint32 , alphabet_size uint32 , symbol *uint32 , repeat *uint32 , space *uint32 , prev_code_len *uint32 , repeat_code_len *uint32 , symbol_lists symbolList , code_length_histo []uint16 , next_symbol []int ) {
var old_repeat uint32
var extra_bits uint32 = 3
var new_len uint32 = 0
if code_len == repeatPreviousCodeLength {
new_len = *prev_code_len
extra_bits = 2
}
if *repeat_code_len != new_len {
*repeat = 0
*repeat_code_len = new_len
}
old_repeat = *repeat
if *repeat > 0 {
*repeat -= 2
*repeat <<= extra_bits
}
*repeat += repeat_delta + 3
repeat_delta = *repeat - old_repeat
if *symbol +repeat_delta > alphabet_size {
*symbol = alphabet_size
*space = 0xFFFFF
return
}
if *repeat_code_len != 0 {
var last uint = uint (*symbol + repeat_delta )
var next int = next_symbol [*repeat_code_len ]
for {
symbolListPut (symbol_lists , next , uint16 (*symbol ))
next = int (*symbol )
(*symbol )++
if (*symbol ) == uint32 (last ) {
break
}
}
next_symbol [*repeat_code_len ] = next
*space -= repeat_delta << (15 - *repeat_code_len )
code_length_histo [*repeat_code_len ] = uint16 (uint32 (code_length_histo [*repeat_code_len ]) + repeat_delta )
} else {
*symbol += repeat_delta
}
}
func readSymbolCodeLengths(alphabet_size uint32 , s *Reader ) int {
var br *bitReader = &s .br
var symbol uint32 = s .symbol
var repeat uint32 = s .repeat
var space uint32 = s .space
var prev_code_len uint32 = s .prev_code_len
var repeat_code_len uint32 = s .repeat_code_len
var symbol_lists symbolList = s .symbol_lists
var code_length_histo []uint16 = s .code_length_histo [:]
var next_symbol []int = s .next_symbol [:]
if !warmupBitReader (br ) {
return decoderNeedsMoreInput
}
var p []huffmanCode
for symbol < alphabet_size && space > 0 {
p = s .table [:]
var code_len uint32
if !checkInputAmount (br , shortFillBitWindowRead ) {
s .symbol = symbol
s .repeat = repeat
s .prev_code_len = prev_code_len
s .repeat_code_len = repeat_code_len
s .space = space
return decoderNeedsMoreInput
}
fillBitWindow16 (br )
p = p [getBitsUnmasked (br )&uint64 (bitMask (huffmanMaxCodeLengthCodeLength )):]
dropBits (br , uint32 (p [0 ].bits ))
code_len = uint32 (p [0 ].value )
if code_len < repeatPreviousCodeLength {
processSingleCodeLength (code_len , &symbol , &repeat , &space , &prev_code_len , symbol_lists , code_length_histo , next_symbol )
} else {
var extra_bits uint32
if code_len == repeatPreviousCodeLength {
extra_bits = 2
} else {
extra_bits = 3
}
var repeat_delta uint32 = uint32 (getBitsUnmasked (br )) & bitMask (extra_bits )
dropBits (br , extra_bits )
processRepeatedCodeLength (code_len , repeat_delta , alphabet_size , &symbol , &repeat , &space , &prev_code_len , &repeat_code_len , symbol_lists , code_length_histo , next_symbol )
}
}
s .space = space
return decoderSuccess
}
func safeReadSymbolCodeLengths(alphabet_size uint32 , s *Reader ) int {
var br *bitReader = &s .br
var get_byte bool = false
var p []huffmanCode
for s .symbol < alphabet_size && s .space > 0 {
p = s .table [:]
var code_len uint32
var available_bits uint32
var bits uint32 = 0
if get_byte && !pullByte (br ) {
return decoderNeedsMoreInput
}
get_byte = false
available_bits = getAvailableBits (br )
if available_bits != 0 {
bits = uint32 (getBitsUnmasked (br ))
}
p = p [bits &bitMask (huffmanMaxCodeLengthCodeLength ):]
if uint32 (p [0 ].bits ) > available_bits {
get_byte = true
continue
}
code_len = uint32 (p [0 ].value )
if code_len < repeatPreviousCodeLength {
dropBits (br , uint32 (p [0 ].bits ))
processSingleCodeLength (code_len , &s .symbol , &s .repeat , &s .space , &s .prev_code_len , s .symbol_lists , s .code_length_histo [:], s .next_symbol [:])
} else {
var extra_bits uint32 = code_len - 14
var repeat_delta uint32 = (bits >> p [0 ].bits ) & bitMask (extra_bits )
if available_bits < uint32 (p [0 ].bits )+extra_bits {
get_byte = true
continue
}
dropBits (br , uint32 (p [0 ].bits )+extra_bits )
processRepeatedCodeLength (code_len , repeat_delta , alphabet_size , &s .symbol , &s .repeat , &s .space , &s .prev_code_len , &s .repeat_code_len , s .symbol_lists , s .code_length_histo [:], s .next_symbol [:])
}
}
return decoderSuccess
}
func readCodeLengthCodeLengths(s *Reader ) int {
var br *bitReader = &s .br
var num_codes uint32 = s .repeat
var space uint32 = s .space
var i uint32 = s .sub_loop_counter
for ; i < codeLengthCodes ; i ++ {
var code_len_idx byte = kCodeLengthCodeOrder [i ]
var ix uint32
var v uint32
if !safeGetBits (br , 4 , &ix ) {
var available_bits uint32 = getAvailableBits (br )
if available_bits != 0 {
ix = uint32 (getBitsUnmasked (br ) & 0xF )
} else {
ix = 0
}
if uint32 (kCodeLengthPrefixLength [ix ]) > available_bits {
s .sub_loop_counter = i
s .repeat = num_codes
s .space = space
s .substate_huffman = stateHuffmanComplex
return decoderNeedsMoreInput
}
}
v = uint32 (kCodeLengthPrefixValue [ix ])
dropBits (br , uint32 (kCodeLengthPrefixLength [ix ]))
s .code_length_code_lengths [code_len_idx ] = byte (v )
if v != 0 {
space = space - (32 >> v )
num_codes ++
s .code_length_histo [v ]++
if space -1 >= 32 {
break
}
}
}
if num_codes != 1 && space != 0 {
return decoderErrorFormatClSpace
}
return decoderSuccess
}
func readHuffmanCode(alphabet_size uint32 , max_symbol uint32 , table []huffmanCode , opt_table_size *uint32 , s *Reader ) int {
var br *bitReader = &s .br
alphabet_size &= 0x7FF
for {
switch s .substate_huffman {
case stateHuffmanNone :
if !safeReadBits (br , 2 , &s .sub_loop_counter ) {
return decoderNeedsMoreInput
}
if s .sub_loop_counter != 1 {
s .space = 32
s .repeat = 0
var i int
for i = 0 ; i <= huffmanMaxCodeLengthCodeLength ; i ++ {
s .code_length_histo [i ] = 0
}
for i = 0 ; i < codeLengthCodes ; i ++ {
s .code_length_code_lengths [i ] = 0
}
s .substate_huffman = stateHuffmanComplex
continue
}
fallthrough
case stateHuffmanSimpleSize :
if !safeReadBits (br , 2 , &s .symbol ) {
s .substate_huffman = stateHuffmanSimpleSize
return decoderNeedsMoreInput
}
s .sub_loop_counter = 0
fallthrough
case stateHuffmanSimpleRead :
{
var result int = readSimpleHuffmanSymbols (alphabet_size , max_symbol , s )
if result != decoderSuccess {
return result
}
}
fallthrough
case stateHuffmanSimpleBuild :
var table_size uint32
if s .symbol == 3 {
var bits uint32
if !safeReadBits (br , 1 , &bits ) {
s .substate_huffman = stateHuffmanSimpleBuild
return decoderNeedsMoreInput
}
s .symbol += bits
}
table_size = buildSimpleHuffmanTable (table , huffmanTableBits , s .symbols_lists_array [:], s .symbol )
if opt_table_size != nil {
*opt_table_size = table_size
}
s .substate_huffman = stateHuffmanNone
return decoderSuccess
case stateHuffmanComplex :
{
var i uint32
var result int = readCodeLengthCodeLengths (s )
if result != decoderSuccess {
return result
}
buildCodeLengthsHuffmanTable (s .table [:], s .code_length_code_lengths [:], s .code_length_histo [:])
for i = 0 ; i < 16 ; i ++ {
s .code_length_histo [i ] = 0
}
for i = 0 ; i <= huffmanMaxCodeLength ; i ++ {
s .next_symbol [i ] = int (i ) - (huffmanMaxCodeLength + 1 )
symbolListPut (s .symbol_lists , s .next_symbol [i ], 0xFFFF )
}
s .symbol = 0
s .prev_code_len = initialRepeatedCodeLength
s .repeat = 0
s .repeat_code_len = 0
s .space = 32768
s .substate_huffman = stateHuffmanLengthSymbols
}
fallthrough
case stateHuffmanLengthSymbols :
var table_size uint32
var result int = readSymbolCodeLengths (max_symbol , s )
if result == decoderNeedsMoreInput {
result = safeReadSymbolCodeLengths (max_symbol , s )
}
if result != decoderSuccess {
return result
}
if s .space != 0 {
return decoderErrorFormatHuffmanSpace
}
table_size = buildHuffmanTable (table , huffmanTableBits , s .symbol_lists , s .code_length_histo [:])
if opt_table_size != nil {
*opt_table_size = table_size
}
s .substate_huffman = stateHuffmanNone
return decoderSuccess
default :
return decoderErrorUnreachable
}
}
}
func readBlockLength(table []huffmanCode , br *bitReader ) uint32 {
var code uint32
var nbits uint32
code = readSymbol (table , br )
nbits = kBlockLengthPrefixCode [code ].nbits
return kBlockLengthPrefixCode [code ].offset + readBits (br , nbits )
}
func safeReadBlockLength(s *Reader , result *uint32 , table []huffmanCode , br *bitReader ) bool {
var index uint32
if s .substate_read_block_length == stateReadBlockLengthNone {
if !safeReadSymbol (table , br , &index ) {
return false
}
} else {
index = s .block_length_index
}
{
var bits uint32
var nbits uint32 = kBlockLengthPrefixCode [index ].nbits
if !safeReadBits (br , nbits , &bits ) {
s .block_length_index = index
s .substate_read_block_length = stateReadBlockLengthSuffix
return false
}
*result = kBlockLengthPrefixCode [index ].offset + bits
s .substate_read_block_length = stateReadBlockLengthNone
return true
}
}
func inverseMoveToFrontTransform(v []byte , v_len uint32 , state *Reader ) {
var mtf [256 ]byte
var i int
for i = 1 ; i < 256 ; i ++ {
mtf [i ] = byte (i )
}
var mtf_1 byte
for i = 0 ; uint32 (i ) < v_len ; i ++ {
var index int = int (v [i ])
var value byte = mtf [index ]
v [i ] = value
mtf_1 = value
for index >= 1 {
index --
mtf [index +1 ] = mtf [index ]
}
mtf [0 ] = mtf_1
}
}
func huffmanTreeGroupDecode(group *huffmanTreeGroup , s *Reader ) int {
if s .substate_tree_group != stateTreeGroupLoop {
s .next = group .codes
s .htree_index = 0
s .substate_tree_group = stateTreeGroupLoop
}
for s .htree_index < int (group .num_htrees ) {
var table_size uint32
var result int = readHuffmanCode (uint32 (group .alphabet_size ), uint32 (group .max_symbol ), s .next , &table_size , s )
if result != decoderSuccess {
return result
}
group .htrees [s .htree_index ] = s .next
s .next = s .next [table_size :]
s .htree_index ++
}
s .substate_tree_group = stateTreeGroupNone
return decoderSuccess
}
func decodeContextMap(context_map_size uint32 , num_htrees *uint32 , context_map_arg *[]byte , s *Reader ) int {
var br *bitReader = &s .br
var result int = decoderSuccess
switch int (s .substate_context_map ) {
case stateContextMapNone :
result = decodeVarLenUint8 (s , br , num_htrees )
if result != decoderSuccess {
return result
}
(*num_htrees )++
s .context_index = 0
*context_map_arg = make ([]byte , uint (context_map_size ))
if *context_map_arg == nil {
return decoderErrorAllocContextMap
}
if *num_htrees <= 1 {
for i := 0 ; i < int (context_map_size ); i ++ {
(*context_map_arg )[i ] = 0
}
return decoderSuccess
}
s .substate_context_map = stateContextMapReadPrefix
fallthrough
case stateContextMapReadPrefix :
{
var bits uint32
if !safeGetBits (br , 5 , &bits ) {
return decoderNeedsMoreInput
}
if bits &1 != 0 {
s .max_run_length_prefix = (bits >> 1 ) + 1
dropBits (br , 5 )
} else {
s .max_run_length_prefix = 0
dropBits (br , 1 )
}
s .substate_context_map = stateContextMapHuffman
}
fallthrough
case stateContextMapHuffman :
{
var alphabet_size uint32 = *num_htrees + s .max_run_length_prefix
result = readHuffmanCode (alphabet_size , alphabet_size , s .context_map_table [:], nil , s )
if result != decoderSuccess {
return result
}
s .code = 0xFFFF
s .substate_context_map = stateContextMapDecode
}
fallthrough
case stateContextMapDecode :
{
var context_index uint32 = s .context_index
var max_run_length_prefix uint32 = s .max_run_length_prefix
var context_map []byte = *context_map_arg
var code uint32 = s .code
var skip_preamble bool = (code != 0xFFFF )
for context_index < context_map_size || skip_preamble {
if !skip_preamble {
if !safeReadSymbol (s .context_map_table [:], br , &code ) {
s .code = 0xFFFF
s .context_index = context_index
return decoderNeedsMoreInput
}
if code == 0 {
context_map [context_index ] = 0
context_index ++
continue
}
if code > max_run_length_prefix {
context_map [context_index ] = byte (code - max_run_length_prefix )
context_index ++
continue
}
} else {
skip_preamble = false
}
{
var reps uint32
if !safeReadBits (br , code , &reps ) {
s .code = code
s .context_index = context_index
return decoderNeedsMoreInput
}
reps += 1 << code
if context_index +reps > context_map_size {
return decoderErrorFormatContextMapRepeat
}
for {
context_map [context_index ] = 0
context_index ++
reps --
if reps == 0 {
break
}
}
}
}
}
fallthrough
case stateContextMapTransform :
var bits uint32
if !safeReadBits (br , 1 , &bits ) {
s .substate_context_map = stateContextMapTransform
return decoderNeedsMoreInput
}
if bits != 0 {
inverseMoveToFrontTransform (*context_map_arg , context_map_size , s )
}
s .substate_context_map = stateContextMapNone
return decoderSuccess
default :
return decoderErrorUnreachable
}
}
func decodeBlockTypeAndLength(safe int , s *Reader , tree_type int ) bool {
var max_block_type uint32 = s .num_block_types [tree_type ]
type_tree := s .block_type_trees [tree_type *huffmanMaxSize258 :]
len_tree := s .block_len_trees [tree_type *huffmanMaxSize26 :]
var br *bitReader = &s .br
var ringbuffer []uint32 = s .block_type_rb [tree_type *2 :]
var block_type uint32
if max_block_type <= 1 {
return false
}
if safe == 0 {
block_type = readSymbol (type_tree , br )
s .block_length [tree_type ] = readBlockLength (len_tree , br )
} else {
var memento bitReaderState
bitReaderSaveState (br , &memento )
if !safeReadSymbol (type_tree , br , &block_type ) {
return false
}
if !safeReadBlockLength (s , &s .block_length [tree_type ], len_tree , br ) {
s .substate_read_block_length = stateReadBlockLengthNone
bitReaderRestoreState (br , &memento )
return false
}
}
if block_type == 1 {
block_type = ringbuffer [1 ] + 1
} else if block_type == 0 {
block_type = ringbuffer [0 ]
} else {
block_type -= 2
}
if block_type >= max_block_type {
block_type -= max_block_type
}
ringbuffer [0 ] = ringbuffer [1 ]
ringbuffer [1 ] = block_type
return true
}
func detectTrivialLiteralBlockTypes(s *Reader ) {
var i uint
for i = 0 ; i < 8 ; i ++ {
s .trivial_literal_contexts [i ] = 0
}
for i = 0 ; uint32 (i ) < s .num_block_types [0 ]; i ++ {
var offset uint = i << literalContextBits
var error uint = 0
var sample uint = uint (s .context_map [offset ])
var j uint
for j = 0 ; j < 1 <<literalContextBits ; {
var k int
for k = 0 ; k < 4 ; k ++ {
error |= uint (s .context_map [offset +j ]) ^ sample
j ++
}
}
if error == 0 {
s .trivial_literal_contexts [i >>5 ] |= 1 << (i & 31 )
}
}
}
func prepareLiteralDecoding(s *Reader ) {
var context_mode byte
var trivial uint
var block_type uint32 = s .block_type_rb [1 ]
var context_offset uint32 = block_type << literalContextBits
s .context_map_slice = s .context_map [context_offset :]
trivial = uint (s .trivial_literal_contexts [block_type >>5 ])
s .trivial_literal_context = int ((trivial >> (block_type & 31 )) & 1 )
s .literal_htree = []huffmanCode (s .literal_hgroup .htrees [s .context_map_slice [0 ]])
context_mode = s .context_modes [block_type ] & 3
s .context_lookup = getContextLUT (int (context_mode ))
}
func decodeLiteralBlockSwitchInternal(safe int , s *Reader ) bool {
if !decodeBlockTypeAndLength (safe , s , 0 ) {
return false
}
prepareLiteralDecoding (s )
return true
}
func decodeLiteralBlockSwitch(s *Reader ) {
decodeLiteralBlockSwitchInternal (0 , s )
}
func safeDecodeLiteralBlockSwitch(s *Reader ) bool {
return decodeLiteralBlockSwitchInternal (1 , s )
}
func decodeCommandBlockSwitchInternal(safe int , s *Reader ) bool {
if !decodeBlockTypeAndLength (safe , s , 1 ) {
return false
}
s .htree_command = []huffmanCode (s .insert_copy_hgroup .htrees [s .block_type_rb [3 ]])
return true
}
func decodeCommandBlockSwitch(s *Reader ) {
decodeCommandBlockSwitchInternal (0 , s )
}
func safeDecodeCommandBlockSwitch(s *Reader ) bool {
return decodeCommandBlockSwitchInternal (1 , s )
}
func decodeDistanceBlockSwitchInternal(safe int , s *Reader ) bool {
if !decodeBlockTypeAndLength (safe , s , 2 ) {
return false
}
s .dist_context_map_slice = s .dist_context_map [s .block_type_rb [5 ]<<distanceContextBits :]
s .dist_htree_index = s .dist_context_map_slice [s .distance_context ]
return true
}
func decodeDistanceBlockSwitch(s *Reader ) {
decodeDistanceBlockSwitchInternal (0 , s )
}
func safeDecodeDistanceBlockSwitch(s *Reader ) bool {
return decodeDistanceBlockSwitchInternal (1 , s )
}
func unwrittenBytes(s *Reader , wrap bool ) uint {
var pos uint
if wrap && s .pos > s .ringbuffer_size {
pos = uint (s .ringbuffer_size )
} else {
pos = uint (s .pos )
}
var partial_pos_rb uint = (s .rb_roundtrips * uint (s .ringbuffer_size )) + pos
return partial_pos_rb - s .partial_pos_out
}
func writeRingBuffer(s *Reader , available_out *uint , next_out *[]byte , total_out *uint , force bool ) int {
start := s .ringbuffer [s .partial_pos_out &uint (s .ringbuffer_mask ):]
var to_write uint = unwrittenBytes (s , true )
var num_written uint = *available_out
if num_written > to_write {
num_written = to_write
}
if s .meta_block_remaining_len < 0 {
return decoderErrorFormatBlockLength1
}
if next_out != nil && *next_out == nil {
*next_out = start
} else {
if next_out != nil {
copy (*next_out , start [:num_written ])
*next_out = (*next_out )[num_written :]
}
}
*available_out -= num_written
s .partial_pos_out += num_written
if total_out != nil {
*total_out = s .partial_pos_out
}
if num_written < to_write {
if s .ringbuffer_size == 1 <<s .window_bits || force {
return decoderNeedsMoreOutput
} else {
return decoderSuccess
}
}
if s .ringbuffer_size == 1 <<s .window_bits && s .pos >= s .ringbuffer_size {
s .pos -= s .ringbuffer_size
s .rb_roundtrips ++
if uint (s .pos ) != 0 {
s .should_wrap_ringbuffer = 1
} else {
s .should_wrap_ringbuffer = 0
}
}
return decoderSuccess
}
func wrapRingBuffer(s *Reader ) {
if s .should_wrap_ringbuffer != 0 {
copy (s .ringbuffer , s .ringbuffer_end [:uint (s .pos )])
s .should_wrap_ringbuffer = 0
}
}
func ensureRingBuffer(s *Reader ) bool {
var old_ringbuffer []byte
if s .ringbuffer_size == s .new_ringbuffer_size {
return true
}
spaceNeeded := int (s .new_ringbuffer_size ) + int (kRingBufferWriteAheadSlack )
if len (s .ringbuffer ) < spaceNeeded {
old_ringbuffer = s .ringbuffer
s .ringbuffer = make ([]byte , spaceNeeded )
}
s .ringbuffer [s .new_ringbuffer_size -2 ] = 0
s .ringbuffer [s .new_ringbuffer_size -1 ] = 0
if old_ringbuffer != nil {
copy (s .ringbuffer , old_ringbuffer [:uint (s .pos )])
}
s .ringbuffer_size = s .new_ringbuffer_size
s .ringbuffer_mask = s .new_ringbuffer_size - 1
s .ringbuffer_end = s .ringbuffer [s .ringbuffer_size :]
return true
}
func copyUncompressedBlockToOutput(available_out *uint , next_out *[]byte , total_out *uint , s *Reader ) int {
if !ensureRingBuffer (s ) {
return decoderErrorAllocRingBuffer1
}
for {
switch s .substate_uncompressed {
case stateUncompressedNone :
{
var nbytes int = int (getRemainingBytes (&s .br ))
if nbytes > s .meta_block_remaining_len {
nbytes = s .meta_block_remaining_len
}
if s .pos +nbytes > s .ringbuffer_size {
nbytes = s .ringbuffer_size - s .pos
}
copyBytes (s .ringbuffer [s .pos :], &s .br , uint (nbytes ))
s .pos += nbytes
s .meta_block_remaining_len -= nbytes
if s .pos < 1 <<s .window_bits {
if s .meta_block_remaining_len == 0 {
return decoderSuccess
}
return decoderNeedsMoreInput
}
s .substate_uncompressed = stateUncompressedWrite
}
fallthrough
case stateUncompressedWrite :
{
result := writeRingBuffer (s , available_out , next_out , total_out , false )
if result != decoderSuccess {
return result
}
if s .ringbuffer_size == 1 <<s .window_bits {
s .max_distance = s .max_backward_distance
}
s .substate_uncompressed = stateUncompressedNone
break
}
}
}
}
func calculateRingBufferSize(s *Reader ) {
var window_size int = 1 << s .window_bits
var new_ringbuffer_size int = window_size
var min_size int
if s .ringbuffer_size != 0 {
min_size = s .ringbuffer_size
} else {
min_size = 1024
}
var output_size int
if s .ringbuffer_size == window_size {
return
}
if s .is_metadata != 0 {
return
}
if s .ringbuffer == nil {
output_size = 0
} else {
output_size = s .pos
}
output_size += s .meta_block_remaining_len
if min_size < output_size {
min_size = output_size
}
if !(s .canny_ringbuffer_allocation == 0 ) {
for new_ringbuffer_size >>1 >= min_size {
new_ringbuffer_size >>= 1
}
}
s .new_ringbuffer_size = new_ringbuffer_size
}
func readContextModes(s *Reader ) int {
var br *bitReader = &s .br
var i int = s .loop_counter
for i < int (s .num_block_types [0 ]) {
var bits uint32
if !safeReadBits (br , 2 , &bits ) {
s .loop_counter = i
return decoderNeedsMoreInput
}
s .context_modes [i ] = byte (bits )
i ++
}
return decoderSuccess
}
func takeDistanceFromRingBuffer(s *Reader ) {
if s .distance_code == 0 {
s .dist_rb_idx --
s .distance_code = s .dist_rb [s .dist_rb_idx &3 ]
s .distance_context = 1
} else {
var distance_code int = s .distance_code << 1
const kDistanceShortCodeIndexOffset uint32 = 0xAAAFFF1B
const kDistanceShortCodeValueOffset uint32 = 0xFA5FA500
var v int = (s .dist_rb_idx + int (kDistanceShortCodeIndexOffset >>uint (distance_code ))) & 0x3
s .distance_code = s .dist_rb [v ]
v = int (kDistanceShortCodeValueOffset >>uint (distance_code )) & 0x3
if distance_code &0x3 != 0 {
s .distance_code += v
} else {
s .distance_code -= v
if s .distance_code <= 0 {
s .distance_code = 0x7FFFFFFF
}
}
}
}
func safeReadBitsMaybeZero(br *bitReader , n_bits uint32 , val *uint32 ) bool {
if n_bits != 0 {
return safeReadBits (br , n_bits , val )
} else {
*val = 0
return true
}
}
func readDistanceInternal(safe int , s *Reader , br *bitReader ) bool {
var distval int
var memento bitReaderState
var distance_tree []huffmanCode = []huffmanCode (s .distance_hgroup .htrees [s .dist_htree_index ])
if safe == 0 {
s .distance_code = int (readSymbol (distance_tree , br ))
} else {
var code uint32
bitReaderSaveState (br , &memento )
if !safeReadSymbol (distance_tree , br , &code ) {
return false
}
s .distance_code = int (code )
}
s .distance_context = 0
if s .distance_code &^0xF == 0 {
takeDistanceFromRingBuffer (s )
s .block_length [2 ]--
return true
}
distval = s .distance_code - int (s .num_direct_distance_codes )
if distval >= 0 {
var nbits uint32
var postfix int
var offset int
if safe == 0 && (s .distance_postfix_bits == 0 ) {
nbits = (uint32 (distval ) >> 1 ) + 1
offset = ((2 + (distval & 1 )) << nbits ) - 4
s .distance_code = int (s .num_direct_distance_codes ) + offset + int (readBits (br , nbits ))
} else {
var bits uint32
postfix = distval & s .distance_postfix_mask
distval >>= s .distance_postfix_bits
nbits = (uint32 (distval ) >> 1 ) + 1
if safe != 0 {
if !safeReadBitsMaybeZero (br , nbits , &bits ) {
s .distance_code = -1
bitReaderRestoreState (br , &memento )
return false
}
} else {
bits = readBits (br , nbits )
}
offset = ((2 + (distval & 1 )) << nbits ) - 4
s .distance_code = int (s .num_direct_distance_codes ) + ((offset + int (bits )) << s .distance_postfix_bits ) + postfix
}
}
s .distance_code = s .distance_code - numDistanceShortCodes + 1
s .block_length [2 ]--
return true
}
func readDistance(s *Reader , br *bitReader ) {
readDistanceInternal (0 , s , br )
}
func safeReadDistance(s *Reader , br *bitReader ) bool {
return readDistanceInternal (1 , s , br )
}
func readCommandInternal(safe int , s *Reader , br *bitReader , insert_length *int ) bool {
var cmd_code uint32
var insert_len_extra uint32 = 0
var copy_length uint32
var v cmdLutElement
var memento bitReaderState
if safe == 0 {
cmd_code = readSymbol (s .htree_command , br )
} else {
bitReaderSaveState (br , &memento )
if !safeReadSymbol (s .htree_command , br , &cmd_code ) {
return false
}
}
v = kCmdLut [cmd_code ]
s .distance_code = int (v .distance_code )
s .distance_context = int (v .context )
s .dist_htree_index = s .dist_context_map_slice [s .distance_context ]
*insert_length = int (v .insert_len_offset )
if safe == 0 {
if v .insert_len_extra_bits != 0 {
insert_len_extra = readBits (br , uint32 (v .insert_len_extra_bits ))
}
copy_length = readBits (br , uint32 (v .copy_len_extra_bits ))
} else {
if !safeReadBitsMaybeZero (br , uint32 (v .insert_len_extra_bits ), &insert_len_extra ) || !safeReadBitsMaybeZero (br , uint32 (v .copy_len_extra_bits ), ©_length ) {
bitReaderRestoreState (br , &memento )
return false
}
}
s .copy_length = int (copy_length ) + int (v .copy_len_offset )
s .block_length [1 ]--
*insert_length += int (insert_len_extra )
return true
}
func readCommand(s *Reader , br *bitReader , insert_length *int ) {
readCommandInternal (0 , s , br , insert_length )
}
func safeReadCommand(s *Reader , br *bitReader , insert_length *int ) bool {
return readCommandInternal (1 , s , br , insert_length )
}
func checkInputAmountMaybeSafe(safe int , br *bitReader , num uint ) bool {
if safe != 0 {
return true
}
return checkInputAmount (br , num )
}
func processCommandsInternal(safe int , s *Reader ) int {
var pos int = s .pos
var i int = s .loop_counter
var result int = decoderSuccess
var br *bitReader = &s .br
var hc []huffmanCode
if !checkInputAmountMaybeSafe (safe , br , 28 ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
if safe == 0 {
warmupBitReader (br )
}
if s .state == stateCommandBegin {
goto CommandBegin
} else if s .state == stateCommandInner {
goto CommandInner
} else if s .state == stateCommandPostDecodeLiterals {
goto CommandPostDecodeLiterals
} else if s .state == stateCommandPostWrapCopy {
goto CommandPostWrapCopy
} else {
return decoderErrorUnreachable
}
CommandBegin :
if safe != 0 {
s .state = stateCommandBegin
}
if !checkInputAmountMaybeSafe (safe , br , 28 ) {
s .state = stateCommandBegin
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
if s .block_length [1 ] == 0 {
if safe != 0 {
if !safeDecodeCommandBlockSwitch (s ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
} else {
decodeCommandBlockSwitch (s )
}
goto CommandBegin
}
if safe != 0 {
if !safeReadCommand (s , br , &i ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
} else {
readCommand (s , br , &i )
}
if i == 0 {
goto CommandPostDecodeLiterals
}
s .meta_block_remaining_len -= i
CommandInner :
if safe != 0 {
s .state = stateCommandInner
}
if s .trivial_literal_context != 0 {
var bits uint32
var value uint32
preloadSymbol (safe , s .literal_htree , br , &bits , &value )
for {
if !checkInputAmountMaybeSafe (safe , br , 28 ) {
s .state = stateCommandInner
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
if s .block_length [0 ] == 0 {
if safe != 0 {
if !safeDecodeLiteralBlockSwitch (s ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
} else {
decodeLiteralBlockSwitch (s )
}
preloadSymbol (safe , s .literal_htree , br , &bits , &value )
if s .trivial_literal_context == 0 {
goto CommandInner
}
}
if safe == 0 {
s .ringbuffer [pos ] = byte (readPreloadedSymbol (s .literal_htree , br , &bits , &value ))
} else {
var literal uint32
if !safeReadSymbol (s .literal_htree , br , &literal ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
s .ringbuffer [pos ] = byte (literal )
}
s .block_length [0 ]--
pos ++
if pos == s .ringbuffer_size {
s .state = stateCommandInnerWrite
i --
goto saveStateAndReturn
}
i --
if i == 0 {
break
}
}
} else {
var p1 byte = s .ringbuffer [(pos -1 )&s .ringbuffer_mask ]
var p2 byte = s .ringbuffer [(pos -2 )&s .ringbuffer_mask ]
for {
var context byte
if !checkInputAmountMaybeSafe (safe , br , 28 ) {
s .state = stateCommandInner
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
if s .block_length [0 ] == 0 {
if safe != 0 {
if !safeDecodeLiteralBlockSwitch (s ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
} else {
decodeLiteralBlockSwitch (s )
}
if s .trivial_literal_context != 0 {
goto CommandInner
}
}
context = getContext (p1 , p2 , s .context_lookup )
hc = []huffmanCode (s .literal_hgroup .htrees [s .context_map_slice [context ]])
p2 = p1
if safe == 0 {
p1 = byte (readSymbol (hc , br ))
} else {
var literal uint32
if !safeReadSymbol (hc , br , &literal ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
p1 = byte (literal )
}
s .ringbuffer [pos ] = p1
s .block_length [0 ]--
pos ++
if pos == s .ringbuffer_size {
s .state = stateCommandInnerWrite
i --
goto saveStateAndReturn
}
i --
if i == 0 {
break
}
}
}
if s .meta_block_remaining_len <= 0 {
s .state = stateMetablockDone
goto saveStateAndReturn
}
CommandPostDecodeLiterals :
if safe != 0 {
s .state = stateCommandPostDecodeLiterals
}
if s .distance_code >= 0 {
if s .distance_code != 0 {
s .distance_context = 0
} else {
s .distance_context = 1
}
s .dist_rb_idx --
s .distance_code = s .dist_rb [s .dist_rb_idx &3 ]
} else {
if s .block_length [2 ] == 0 {
if safe != 0 {
if !safeDecodeDistanceBlockSwitch (s ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
} else {
decodeDistanceBlockSwitch (s )
}
}
if safe != 0 {
if !safeReadDistance (s , br ) {
result = decoderNeedsMoreInput
goto saveStateAndReturn
}
} else {
readDistance (s , br )
}
}
if s .max_distance != s .max_backward_distance {
if pos < s .max_backward_distance {
s .max_distance = pos
} else {
s .max_distance = s .max_backward_distance
}
}
i = s .copy_length
if s .distance_code > s .max_distance {
if s .distance_code > maxAllowedDistance {
return decoderErrorFormatDistance
}
if i >= minDictionaryWordLength && i <= maxDictionaryWordLength {
var address int = s .distance_code - s .max_distance - 1
var words *dictionary = s .dictionary
var trans *transforms = s .transforms
var offset int = int (s .dictionary .offsets_by_length [i ])
var shift uint32 = uint32 (s .dictionary .size_bits_by_length [i ])
var mask int = int (bitMask (shift ))
var word_idx int = address & mask
var transform_idx int = address >> shift
s .dist_rb_idx += s .distance_context
offset += word_idx * i
if words .data == nil {
return decoderErrorDictionaryNotSet
}
if transform_idx < int (trans .num_transforms ) {
word := words .data [offset :]
var len int = i
if transform_idx == int (trans .cutOffTransforms [0 ]) {
copy (s .ringbuffer [pos :], word [:uint (len )])
} else {
len = transformDictionaryWord (s .ringbuffer [pos :], word , int (len ), trans , transform_idx )
}
pos += int (len )
s .meta_block_remaining_len -= int (len )
if pos >= s .ringbuffer_size {
s .state = stateCommandPostWrite1
goto saveStateAndReturn
}
} else {
return decoderErrorFormatTransform
}
} else {
return decoderErrorFormatDictionary
}
} else {
var src_start int = (pos - s .distance_code ) & s .ringbuffer_mask
copy_dst := s .ringbuffer [pos :]
copy_src := s .ringbuffer [src_start :]
var dst_end int = pos + i
var src_end int = src_start + i
s .dist_rb [s .dist_rb_idx &3 ] = s .distance_code
s .dist_rb_idx ++
s .meta_block_remaining_len -= i
copy (copy_dst , copy_src [:16 ])
if src_end > pos && dst_end > src_start {
goto CommandPostWrapCopy
}
if dst_end >= s .ringbuffer_size || src_end >= s .ringbuffer_size {
goto CommandPostWrapCopy
}
pos += i
if i > 16 {
if i > 32 {
copy (copy_dst [16 :], copy_src [16 :][:uint (i -16 )])
} else {
copy (copy_dst [16 :], copy_src [16 :][:16 ])
}
}
}
if s .meta_block_remaining_len <= 0 {
s .state = stateMetablockDone
goto saveStateAndReturn
} else {
goto CommandBegin
}
CommandPostWrapCopy :
{
var wrap_guard int = s .ringbuffer_size - pos
for {
i --
if i < 0 {
break
}
s .ringbuffer [pos ] = s .ringbuffer [(pos -s .distance_code )&s .ringbuffer_mask ]
pos ++
wrap_guard --
if wrap_guard == 0 {
s .state = stateCommandPostWrite2
goto saveStateAndReturn
}
}
}
if s .meta_block_remaining_len <= 0 {
s .state = stateMetablockDone
goto saveStateAndReturn
} else {
goto CommandBegin
}
saveStateAndReturn :
s .pos = pos
s .loop_counter = i
return result
}
func processCommands(s *Reader ) int {
return processCommandsInternal (0 , s )
}
func safeProcessCommands(s *Reader ) int {
return processCommandsInternal (1 , s )
}
var maxDistanceSymbol_bound = [maxNpostfix + 1 ]uint32 {0 , 4 , 12 , 28 }
var maxDistanceSymbol_diff = [maxNpostfix + 1 ]uint32 {73 , 126 , 228 , 424 }
func maxDistanceSymbol(ndirect uint32 , npostfix uint32 ) uint32 {
var postfix uint32 = 1 << npostfix
if ndirect < maxDistanceSymbol_bound [npostfix ] {
return ndirect + maxDistanceSymbol_diff [npostfix ] + postfix
} else if ndirect > maxDistanceSymbol_bound [npostfix ]+postfix {
return ndirect + maxDistanceSymbol_diff [npostfix ]
} else {
return maxDistanceSymbol_bound [npostfix ] + maxDistanceSymbol_diff [npostfix ] + postfix
}
}
func decoderDecompressStream(s *Reader , available_in *uint , next_in *[]byte , available_out *uint , next_out *[]byte ) int {
var result int = decoderSuccess
var br *bitReader = &s .br
if int (s .error_code ) < 0 {
return decoderResultError
}
if *available_out != 0 && (next_out == nil || *next_out == nil ) {
return saveErrorCode (s , decoderErrorInvalidArguments )
}
if *available_out == 0 {
next_out = nil
}
if s .buffer_length == 0 {
br .input_len = *available_in
br .input = *next_in
br .byte_pos = 0
} else {
result = decoderNeedsMoreInput
br .input = s .buffer .u8 [:]
br .byte_pos = 0
}
for {
if result != decoderSuccess {
if result == decoderNeedsMoreInput {
if s .ringbuffer != nil {
var intermediate_result int = writeRingBuffer (s , available_out , next_out , nil , true )
if int (intermediate_result ) < 0 {
result = intermediate_result
break
}
}
if s .buffer_length != 0 {
if br .byte_pos == br .input_len {
s .buffer_length = 0
result = decoderSuccess
br .input_len = *available_in
br .input = *next_in
br .byte_pos = 0
continue
} else if *available_in != 0 {
result = decoderSuccess
s .buffer .u8 [s .buffer_length ] = (*next_in )[0 ]
s .buffer_length ++
br .input_len = uint (s .buffer_length )
*next_in = (*next_in )[1 :]
(*available_in )--
continue
}
break
} else {
*next_in = br .input [br .byte_pos :]
*available_in = br .input_len - br .byte_pos
for *available_in != 0 {
s .buffer .u8 [s .buffer_length ] = (*next_in )[0 ]
s .buffer_length ++
*next_in = (*next_in )[1 :]
(*available_in )--
}
break
}
}
if s .buffer_length != 0 {
s .buffer_length = 0
} else {
bitReaderUnload (br )
*available_in = br .input_len - br .byte_pos
*next_in = br .input [br .byte_pos :]
}
break
}
switch s .state {
case stateUninited :
if !warmupBitReader (br ) {
result = decoderNeedsMoreInput
break
}
result = decodeWindowBits (s , br )
if result != decoderSuccess {
break
}
if s .large_window {
s .state = stateLargeWindowBits
break
}
s .state = stateInitialize
case stateLargeWindowBits :
if !safeReadBits (br , 6 , &s .window_bits ) {
result = decoderNeedsMoreInput
break
}
if s .window_bits < largeMinWbits || s .window_bits > largeMaxWbits {
result = decoderErrorFormatWindowBits
break
}
s .state = stateInitialize
fallthrough
case stateInitialize :
s .max_backward_distance = (1 << s .window_bits ) - windowGap
s .block_type_trees = make ([]huffmanCode , (3 * (huffmanMaxSize258 + huffmanMaxSize26 )))
if s .block_type_trees == nil {
result = decoderErrorAllocBlockTypeTrees
break
}
s .block_len_trees = s .block_type_trees [3 *huffmanMaxSize258 :]
s .state = stateMetablockBegin
fallthrough
case stateMetablockBegin :
decoderStateMetablockBegin (s )
s .state = stateMetablockHeader
fallthrough
case stateMetablockHeader :
result = decodeMetaBlockLength (s , br )
if result != decoderSuccess {
break
}
if s .is_metadata != 0 || s .is_uncompressed != 0 {
if !bitReaderJumpToByteBoundary (br ) {
result = decoderErrorFormatPadding1
break
}
}
if s .is_metadata != 0 {
s .state = stateMetadata
break
}
if s .meta_block_remaining_len == 0 {
s .state = stateMetablockDone
break
}
calculateRingBufferSize (s )
if s .is_uncompressed != 0 {
s .state = stateUncompressed
break
}
s .loop_counter = 0
s .state = stateHuffmanCode0
case stateUncompressed :
result = copyUncompressedBlockToOutput (available_out , next_out , nil , s )
if result == decoderSuccess {
s .state = stateMetablockDone
}
case stateMetadata :
for ; s .meta_block_remaining_len > 0 ; s .meta_block_remaining_len -- {
var bits uint32
if !safeReadBits (br , 8 , &bits ) {
result = decoderNeedsMoreInput
break
}
}
if result == decoderSuccess {
s .state = stateMetablockDone
}
case stateHuffmanCode0 :
if s .loop_counter >= 3 {
s .state = stateMetablockHeader2
break
}
result = decodeVarLenUint8 (s , br , &s .num_block_types [s .loop_counter ])
if result != decoderSuccess {
break
}
s .num_block_types [s .loop_counter ]++
if s .num_block_types [s .loop_counter ] < 2 {
s .loop_counter ++
break
}
s .state = stateHuffmanCode1
fallthrough
case stateHuffmanCode1 :
{
var alphabet_size uint32 = s .num_block_types [s .loop_counter ] + 2
var tree_offset int = s .loop_counter * huffmanMaxSize258
result = readHuffmanCode (alphabet_size , alphabet_size , s .block_type_trees [tree_offset :], nil , s )
if result != decoderSuccess {
break
}
s .state = stateHuffmanCode2
}
fallthrough
case stateHuffmanCode2 :
{
var alphabet_size uint32 = numBlockLenSymbols
var tree_offset int = s .loop_counter * huffmanMaxSize26
result = readHuffmanCode (alphabet_size , alphabet_size , s .block_len_trees [tree_offset :], nil , s )
if result != decoderSuccess {
break
}
s .state = stateHuffmanCode3
}
fallthrough
case stateHuffmanCode3 :
var tree_offset int = s .loop_counter * huffmanMaxSize26
if !safeReadBlockLength (s , &s .block_length [s .loop_counter ], s .block_len_trees [tree_offset :], br ) {
result = decoderNeedsMoreInput
break
}
s .loop_counter ++
s .state = stateHuffmanCode0
case stateMetablockHeader2 :
{
var bits uint32
if !safeReadBits (br , 6 , &bits ) {
result = decoderNeedsMoreInput
break
}
s .distance_postfix_bits = bits & bitMask (2 )
bits >>= 2
s .num_direct_distance_codes = numDistanceShortCodes + (bits << s .distance_postfix_bits )
s .distance_postfix_mask = int (bitMask (s .distance_postfix_bits ))
s .context_modes = make ([]byte , uint (s .num_block_types [0 ]))
if s .context_modes == nil {
result = decoderErrorAllocContextModes
break
}
s .loop_counter = 0
s .state = stateContextModes
}
fallthrough
case stateContextModes :
result = readContextModes (s )
if result != decoderSuccess {
break
}
s .state = stateContextMap1
fallthrough
case stateContextMap1 :
result = decodeContextMap (s .num_block_types [0 ]<<literalContextBits , &s .num_literal_htrees , &s .context_map , s )
if result != decoderSuccess {
break
}
detectTrivialLiteralBlockTypes (s )
s .state = stateContextMap2
fallthrough
case stateContextMap2 :
{
var num_direct_codes uint32 = s .num_direct_distance_codes - numDistanceShortCodes
var num_distance_codes uint32
var max_distance_symbol uint32
if s .large_window {
num_distance_codes = uint32 (distanceAlphabetSize (uint (s .distance_postfix_bits ), uint (num_direct_codes ), largeMaxDistanceBits ))
max_distance_symbol = maxDistanceSymbol (num_direct_codes , s .distance_postfix_bits )
} else {
num_distance_codes = uint32 (distanceAlphabetSize (uint (s .distance_postfix_bits ), uint (num_direct_codes ), maxDistanceBits ))
max_distance_symbol = num_distance_codes
}
var allocation_success bool = true
result = decodeContextMap (s .num_block_types [2 ]<<distanceContextBits , &s .num_dist_htrees , &s .dist_context_map , s )
if result != decoderSuccess {
break
}
if !decoderHuffmanTreeGroupInit (s , &s .literal_hgroup , numLiteralSymbols , numLiteralSymbols , s .num_literal_htrees ) {
allocation_success = false
}
if !decoderHuffmanTreeGroupInit (s , &s .insert_copy_hgroup , numCommandSymbols , numCommandSymbols , s .num_block_types [1 ]) {
allocation_success = false
}
if !decoderHuffmanTreeGroupInit (s , &s .distance_hgroup , num_distance_codes , max_distance_symbol , s .num_dist_htrees ) {
allocation_success = false
}
if !allocation_success {
return saveErrorCode (s , decoderErrorAllocTreeGroups )
}
s .loop_counter = 0
s .state = stateTreeGroup
}
fallthrough
case stateTreeGroup :
var hgroup *huffmanTreeGroup = nil
switch s .loop_counter {
case 0 :
hgroup = &s .literal_hgroup
case 1 :
hgroup = &s .insert_copy_hgroup
case 2 :
hgroup = &s .distance_hgroup
default :
return saveErrorCode (s , decoderErrorUnreachable )
}
result = huffmanTreeGroupDecode (hgroup , s )
if result != decoderSuccess {
break
}
s .loop_counter ++
if s .loop_counter >= 3 {
prepareLiteralDecoding (s )
s .dist_context_map_slice = s .dist_context_map
s .htree_command = []huffmanCode (s .insert_copy_hgroup .htrees [0 ])
if !ensureRingBuffer (s ) {
result = decoderErrorAllocRingBuffer2
break
}
s .state = stateCommandBegin
}
case stateCommandBegin , stateCommandInner , stateCommandPostDecodeLiterals , stateCommandPostWrapCopy :
result = processCommands (s )
if result == decoderNeedsMoreInput {
result = safeProcessCommands (s )
}
case stateCommandInnerWrite , stateCommandPostWrite1 , stateCommandPostWrite2 :
result = writeRingBuffer (s , available_out , next_out , nil , false )
if result != decoderSuccess {
break
}
wrapRingBuffer (s )
if s .ringbuffer_size == 1 <<s .window_bits {
s .max_distance = s .max_backward_distance
}
if s .state == stateCommandPostWrite1 {
if s .meta_block_remaining_len == 0 {
s .state = stateMetablockDone
} else {
s .state = stateCommandBegin
}
} else if s .state == stateCommandPostWrite2 {
s .state = stateCommandPostWrapCopy
} else {
if s .loop_counter == 0 {
if s .meta_block_remaining_len == 0 {
s .state = stateMetablockDone
} else {
s .state = stateCommandPostDecodeLiterals
}
break
}
s .state = stateCommandInner
}
case stateMetablockDone :
if s .meta_block_remaining_len < 0 {
result = decoderErrorFormatBlockLength2
break
}
decoderStateCleanupAfterMetablock (s )
if s .is_last_metablock == 0 {
s .state = stateMetablockBegin
break
}
if !bitReaderJumpToByteBoundary (br ) {
result = decoderErrorFormatPadding2
break
}
if s .buffer_length == 0 {
bitReaderUnload (br )
*available_in = br .input_len - br .byte_pos
*next_in = br .input [br .byte_pos :]
}
s .state = stateDone
fallthrough
case stateDone :
if s .ringbuffer != nil {
result = writeRingBuffer (s , available_out , next_out , nil , true )
if result != decoderSuccess {
break
}
}
return saveErrorCode (s , result )
}
}
return saveErrorCode (s , result )
}
func decoderHasMoreOutput(s *Reader ) bool {
if int (s .error_code ) < 0 {
return false
}
return s .ringbuffer != nil && unwrittenBytes (s , false ) != 0
}
func decoderGetErrorCode(s *Reader ) int {
return int (s .error_code )
}
func decoderErrorString(c int ) string {
switch c {
case decoderNoError :
return "NO_ERROR"
case decoderSuccess :
return "SUCCESS"
case decoderNeedsMoreInput :
return "NEEDS_MORE_INPUT"
case decoderNeedsMoreOutput :
return "NEEDS_MORE_OUTPUT"
case decoderErrorFormatExuberantNibble :
return "EXUBERANT_NIBBLE"
case decoderErrorFormatReserved :
return "RESERVED"
case decoderErrorFormatExuberantMetaNibble :
return "EXUBERANT_META_NIBBLE"
case decoderErrorFormatSimpleHuffmanAlphabet :
return "SIMPLE_HUFFMAN_ALPHABET"
case decoderErrorFormatSimpleHuffmanSame :
return "SIMPLE_HUFFMAN_SAME"
case decoderErrorFormatClSpace :
return "CL_SPACE"
case decoderErrorFormatHuffmanSpace :
return "HUFFMAN_SPACE"
case decoderErrorFormatContextMapRepeat :
return "CONTEXT_MAP_REPEAT"
case decoderErrorFormatBlockLength1 :
return "BLOCK_LENGTH_1"
case decoderErrorFormatBlockLength2 :
return "BLOCK_LENGTH_2"
case decoderErrorFormatTransform :
return "TRANSFORM"
case decoderErrorFormatDictionary :
return "DICTIONARY"
case decoderErrorFormatWindowBits :
return "WINDOW_BITS"
case decoderErrorFormatPadding1 :
return "PADDING_1"
case decoderErrorFormatPadding2 :
return "PADDING_2"
case decoderErrorFormatDistance :
return "DISTANCE"
case decoderErrorDictionaryNotSet :
return "DICTIONARY_NOT_SET"
case decoderErrorInvalidArguments :
return "INVALID_ARGUMENTS"
case decoderErrorAllocContextModes :
return "CONTEXT_MODES"
case decoderErrorAllocTreeGroups :
return "TREE_GROUPS"
case decoderErrorAllocContextMap :
return "CONTEXT_MAP"
case decoderErrorAllocRingBuffer1 :
return "RING_BUFFER_1"
case decoderErrorAllocRingBuffer2 :
return "RING_BUFFER_2"
case decoderErrorAllocBlockTypeTrees :
return "BLOCK_TYPE_TREES"
case decoderErrorUnreachable :
return "UNREACHABLE"
default :
return "INVALID"
}
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .