Source File
bzip2.go
Belonging Package
compress/bzip2
package bzip2
import
type StructuralError string
func ( StructuralError) () string {
return "bzip2 data invalid: " + string()
}
type reader struct {
br bitReader
fileCRC uint32
blockCRC uint32
wantBlockCRC uint32
setupDone bool // true if we have parsed the bzip2 header.
blockSize int // blockSize in bytes, i.e. 900 * 1000.
eof bool
c [256]uint // the ``C'' array for the inverse BWT.
tt []uint32 // mirrors the ``tt'' array in the bzip2 source and contains the P array in the upper 24 bits.
tPos uint32 // Index of the next output byte in tt.
preRLE []uint32 // contains the RLE data still to be processed.
preRLEUsed int // number of entries of preRLE used.
lastByte int // the last byte value seen.
byteRepeats uint // the number of repeats of lastByte seen.
repeats uint // the number of copies of lastByte to output.
}
func ( io.Reader) io.Reader {
:= new(reader)
.br = newBitReader()
return
}
const bzip2FileMagic = 0x425a // "BZ"
const bzip2BlockMagic = 0x314159265359
const bzip2FinalMagic = 0x177245385090
func ( *reader) ( bool) error {
:= &.br
if {
:= .ReadBits(16)
if != bzip2FileMagic {
return StructuralError("bad magic value")
}
}
:= .ReadBits(8)
if != 'h' {
return StructuralError("non-Huffman entropy encoding")
}
:= .ReadBits(8)
if < '1' || > '9' {
return StructuralError("invalid compression level")
}
.fileCRC = 0
.blockSize = 100 * 1000 * ( - '0')
if .blockSize > len(.tt) {
.tt = make([]uint32, .blockSize)
}
return nil
}
func ( *reader) ( []byte) ( int, error) {
if .eof {
return 0, io.EOF
}
if !.setupDone {
= .setup(true)
:= .br.Err()
if != nil {
=
}
if != nil {
return 0,
}
.setupDone = true
}
, = .read()
:= .br.Err()
if != nil {
=
}
return
}
:= 0
if .repeats > 0 {
[] = byte(.lastByte)
++
.repeats--
if .repeats == 0 {
.lastByte = -1
}
continue
}
.tPos = .preRLE[.tPos]
:= byte(.tPos)
.tPos >>= 8
.preRLEUsed++
if .byteRepeats == 3 {
.repeats = uint()
.byteRepeats = 0
continue
}
if .lastByte == int() {
.byteRepeats++
} else {
.byteRepeats = 0
}
.lastByte = int()
[] =
++
}
return
}
func ( *reader) ( []byte) (int, error) {
for {
:= .readFromBlock()
if > 0 || len() == 0 {
.blockCRC = updateCRC(.blockCRC, [:])
return , nil
}
if .blockCRC != .wantBlockCRC {
.br.err = StructuralError("block checksum mismatch")
return 0, .br.err
}
:= &.br
switch .ReadBits64(48) {
default:
return 0, StructuralError("bad magic value found")
:= uint32(.ReadBits64(32))
if .err != nil {
return 0, .err
}
if .fileCRC != {
.err = StructuralError("file checksum mismatch")
return 0, .err
}
if .bits%8 != 0 {
.ReadBits(.bits % 8)
}
, := .r.ReadByte()
if == io.EOF {
.err = io.EOF
.eof = true
return 0, io.EOF
}
if != nil {
.err =
return 0,
}
, := .r.ReadByte()
if != nil {
if == io.EOF {
= io.ErrUnexpectedEOF
}
.err =
return 0,
}
if != 'B' || != 'Z' {
return 0, StructuralError("bad magic value in continuation file")
}
if := .setup(false); != nil {
return 0,
}
}
}
}
func ( *reader) () ( error) {
:= &.br
.wantBlockCRC = uint32(.ReadBits64(32)) // skip checksum. TODO: check it if we can figure out what it is.
.blockCRC = 0
.fileCRC = (.fileCRC<<1 | .fileCRC>>31) ^ .wantBlockCRC
:= .ReadBits(1)
if != 0 {
return StructuralError("deprecated randomized files")
}
:= uint(.ReadBits(24))
return StructuralError("no symbols in input")
}
:= .ReadBits(3)
if < 2 || > 6 {
return StructuralError("invalid number of Huffman trees")
}
:= newMTFDecoderWithRange()
for := range {
:= 0
for {
:= .ReadBits(1)
if == 0 {
break
}
++
}
if >= {
return StructuralError("tree index too large")
}
[] = .Decode()
}
:= make([]byte, )
:= 0
for := 0; < 256; ++ {
if [] {
[] = byte()
++
}
}
:= newMTFDecoder()
+= 2 // to account for RUNA and RUNB symbols
:= make([]huffmanTree, )
:= .ReadBits(5)
for := range {
for {
if < 1 || > 20 {
return StructuralError("Huffman length out of range")
}
if !.ReadBit() {
break
}
if .ReadBit() {
--
} else {
++
}
}
[] = uint8()
}
[], = newHuffmanTree()
if != nil {
return
}
}
:= 1 // the next tree index to use
if len() == 0 {
return StructuralError("no tree selectors given")
}
if int([0]) >= len() {
return StructuralError("tree selector out of range")
}
:= [[0]]
:= 0
:= 0
for := range .c {
.c[] = 0
}
:= 0 // counts the number of symbols decoded by the current tree.
for {
if == 50 {
if >= {
return StructuralError("insufficient selector indices for number of symbols")
}
if int([]) >= len() {
return StructuralError("tree selector out of range")
}
= [[]]
++
= 0
}
:= .Decode()
++
if == 0 {
= 1
}
+= <<
<<= 1
if > 2*1024*1024 {
return StructuralError("repeat count too large")
}
continue
}
break
}
:= .Decode(int( - 1))
if >= .blockSize {
return StructuralError("data exceeds block size")
}
.tt[] = uint32()
.c[]++
++
}
if >= uint() {
return StructuralError("origPtr out of bounds")
}
.preRLE = .tt[:]
.preRLEUsed = 0
.tPos = inverseBWT(.preRLE, , .c[:])
.lastByte = -1
.byteRepeats = 0
.repeats = 0
return nil
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin 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. |