@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
"sync"
"github.com/klauspost/compress/fse"
)
@ -216,6 +217,7 @@ func (s *Scratch) Decoder() *Decoder {
return & Decoder {
dt : s . dt ,
actualTableLog : s . actualTableLog ,
bufs : & s . decPool ,
}
}
@ -223,6 +225,15 @@ func (s *Scratch) Decoder() *Decoder {
type Decoder struct {
dt dTable
actualTableLog uint8
bufs * sync . Pool
}
func ( d * Decoder ) buffer ( ) * [ 4 ] [ 256 ] byte {
buf , ok := d . bufs . Get ( ) . ( * [ 4 ] [ 256 ] byte )
if ok {
return buf
}
return & [ 4 ] [ 256 ] byte { }
}
// Decompress1X will decompress a 1X encoded stream.
@ -249,7 +260,8 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
dt := d . dt . single [ : tlSize ]
// Use temp table to avoid bound checks/append penalty.
var buf [ 256 ] byte
bufs := d . buffer ( )
buf := & bufs [ 0 ]
var off uint8
for br . off >= 8 {
@ -277,6 +289,7 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
br . close ( )
d . bufs . Put ( bufs )
return nil , ErrMaxDecodedSizeExceeded
}
dst = append ( dst , buf [ : ] ... )
@ -284,6 +297,7 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
}
if len ( dst ) + int ( off ) > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -310,6 +324,7 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
}
}
if len ( dst ) >= maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -319,6 +334,7 @@ func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) {
bitsLeft -= nBits
dst = append ( dst , uint8 ( v . entry >> 8 ) )
}
d . bufs . Put ( bufs )
return dst , br . close ( )
}
@ -341,7 +357,8 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
dt := d . dt . single [ : 256 ]
// Use temp table to avoid bound checks/append penalty.
var buf [ 256 ] byte
bufs := d . buffer ( )
buf := & bufs [ 0 ]
var off uint8
switch d . actualTableLog {
@ -369,6 +386,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
br . close ( )
d . bufs . Put ( bufs )
return nil , ErrMaxDecodedSizeExceeded
}
dst = append ( dst , buf [ : ] ... )
@ -398,6 +416,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
br . close ( )
d . bufs . Put ( bufs )
return nil , ErrMaxDecodedSizeExceeded
}
dst = append ( dst , buf [ : ] ... )
@ -426,6 +445,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -455,6 +475,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -484,6 +505,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -513,6 +535,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -542,6 +565,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -571,6 +595,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -578,10 +603,12 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
}
}
default :
d . bufs . Put ( bufs )
return nil , fmt . Errorf ( "invalid tablelog: %d" , d . actualTableLog )
}
if len ( dst ) + int ( off ) > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -601,6 +628,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
}
if len ( dst ) >= maxDecodedSize {
br . close ( )
d . bufs . Put ( bufs )
return nil , ErrMaxDecodedSizeExceeded
}
v := dt [ br . peekByteFast ( ) >> shift ]
@ -609,6 +637,7 @@ func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
bitsLeft -= int8 ( nBits )
dst = append ( dst , uint8 ( v . entry >> 8 ) )
}
d . bufs . Put ( bufs )
return dst , br . close ( )
}
@ -628,7 +657,8 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
dt := d . dt . single [ : 256 ]
// Use temp table to avoid bound checks/append penalty.
var buf [ 256 ] byte
bufs := d . buffer ( )
buf := & bufs [ 0 ]
var off uint8
const shift = 56
@ -655,6 +685,7 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
off += 4
if off == 0 {
if len ( dst ) + 256 > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -663,6 +694,7 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
}
if len ( dst ) + int ( off ) > maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -679,6 +711,7 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
}
}
if len ( dst ) >= maxDecodedSize {
d . bufs . Put ( bufs )
br . close ( )
return nil , ErrMaxDecodedSizeExceeded
}
@ -688,6 +721,7 @@ func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
bitsLeft -= int8 ( nBits )
dst = append ( dst , uint8 ( v . entry >> 8 ) )
}
d . bufs . Put ( bufs )
return dst , br . close ( )
}
@ -707,6 +741,7 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
}
var br [ 4 ] bitReaderShifted
// Decode "jump table"
start := 6
for i := 0 ; i < 3 ; i ++ {
length := int ( src [ i * 2 ] ) | ( int ( src [ i * 2 + 1 ] ) << 8 )
@ -735,12 +770,12 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
single := d . dt . single [ : tlSize ]
// Use temp table to avoid bound checks/append penalty.
var buf [ 256 ] byte
buf := d . buffer ( )
var off uint8
var decoded int
// Decode 2 values from each decoder/loop.
const bufoff = 256 / 4
const bufoff = 256
for {
if br [ 0 ] . off < 4 || br [ 1 ] . off < 4 || br [ 2 ] . off < 4 || br [ 3 ] . off < 4 {
break
@ -758,8 +793,8 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
v2 := single [ val2 & tlMask ]
br [ stream ] . advance ( uint8 ( v . entry ) )
br [ stream2 ] . advance ( uint8 ( v2 . entry ) )
buf [ off+ bufoff * stream] = uint8 ( v . entry >> 8 )
buf [ off+ bufoff * stream2] = uint8 ( v2 . entry >> 8 )
buf [ stream] [ off ] = uint8 ( v . entry >> 8 )
buf [ stream2] [ off ] = uint8 ( v2 . entry >> 8 )
val = br [ stream ] . peekBitsFast ( d . actualTableLog )
val2 = br [ stream2 ] . peekBitsFast ( d . actualTableLog )
@ -767,8 +802,8 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
v2 = single [ val2 & tlMask ]
br [ stream ] . advance ( uint8 ( v . entry ) )
br [ stream2 ] . advance ( uint8 ( v2 . entry ) )
buf [ off+ bufoff * stream+ 1 ] = uint8 ( v . entry >> 8 )
buf [ off+ bufoff * stream2+ 1 ] = uint8 ( v2 . entry >> 8 )
buf [ stream] [ off + 1 ] = uint8 ( v . entry >> 8 )
buf [ stream2] [ off + 1 ] = uint8 ( v2 . entry >> 8 )
}
{
@ -783,8 +818,8 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
v2 := single [ val2 & tlMask ]
br [ stream ] . advance ( uint8 ( v . entry ) )
br [ stream2 ] . advance ( uint8 ( v2 . entry ) )
buf [ off+ bufoff * stream] = uint8 ( v . entry >> 8 )
buf [ off+ bufoff * stream2] = uint8 ( v2 . entry >> 8 )
buf [ stream] [ off ] = uint8 ( v . entry >> 8 )
buf [ stream2] [ off ] = uint8 ( v2 . entry >> 8 )
val = br [ stream ] . peekBitsFast ( d . actualTableLog )
val2 = br [ stream2 ] . peekBitsFast ( d . actualTableLog )
@ -792,25 +827,26 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
v2 = single [ val2 & tlMask ]
br [ stream ] . advance ( uint8 ( v . entry ) )
br [ stream2 ] . advance ( uint8 ( v2 . entry ) )
buf [ off+ bufoff * stream+ 1 ] = uint8 ( v . entry >> 8 )
buf [ off+ bufoff * stream2+ 1 ] = uint8 ( v2 . entry >> 8 )
buf [ stream] [ off + 1 ] = uint8 ( v . entry >> 8 )
buf [ stream2] [ off + 1 ] = uint8 ( v2 . entry >> 8 )
}
off += 2
if off == bufoff {
if off == 0 {
if bufoff > dstEvery {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 1" )
}
copy ( out , buf [ : bufoff ] )
copy ( out [ dstEvery : ] , buf [ bufoff : bufoff * 2 ] )
copy ( out [ dstEvery * 2 : ] , buf [ bufoff * 2 : bufoff * 3 ] )
copy ( out [ dstEvery * 3 : ] , buf [ bufoff * 3 : bufoff * 4 ] )
off = 0
copy ( out , buf [ 0 ] [ : ] )
copy ( out [ dstEvery : ] , buf [ 1 ] [ : ] )
copy ( out [ dstEvery * 2 : ] , buf [ 2 ] [ : ] )
copy ( out [ dstEvery * 3 : ] , buf [ 3 ] [ : ] )
out = out [ bufoff : ]
decoded += 256
decoded += bufoff * 4
// There must at least be 3 buffers left.
if len ( out ) < dstEvery * 3 {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 2" )
}
}
@ -818,41 +854,31 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
if off > 0 {
ioff := int ( off )
if len ( out ) < dstEvery * 3 + ioff {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 3" )
}
copy ( out , buf [ : off ] )
copy ( out [ dstEvery : dstEvery + ioff ] , buf [ bufoff : bufoff * 2 ] )
copy ( out [ dstEvery * 2 : dstEvery * 2 + ioff ] , buf [ bufoff * 2 : bufoff * 3 ] )
copy ( out [ dstEvery * 3 : dstEvery * 3 + ioff ] , buf [ bufoff * 3 : bufoff * 4 ] )
copy ( out , buf [ 0 ] [ : off ] )
copy ( out [ dstEvery : ] , buf [ 1 ] [ : off ] )
copy ( out [ dstEvery * 2 : ] , buf [ 2 ] [ : off ] )
copy ( out [ dstEvery * 3 : ] , buf [ 3 ] [ : off ] )
decoded += int ( off ) * 4
out = out [ off : ]
}
// Decode remaining.
remainBytes := dstEvery - ( decoded / 4 )
for i := range br {
offset := dstEvery * i
endsAt := offset + remainBytes
if endsAt > len ( out ) {
endsAt = len ( out )
}
br := & br [ i ]
bitsLeft := br . off * 8 + uint ( 64 - br . bitsRead )
bitsLeft := br . remaining ( )
for bitsLeft > 0 {
br . fill ( )
if false && br . bitsRead >= 32 {
if br . off >= 4 {
v := br . in [ br . off - 4 : ]
v = v [ : 4 ]
low := ( uint32 ( v [ 0 ] ) ) | ( uint32 ( v [ 1 ] ) << 8 ) | ( uint32 ( v [ 2 ] ) << 16 ) | ( uint32 ( v [ 3 ] ) << 24 )
br . value = ( br . value << 32 ) | uint64 ( low )
br . bitsRead -= 32
br . off -= 4
} else {
for br . off > 0 {
br . value = ( br . value << 8 ) | uint64 ( br . in [ br . off - 1 ] )
br . bitsRead -= 8
br . off --
}
}
}
// end inline...
if offset >= len ( out ) {
if offset >= endsAt {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 4" )
}
@ -865,12 +891,17 @@ func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) {
out [ offset ] = uint8 ( v >> 8 )
offset ++
}
if offset != endsAt {
d . bufs . Put ( buf )
return nil , fmt . Errorf ( "corruption detected: short output block %d, end %d != %d" , i , offset , endsAt )
}
decoded += offset - dstEvery * i
err = br . close ( )
if err != nil {
return nil , err
}
}
d . bufs . Put ( buf )
if dstSize != decoded {
return nil , errors . New ( "corruption detected: short output block" )
}
@ -916,12 +947,12 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
single := d . dt . single [ : tlSize ]
// Use temp table to avoid bound checks/append penalty.
var buf [ 256 ] byte
buf := d . buffer ( )
var off uint8
var decoded int
// Decode 4 values from each decoder/loop.
const bufoff = 256 / 4
const bufoff = 256
for {
if br [ 0 ] . off < 4 || br [ 1 ] . off < 4 || br [ 2 ] . off < 4 || br [ 3 ] . off < 4 {
break
@ -942,8 +973,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream] = uint8 ( v >> 8 )
buf [ off+ bufoff * stream2] = uint8 ( v2 >> 8 )
buf [ stream] [ off ] = uint8 ( v >> 8 )
buf [ stream2] [ off ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
@ -951,8 +982,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream+ 1 ] = uint8 ( v >> 8 )
buf [ off+ bufoff * stream2+ 1 ] = uint8 ( v2 >> 8 )
buf [ stream] [ off + 1 ] = uint8 ( v >> 8 )
buf [ stream2] [ off + 1 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
@ -960,8 +991,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream+ 2 ] = uint8 ( v >> 8 )
buf [ off+ bufoff * stream2+ 2 ] = uint8 ( v2 >> 8 )
buf [ stream] [ off + 2 ] = uint8 ( v >> 8 )
buf [ stream2] [ off + 2 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
@ -969,8 +1000,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream2 + 3 ] = uint8 ( v 2 >> 8 )
buf [ off+ bufoff * stream + 3 ] = uint8 ( v >> 8 )
buf [ stream] [ off + 3 ] = uint8 ( v >> 8 )
buf [ stream2] [ off + 3 ] = uint8 ( v 2 >> 8 )
}
{
@ -987,8 +1018,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream] = uint8 ( v >> 8 )
buf [ off+ bufoff * stream2] = uint8 ( v2 >> 8 )
buf [ stream] [ off ] = uint8 ( v >> 8 )
buf [ stream2] [ off ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
@ -996,8 +1027,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream+ 1 ] = uint8 ( v >> 8 )
buf [ off+ bufoff * stream2+ 1 ] = uint8 ( v2 >> 8 )
buf [ stream] [ off + 1 ] = uint8 ( v >> 8 )
buf [ stream2] [ off + 1 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
@ -1005,8 +1036,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream+ 2 ] = uint8 ( v >> 8 )
buf [ off+ bufoff * stream2+ 2 ] = uint8 ( v2 >> 8 )
buf [ stream] [ off + 2 ] = uint8 ( v >> 8 )
buf [ stream2] [ off + 2 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
@ -1014,25 +1045,26 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ off+ bufoff * stream2 + 3 ] = uint8 ( v 2 >> 8 )
buf [ off+ bufoff * stream + 3 ] = uint8 ( v >> 8 )
buf [ stream] [ off + 3 ] = uint8 ( v >> 8 )
buf [ stream2] [ off + 3 ] = uint8 ( v 2 >> 8 )
}
off += 4
if off == bufoff {
if off == 0 {
if bufoff > dstEvery {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 1" )
}
copy ( out , buf [ : bufoff ] )
copy ( out [ dstEvery : ] , buf [ bufoff : bufoff * 2 ] )
copy ( out [ dstEvery * 2 : ] , buf [ bufoff * 2 : bufoff * 3 ] )
copy ( out [ dstEvery * 3 : ] , buf [ bufoff * 3 : bufoff * 4 ] )
off = 0
copy ( out , buf [ 0 ] [ : ] )
copy ( out [ dstEvery : ] , buf [ 1 ] [ : ] )
copy ( out [ dstEvery * 2 : ] , buf [ 2 ] [ : ] )
copy ( out [ dstEvery * 3 : ] , buf [ 3 ] [ : ] )
out = out [ bufoff : ]
decoded += 256
decoded += bufoff * 4
// There must at least be 3 buffers left.
if len ( out ) < dstEvery * 3 {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 2" )
}
}
@ -1040,23 +1072,31 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
if off > 0 {
ioff := int ( off )
if len ( out ) < dstEvery * 3 + ioff {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 3" )
}
copy ( out , buf [ : off ] )
copy ( out [ dstEvery : dstEvery + ioff ] , buf [ bufoff : bufoff * 2 ] )
copy ( out [ dstEvery * 2 : dstEvery * 2 + ioff ] , buf [ bufoff * 2 : bufoff * 3 ] )
copy ( out [ dstEvery * 3 : dstEvery * 3 + ioff ] , buf [ bufoff * 3 : bufoff * 4 ] )
copy ( out , buf [ 0 ] [ : off ] )
copy ( out [ dstEvery : ] , buf [ 1 ] [ : off ] )
copy ( out [ dstEvery * 2 : ] , buf [ 2 ] [ : off ] )
copy ( out [ dstEvery * 3 : ] , buf [ 3 ] [ : off ] )
decoded += int ( off ) * 4
out = out [ off : ]
}
// Decode remaining.
// Decode remaining.
remainBytes := dstEvery - ( decoded / 4 )
for i := range br {
offset := dstEvery * i
endsAt := offset + remainBytes
if endsAt > len ( out ) {
endsAt = len ( out )
}
br := & br [ i ]
bitsLeft := int ( br . off * 8 ) + int ( 64 - br . bitsRead )
bitsLeft := br . remaining ( )
for bitsLeft > 0 {
if br . finished ( ) {
d . bufs . Put ( buf )
return nil , io . ErrUnexpectedEOF
}
if br . bitsRead >= 56 {
@ -1076,7 +1116,8 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
}
}
// end inline...
if offset >= len ( out ) {
if offset >= endsAt {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 4" )
}
@ -1084,16 +1125,22 @@ func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
v := single [ uint8 ( br . value >> shift ) ] . entry
nBits := uint8 ( v )
br . advance ( nBits )
bitsLeft -= int( nBits )
bitsLeft -= u int( nBits )
out [ offset ] = uint8 ( v >> 8 )
offset ++
}
if offset != endsAt {
d . bufs . Put ( buf )
return nil , fmt . Errorf ( "corruption detected: short output block %d, end %d != %d" , i , offset , endsAt )
}
decoded += offset - dstEvery * i
err = br . close ( )
if err != nil {
d . bufs . Put ( buf )
return nil , err
}
}
d . bufs . Put ( buf )
if dstSize != decoded {
return nil , errors . New ( "corruption detected: short output block" )
}
@ -1135,12 +1182,12 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
single := d . dt . single [ : tlSize ]
// Use temp table to avoid bound checks/append penalty.
var buf [ 256 ] byte
buf := d . buffer ( )
var off uint8
var decoded int
// Decode 4 values from each decoder/loop.
const bufoff = 256 / 4
const bufoff = 256
for {
if br [ 0 ] . off < 4 || br [ 1 ] . off < 4 || br [ 2 ] . off < 4 || br [ 3 ] . off < 4 {
break
@ -1150,104 +1197,109 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
// Interleave 2 decodes.
const stream = 0
const stream2 = 1
br [ stream ] . fillFast ( )
br [ stream2 ] . fillFast ( )
br1 := & br [ stream ]
br2 := & br [ stream2 ]
br1 . fillFast ( )
br2 . fillFast ( )
v := single [ uint8 ( br1 . value >> shift ) ] . entry
v2 := single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off + 1 ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off + 1 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off + 2 ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off + 2 ] = uint8 ( v2 >> 8 )
v := single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 := single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 = single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream + 1 ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 + 1 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 = single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream + 2 ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 + 2 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 = single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream + 3 ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 + 3 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off + 3 ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off + 3 ] = uint8 ( v2 >> 8 )
}
{
const stream = 2
const stream2 = 3
br [ stream ] . fillFast ( )
br [ stream2 ] . fillFast ( )
br1 := & br [ stream ]
br2 := & br [ stream2 ]
br1 . fillFast ( )
br2 . fillFast ( )
v := single [ uint8 ( br1 . value >> shift ) ] . entry
v2 := single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off + 1 ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off + 1 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off + 2 ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off + 2 ] = uint8 ( v2 >> 8 )
v := single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 := single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 = single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream + 1 ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 + 1 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 = single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream + 2 ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 + 2 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br [ stream ] . value >> shift ) ] . entry
v2 = single [ uint8 ( br [ stream2 ] . value >> shift ) ] . entry
br [ stream ] . bitsRead += uint8 ( v )
br [ stream ] . value <<= v & 63
br [ stream2 ] . bitsRead += uint8 ( v2 )
br [ stream2 ] . value <<= v2 & 63
buf [ off + bufoff * stream + 3 ] = uint8 ( v >> 8 )
buf [ off + bufoff * stream2 + 3 ] = uint8 ( v2 >> 8 )
v = single [ uint8 ( br1 . value >> shift ) ] . entry
v2 = single [ uint8 ( br2 . value >> shift ) ] . entry
br1 . bitsRead += uint8 ( v )
br1 . value <<= v & 63
br2 . bitsRead += uint8 ( v2 )
br2 . value <<= v2 & 63
buf [ stream ] [ off + 3 ] = uint8 ( v >> 8 )
buf [ stream2 ] [ off + 3 ] = uint8 ( v2 >> 8 )
}
off += 4
if off == bufoff {
if off == 0 {
if bufoff > dstEvery {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 1" )
}
copy ( out , buf [ : bufoff ] )
copy ( out [ dstEvery : ] , buf [ bufoff : bufoff * 2 ] )
copy ( out [ dstEvery * 2 : ] , buf [ bufoff * 2 : bufoff * 3 ] )
copy ( out [ dstEvery * 3 : ] , buf [ bufoff * 3 : bufoff * 4 ] )
off = 0
copy ( out , buf [ 0 ] [ : ] )
copy ( out [ dstEvery : ] , buf [ 1 ] [ : ] )
copy ( out [ dstEvery * 2 : ] , buf [ 2 ] [ : ] )
copy ( out [ dstEvery * 3 : ] , buf [ 3 ] [ : ] )
out = out [ bufoff : ]
decoded += 256
decoded += bufoff * 4
// There must at least be 3 buffers left.
if len ( out ) < dstEvery * 3 {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 2" )
}
}
@ -1257,21 +1309,27 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
if len ( out ) < dstEvery * 3 + ioff {
return nil , errors . New ( "corruption detected: stream overrun 3" )
}
copy ( out , buf [ : off ] )
copy ( out [ dstEvery : dstEvery + ioff ] , buf [ bufoff : bufoff * 2 ] )
copy ( out [ dstEvery * 2 : dstEvery * 2 + ioff ] , buf [ bufoff * 2 : bufoff * 3 ] )
copy ( out [ dstEvery * 3 : dstEvery * 3 + ioff ] , buf [ bufoff * 3 : bufoff * 4 ] )
copy ( out , buf [ 0 ] [ : off ] )
copy ( out [ dstEvery : ] , buf [ 1 ] [ : off ] )
copy ( out [ dstEvery * 2 : ] , buf [ 2 ] [ : off ] )
copy ( out [ dstEvery * 3 : ] , buf [ 3 ] [ : off ] )
decoded += int ( off ) * 4
out = out [ off : ]
}
// Decode remaining.
remainBytes := dstEvery - ( decoded / 4 )
for i := range br {
offset := dstEvery * i
endsAt := offset + remainBytes
if endsAt > len ( out ) {
endsAt = len ( out )
}
br := & br [ i ]
bitsLeft := int ( br . off * 8 ) + int ( 64 - br . bitsRead )
bitsLeft := br . remaining ( )
for bitsLeft > 0 {
if br . finished ( ) {
d . bufs . Put ( buf )
return nil , io . ErrUnexpectedEOF
}
if br . bitsRead >= 56 {
@ -1291,7 +1349,8 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
}
}
// end inline...
if offset >= len ( out ) {
if offset >= endsAt {
d . bufs . Put ( buf )
return nil , errors . New ( "corruption detected: stream overrun 4" )
}
@ -1299,16 +1358,23 @@ func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
v := single [ br . peekByteFast ( ) ] . entry
nBits := uint8 ( v )
br . advance ( nBits )
bitsLeft -= int( nBits )
bitsLeft -= u int( nBits )
out [ offset ] = uint8 ( v >> 8 )
offset ++
}
if offset != endsAt {
d . bufs . Put ( buf )
return nil , fmt . Errorf ( "corruption detected: short output block %d, end %d != %d" , i , offset , endsAt )
}
decoded += offset - dstEvery * i
err = br . close ( )
if err != nil {
d . bufs . Put ( buf )
return nil , err
}
}
d . bufs . Put ( buf )
if dstSize != decoded {
return nil , errors . New ( "corruption detected: short output block" )
}