| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159 |
- package huff0
- import (
- "errors"
- "fmt"
- "io"
- "sync"
- "github.com/klauspost/compress/fse"
- )
- type dTable struct {
- single []dEntrySingle
- }
- // single-symbols decoding
- type dEntrySingle struct {
- entry uint16
- }
- // Uses special code for all tables that are < 8 bits.
- const use8BitTables = true
- // ReadTable will read a table from the input.
- // The size of the input may be larger than the table definition.
- // Any content remaining after the table definition will be returned.
- // If no Scratch is provided a new one is allocated.
- // The returned Scratch can be used for encoding or decoding input using this table.
- func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) {
- s, err = s.prepare(nil)
- if err != nil {
- return s, nil, err
- }
- if len(in) <= 1 {
- return s, nil, errors.New("input too small for table")
- }
- iSize := in[0]
- in = in[1:]
- if iSize >= 128 {
- // Uncompressed
- oSize := iSize - 127
- iSize = (oSize + 1) / 2
- if int(iSize) > len(in) {
- return s, nil, errors.New("input too small for table")
- }
- for n := uint8(0); n < oSize; n += 2 {
- v := in[n/2]
- s.huffWeight[n] = v >> 4
- s.huffWeight[n+1] = v & 15
- }
- s.symbolLen = uint16(oSize)
- in = in[iSize:]
- } else {
- if len(in) < int(iSize) {
- return s, nil, fmt.Errorf("input too small for table, want %d bytes, have %d", iSize, len(in))
- }
- // FSE compressed weights
- s.fse.DecompressLimit = 255
- hw := s.huffWeight[:]
- s.fse.Out = hw
- b, err := fse.Decompress(in[:iSize], s.fse)
- s.fse.Out = nil
- if err != nil {
- return s, nil, err
- }
- if len(b) > 255 {
- return s, nil, errors.New("corrupt input: output table too large")
- }
- s.symbolLen = uint16(len(b))
- in = in[iSize:]
- }
- // collect weight stats
- var rankStats [16]uint32
- weightTotal := uint32(0)
- for _, v := range s.huffWeight[:s.symbolLen] {
- if v > tableLogMax {
- return s, nil, errors.New("corrupt input: weight too large")
- }
- v2 := v & 15
- rankStats[v2]++
- // (1 << (v2-1)) is slower since the compiler cannot prove that v2 isn't 0.
- weightTotal += (1 << v2) >> 1
- }
- if weightTotal == 0 {
- return s, nil, errors.New("corrupt input: weights zero")
- }
- // get last non-null symbol weight (implied, total must be 2^n)
- {
- tableLog := highBit32(weightTotal) + 1
- if tableLog > tableLogMax {
- return s, nil, errors.New("corrupt input: tableLog too big")
- }
- s.actualTableLog = uint8(tableLog)
- // determine last weight
- {
- total := uint32(1) << tableLog
- rest := total - weightTotal
- verif := uint32(1) << highBit32(rest)
- lastWeight := highBit32(rest) + 1
- if verif != rest {
- // last value must be a clean power of 2
- return s, nil, errors.New("corrupt input: last value not power of two")
- }
- s.huffWeight[s.symbolLen] = uint8(lastWeight)
- s.symbolLen++
- rankStats[lastWeight]++
- }
- }
- if (rankStats[1] < 2) || (rankStats[1]&1 != 0) {
- // by construction : at least 2 elts of rank 1, must be even
- return s, nil, errors.New("corrupt input: min elt size, even check failed ")
- }
- // TODO: Choose between single/double symbol decoding
- // Calculate starting value for each rank
- {
- var nextRankStart uint32
- for n := uint8(1); n < s.actualTableLog+1; n++ {
- current := nextRankStart
- nextRankStart += rankStats[n] << (n - 1)
- rankStats[n] = current
- }
- }
- // fill DTable (always full size)
- tSize := 1 << tableLogMax
- if len(s.dt.single) != tSize {
- s.dt.single = make([]dEntrySingle, tSize)
- }
- cTable := s.prevTable
- if cap(cTable) < maxSymbolValue+1 {
- cTable = make([]cTableEntry, 0, maxSymbolValue+1)
- }
- cTable = cTable[:maxSymbolValue+1]
- s.prevTable = cTable[:s.symbolLen]
- s.prevTableLog = s.actualTableLog
- for n, w := range s.huffWeight[:s.symbolLen] {
- if w == 0 {
- cTable[n] = cTableEntry{
- val: 0,
- nBits: 0,
- }
- continue
- }
- length := (uint32(1) << w) >> 1
- d := dEntrySingle{
- entry: uint16(s.actualTableLog+1-w) | (uint16(n) << 8),
- }
- rank := &rankStats[w]
- cTable[n] = cTableEntry{
- val: uint16(*rank >> (w - 1)),
- nBits: uint8(d.entry),
- }
- single := s.dt.single[*rank : *rank+length]
- for i := range single {
- single[i] = d
- }
- *rank += length
- }
- return s, in, nil
- }
- // Decompress1X will decompress a 1X encoded stream.
- // The length of the supplied input must match the end of a block exactly.
- // Before this is called, the table must be initialized with ReadTable unless
- // the encoder re-used the table.
- // deprecated: Use the stateless Decoder() to get a concurrent version.
- func (s *Scratch) Decompress1X(in []byte) (out []byte, err error) {
- if cap(s.Out) < s.MaxDecodedSize {
- s.Out = make([]byte, s.MaxDecodedSize)
- }
- s.Out = s.Out[:0:s.MaxDecodedSize]
- s.Out, err = s.Decoder().Decompress1X(s.Out, in)
- return s.Out, err
- }
- // Decompress4X will decompress a 4X encoded stream.
- // Before this is called, the table must be initialized with ReadTable unless
- // the encoder re-used the table.
- // The length of the supplied input must match the end of a block exactly.
- // The destination size of the uncompressed data must be known and provided.
- // deprecated: Use the stateless Decoder() to get a concurrent version.
- func (s *Scratch) Decompress4X(in []byte, dstSize int) (out []byte, err error) {
- if dstSize > s.MaxDecodedSize {
- return nil, ErrMaxDecodedSizeExceeded
- }
- if cap(s.Out) < dstSize {
- s.Out = make([]byte, s.MaxDecodedSize)
- }
- s.Out = s.Out[:0:dstSize]
- s.Out, err = s.Decoder().Decompress4X(s.Out, in)
- return s.Out, err
- }
- // Decoder will return a stateless decoder that can be used by multiple
- // decompressors concurrently.
- // Before this is called, the table must be initialized with ReadTable.
- // The Decoder is still linked to the scratch buffer so that cannot be reused.
- // However, it is safe to discard the scratch.
- func (s *Scratch) Decoder() *Decoder {
- return &Decoder{
- dt: s.dt,
- actualTableLog: s.actualTableLog,
- bufs: &s.decPool,
- }
- }
- // Decoder provides stateless decoding.
- 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{}
- }
- // decompress1X8Bit will decompress a 1X encoded stream with tablelog <= 8.
- // The cap of the output buffer will be the maximum decompressed size.
- // The length of the supplied input must match the end of a block exactly.
- func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) {
- if d.actualTableLog == 8 {
- return d.decompress1X8BitExactly(dst, src)
- }
- var br bitReaderBytes
- err := br.init(src)
- if err != nil {
- return dst, err
- }
- maxDecodedSize := cap(dst)
- dst = dst[:0]
- // Avoid bounds check by always having full sized table.
- dt := d.dt.single[:256]
- // Use temp table to avoid bound checks/append penalty.
- bufs := d.buffer()
- buf := &bufs[0]
- var off uint8
- switch d.actualTableLog {
- case 8:
- const shift = 8 - 8
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- br.close()
- d.bufs.Put(bufs)
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 7:
- const shift = 8 - 7
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- br.close()
- d.bufs.Put(bufs)
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 6:
- const shift = 8 - 6
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 5:
- const shift = 8 - 5
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 4:
- const shift = 8 - 4
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 3:
- const shift = 8 - 3
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 2:
- const shift = 8 - 2
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- case 1:
- const shift = 8 - 1
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>(56+shift))]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- 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
- }
- dst = append(dst, buf[:off]...)
- // br < 4, so uint8 is fine
- bitsLeft := int8(uint8(br.off)*8 + (64 - br.bitsRead))
- shift := (8 - d.actualTableLog) & 7
- for bitsLeft > 0 {
- if br.bitsRead >= 64-8 {
- for br.off > 0 {
- br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8)
- br.bitsRead -= 8
- br.off--
- }
- }
- if len(dst) >= maxDecodedSize {
- br.close()
- d.bufs.Put(bufs)
- return nil, ErrMaxDecodedSizeExceeded
- }
- v := dt[br.peekByteFast()>>shift]
- nBits := uint8(v.entry)
- br.advance(nBits)
- bitsLeft -= int8(nBits)
- dst = append(dst, uint8(v.entry>>8))
- }
- d.bufs.Put(bufs)
- return dst, br.close()
- }
- // decompress1X8Bit will decompress a 1X encoded stream with tablelog <= 8.
- // The cap of the output buffer will be the maximum decompressed size.
- // The length of the supplied input must match the end of a block exactly.
- func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) {
- var br bitReaderBytes
- err := br.init(src)
- if err != nil {
- return dst, err
- }
- maxDecodedSize := cap(dst)
- dst = dst[:0]
- // Avoid bounds check by always having full sized table.
- dt := d.dt.single[:256]
- // Use temp table to avoid bound checks/append penalty.
- bufs := d.buffer()
- buf := &bufs[0]
- var off uint8
- const shift = 56
- //fmt.Printf("mask: %b, tl:%d\n", mask, d.actualTableLog)
- for br.off >= 4 {
- br.fillFast()
- v := dt[uint8(br.value>>shift)]
- br.advance(uint8(v.entry))
- buf[off+0] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>shift)]
- br.advance(uint8(v.entry))
- buf[off+1] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>shift)]
- br.advance(uint8(v.entry))
- buf[off+2] = uint8(v.entry >> 8)
- v = dt[uint8(br.value>>shift)]
- br.advance(uint8(v.entry))
- buf[off+3] = uint8(v.entry >> 8)
- off += 4
- if off == 0 {
- if len(dst)+256 > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:]...)
- }
- }
- if len(dst)+int(off) > maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- dst = append(dst, buf[:off]...)
- // br < 4, so uint8 is fine
- bitsLeft := int8(uint8(br.off)*8 + (64 - br.bitsRead))
- for bitsLeft > 0 {
- if br.bitsRead >= 64-8 {
- for br.off > 0 {
- br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8)
- br.bitsRead -= 8
- br.off--
- }
- }
- if len(dst) >= maxDecodedSize {
- d.bufs.Put(bufs)
- br.close()
- return nil, ErrMaxDecodedSizeExceeded
- }
- v := dt[br.peekByteFast()]
- nBits := uint8(v.entry)
- br.advance(nBits)
- bitsLeft -= int8(nBits)
- dst = append(dst, uint8(v.entry>>8))
- }
- d.bufs.Put(bufs)
- return dst, br.close()
- }
- // Decompress4X will decompress a 4X encoded stream.
- // The length of the supplied input must match the end of a block exactly.
- // The *capacity* of the dst slice must match the destination size of
- // the uncompressed data exactly.
- func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) {
- if d.actualTableLog == 8 {
- return d.decompress4X8bitExactly(dst, src)
- }
- var br [4]bitReaderBytes
- start := 6
- for i := 0; i < 3; i++ {
- length := int(src[i*2]) | (int(src[i*2+1]) << 8)
- if start+length >= len(src) {
- return nil, errors.New("truncated input (or invalid offset)")
- }
- err := br[i].init(src[start : start+length])
- if err != nil {
- return nil, err
- }
- start += length
- }
- err := br[3].init(src[start:])
- if err != nil {
- return nil, err
- }
- // destination, offset to match first output
- dstSize := cap(dst)
- dst = dst[:dstSize]
- out := dst
- dstEvery := (dstSize + 3) / 4
- shift := (56 + (8 - d.actualTableLog)) & 63
- const tlSize = 1 << 8
- single := d.dt.single[:tlSize]
- // Use temp table to avoid bound checks/append penalty.
- buf := d.buffer()
- var off uint8
- var decoded int
- // Decode 4 values from each decoder/loop.
- const bufoff = 256
- for {
- if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 {
- break
- }
- {
- // Interleave 2 decodes.
- const stream = 0
- const stream2 = 1
- 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(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
- 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(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 == 0 {
- if bufoff > dstEvery {
- d.bufs.Put(buf)
- return nil, errors.New("corruption detected: stream overrun 1")
- }
- 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 += 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")
- }
- }
- }
- 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[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 := br.remaining()
- for bitsLeft > 0 {
- if br.finished() {
- d.bufs.Put(buf)
- return nil, io.ErrUnexpectedEOF
- }
- if br.bitsRead >= 56 {
- 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 |= uint64(low) << (br.bitsRead - 32)
- br.bitsRead -= 32
- br.off -= 4
- } else {
- for br.off > 0 {
- br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8)
- br.bitsRead -= 8
- br.off--
- }
- }
- }
- // end inline...
- if offset >= endsAt {
- d.bufs.Put(buf)
- return nil, errors.New("corruption detected: stream overrun 4")
- }
- // Read value and increment offset.
- v := single[uint8(br.value>>shift)].entry
- nBits := uint8(v)
- br.advance(nBits)
- bitsLeft -= uint(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")
- }
- return dst, nil
- }
- // Decompress4X will decompress a 4X encoded stream.
- // The length of the supplied input must match the end of a block exactly.
- // The *capacity* of the dst slice must match the destination size of
- // the uncompressed data exactly.
- func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) {
- var br [4]bitReaderBytes
- start := 6
- for i := 0; i < 3; i++ {
- length := int(src[i*2]) | (int(src[i*2+1]) << 8)
- if start+length >= len(src) {
- return nil, errors.New("truncated input (or invalid offset)")
- }
- err := br[i].init(src[start : start+length])
- if err != nil {
- return nil, err
- }
- start += length
- }
- err := br[3].init(src[start:])
- if err != nil {
- return nil, err
- }
- // destination, offset to match first output
- dstSize := cap(dst)
- dst = dst[:dstSize]
- out := dst
- dstEvery := (dstSize + 3) / 4
- const shift = 56
- const tlSize = 1 << 8
- single := d.dt.single[:tlSize]
- // Use temp table to avoid bound checks/append penalty.
- buf := d.buffer()
- var off uint8
- var decoded int
- // Decode 4 values from each decoder/loop.
- const bufoff = 256
- for {
- if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 {
- break
- }
- {
- // Interleave 2 decodes.
- const stream = 0
- const stream2 = 1
- 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(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
- 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(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 == 0 {
- if bufoff > dstEvery {
- d.bufs.Put(buf)
- return nil, errors.New("corruption detected: stream overrun 1")
- }
- 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 += 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")
- }
- }
- }
- if off > 0 {
- ioff := int(off)
- if len(out) < dstEvery*3+ioff {
- return nil, errors.New("corruption detected: stream overrun 3")
- }
- 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.remaining()
- for bitsLeft > 0 {
- if br.finished() {
- d.bufs.Put(buf)
- return nil, io.ErrUnexpectedEOF
- }
- if br.bitsRead >= 56 {
- 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 |= uint64(low) << (br.bitsRead - 32)
- br.bitsRead -= 32
- br.off -= 4
- } else {
- for br.off > 0 {
- br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8)
- br.bitsRead -= 8
- br.off--
- }
- }
- }
- // end inline...
- if offset >= endsAt {
- d.bufs.Put(buf)
- return nil, errors.New("corruption detected: stream overrun 4")
- }
- // Read value and increment offset.
- v := single[br.peekByteFast()].entry
- nBits := uint8(v)
- br.advance(nBits)
- bitsLeft -= uint(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")
- }
- return dst, nil
- }
- // matches will compare a decoding table to a coding table.
- // Errors are written to the writer.
- // Nothing will be written if table is ok.
- func (s *Scratch) matches(ct cTable, w io.Writer) {
- if s == nil || len(s.dt.single) == 0 {
- return
- }
- dt := s.dt.single[:1<<s.actualTableLog]
- tablelog := s.actualTableLog
- ok := 0
- broken := 0
- for sym, enc := range ct {
- errs := 0
- broken++
- if enc.nBits == 0 {
- for _, dec := range dt {
- if uint8(dec.entry>>8) == byte(sym) {
- fmt.Fprintf(w, "symbol %x has decoder, but no encoder\n", sym)
- errs++
- break
- }
- }
- if errs == 0 {
- broken--
- }
- continue
- }
- // Unused bits in input
- ub := tablelog - enc.nBits
- top := enc.val << ub
- // decoder looks at top bits.
- dec := dt[top]
- if uint8(dec.entry) != enc.nBits {
- fmt.Fprintf(w, "symbol 0x%x bit size mismatch (enc: %d, dec:%d).\n", sym, enc.nBits, uint8(dec.entry))
- errs++
- }
- if uint8(dec.entry>>8) != uint8(sym) {
- fmt.Fprintf(w, "symbol 0x%x decoder output mismatch (enc: %d, dec:%d).\n", sym, sym, uint8(dec.entry>>8))
- errs++
- }
- if errs > 0 {
- fmt.Fprintf(w, "%d errros in base, stopping\n", errs)
- continue
- }
- // Ensure that all combinations are covered.
- for i := uint16(0); i < (1 << ub); i++ {
- vval := top | i
- dec := dt[vval]
- if uint8(dec.entry) != enc.nBits {
- fmt.Fprintf(w, "symbol 0x%x bit size mismatch (enc: %d, dec:%d).\n", vval, enc.nBits, uint8(dec.entry))
- errs++
- }
- if uint8(dec.entry>>8) != uint8(sym) {
- fmt.Fprintf(w, "symbol 0x%x decoder output mismatch (enc: %d, dec:%d).\n", vval, sym, uint8(dec.entry>>8))
- errs++
- }
- if errs > 20 {
- fmt.Fprintf(w, "%d errros, stopping\n", errs)
- break
- }
- }
- if errs == 0 {
- ok++
- broken--
- }
- }
- if broken > 0 {
- fmt.Fprintf(w, "%d broken, %d ok\n", broken, ok)
- }
- }
|