// Copyright 2023 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package zstdimport ()// readLiterals reads and decompresses the literals from data at off.// The literals are appended to outbuf, which is returned.// Also returns the new input offset. RFC 3.1.1.3.1.func ( *Reader) ( block, int, []byte) (int, []byte, error) {if >= len() {return0, nil, .makeEOFError() }// Literals section header. RFC 3.1.1.3.1.1. := [] ++if (&3) == 0 || (&3) == 1 {return .readRawRLELiterals(, , , ) } else {return .readHuffLiterals(, , , ) }}// readRawRLELiterals reads and decompresses a Raw_Literals_Block or// a RLE_Literals_Block. RFC 3.1.1.3.1.1.func ( *Reader) ( block, int, byte, []byte) (int, []byte, error) { := ( & 3) == 0varintswitch ( >> 2) & 3 {case0, 2: = int( >> 3)case1:if >= len() {return0, nil, .makeEOFError() } = int(>>4) + (int([]) << 4) ++case3:if +1 >= len() {return0, nil, .makeEOFError() } = int(>>4) + (int([]) << 4) + (int([+1]) << 12) += 2 }// We are going to use the entire literal block in the output. // The maximum size of one decompressed block is 128K, // so we can't have more literals than that.if > 128<<10 {return0, nil, .makeError(, "literal size too large") }if {// RFC 3.1.1.3.1.2.if + > len() {return0, nil, .makeError(, "raw literal size too large") } = append(, [:+]...) += } else {// RFC 3.1.1.3.1.3.if >= len() {return0, nil, .makeError(, "RLE literal missing") } := [] ++for := 0; < ; ++ { = append(, ) } }return , , nil}// readHuffLiterals reads and decompresses a Compressed_Literals_Block or// a Treeless_Literals_Block. RFC 3.1.1.3.1.4.func ( *Reader) ( block, int, byte, []byte) (int, []byte, error) {var (intintint )switch ( >> 2) & 3 {case0, 1:if +1 >= len() {return0, nil, .makeEOFError() } = (int() >> 4) | ((int([]) & 0x3f) << 4) = (int([]) >> 6) | (int([+1]) << 2) += 2if (( >> 2) & 3) == 0 { = 1 } else { = 4 }case2:if +2 >= len() {return0, nil, .makeEOFError() } = (int() >> 4) | (int([]) << 4) | ((int([+1]) & 3) << 12) = (int([+1]) >> 2) | (int([+2]) << 6) += 3 = 4case3:if +3 >= len() {return0, nil, .makeEOFError() } = (int() >> 4) | (int([]) << 4) | ((int([+1]) & 0x3f) << 12) = (int([+1]) >> 6) | (int([+2]) << 2) | (int([+3]) << 10) += 4 = 4 }// We are going to use the entire literal block in the output. // The maximum size of one decompressed block is 128K, // so we can't have more literals than that.if > 128<<10 {return0, nil, .makeError(, "literal size too large") } := + if > len() || < 0 {return0, nil, .makeEOFError() } := if ( & 3) == 2 {// Compressed_Literals_Block. // Read new huffman tree.iflen(.huffmanTable) < 1<<maxHuffmanBits { .huffmanTable = make([]uint16, 1<<maxHuffmanBits) } , , := .readHuff(, , .huffmanTable)if != nil {return0, nil, } .huffmanTableBits = if < - {return0, nil, .makeError(, "Huffman table too big") } -= - = } else {// Treeless_Literals_Block // Reuse previous Huffman tree.if .huffmanTableBits == 0 {return0, nil, .makeError(, "missing literals Huffman tree") } }// Decompress compressedSize bytes of data at off using the // Huffman tree.varerrorif == 1 { , = .readLiteralsOneStream(, , , , ) } else { , = .readLiteralsFourStreams(, , , , ) }if != nil {return0, nil, }return , , nil}// readLiteralsOneStream reads a single stream of compressed literals.func ( *Reader) ( block, , , int, []byte) ([]byte, error) {// We let the reverse bit reader read earlier bytes, // because the Huffman table ignores bits that it doesn't need. , := .makeReverseBitReader(, +-1, -2)if != nil {returnnil, } := .huffmanTable := uint32(.huffmanTableBits) := (uint32(1) << ) - 1for := 0; < ; ++ {if !.fetch(uint8()) {returnnil, .makeError("literals Huffman stream out of bits") }varuint16 := (.bits >> (.cnt - )) & = [] = append(, byte(>>8)) .cnt -= uint32( & 0xff) }return , nil}// readLiteralsFourStreams reads four interleaved streams of// compressed literals.func ( *Reader) ( block, , , int, []byte) ([]byte, error) {// Read the jump table to find out where the streams are. // RFC 3.1.1.3.1.6.if +5 >= len() {returnnil, .makeEOFError() }if < 6 {returnnil, .makeError(, "total streams size too small for jump table") }// RFC 3.1.1.3.1.6. // "The decompressed size of each stream is equal to (Regenerated_Size+3)/4, // except for the last stream, which may be up to 3 bytes smaller, // to reach a total decompressed size as specified in Regenerated_Size." := ( + 3) / 4if < *3 {returnnil, .makeError(, "regenerated size too small to decode streams") } := binary.LittleEndian.Uint16([:]) := binary.LittleEndian.Uint16([+2:]) := binary.LittleEndian.Uint16([+4:]) += 6 := uint64() + uint64() + uint64()if > uint64()-6 {returnnil, .makeEOFError() } := uint32() - 6 - uint32() -- := + int() := + 1 := + int() := + 1 := + int() := + 1 := + int() := + 1// We let the reverse bit readers read earlier bytes, // because the Huffman tables ignore bits that they don't need. , := .makeReverseBitReader(, , -2)if != nil {returnnil, } , := .makeReverseBitReader(, , -2)if != nil {returnnil, } , := .makeReverseBitReader(, , -2)if != nil {returnnil, } , := .makeReverseBitReader(, , -2)if != nil {returnnil, } := len() := + := + := + := - *3 = append(, make([]byte, )...) := .huffmanTable := uint32(.huffmanTableBits) := (uint32(1) << ) - 1for := 0; < ; ++ { := < := func( *reverseBitReader) (uint16, error) {if !.fetch(uint8()) {return0, .makeError("literals Huffman stream out of bits") } := (.bits >> (.cnt - )) & return [], nil } , := (&)if != nil {returnnil, } , := (&)if != nil {returnnil, } , := (&)if != nil {returnnil, }if { , := (&)if != nil {returnnil, } [] = byte( >> 8) ++ .cnt -= uint32( & 0xff) } [] = byte( >> 8) ++ .cnt -= uint32( & 0xff) [] = byte( >> 8) ++ .cnt -= uint32( & 0xff) [] = byte( >> 8) ++ .cnt -= uint32( & 0xff) }return , nil}
The pages are generated with Goldsv0.7.0-preview. (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 @zigo_101 (reachable from the left QR code) to get the latest news of Golds.