package flate
import (
"encoding/binary"
"fmt"
"math/bits"
)
type fastEncL1 struct {
fastGen
table [tableSize ]tableEntry
}
func (e *fastEncL1 ) Encode (dst *tokens , src []byte ) {
const (
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
hashBytes = 5
)
if debugDeflate && e .cur < 0 {
panic (fmt .Sprint ("e.cur < 0: " , e .cur ))
}
for e .cur >= bufferReset {
if len (e .hist ) == 0 {
for i := range e .table [:] {
e .table [i ] = tableEntry {}
}
e .cur = maxMatchOffset
break
}
minOff := e .cur + int32 (len (e .hist )) - maxMatchOffset
for i := range e .table [:] {
v := e .table [i ].offset
if v <= minOff {
v = 0
} else {
v = v - e .cur + maxMatchOffset
}
e .table [i ].offset = v
}
e .cur = maxMatchOffset
}
s := e .addBlock (src )
if len (src ) < minNonLiteralBlockSize {
dst .n = uint16 (len (src ))
return
}
src = e .hist
nextEmit := s
sLimit := int32 (len (src ) - inputMargin )
cv := load6432 (src , s )
for {
const skipLog = 5
const doEvery = 2
nextS := s
var candidate tableEntry
for {
nextHash := hashLen (cv , tableBits , hashBytes )
candidate = e .table [nextHash ]
nextS = s + doEvery + (s -nextEmit )>>skipLog
if nextS > sLimit {
goto emitRemainder
}
now := load6432 (src , nextS )
e .table [nextHash ] = tableEntry {offset : s + e .cur }
nextHash = hashLen (now , tableBits , hashBytes )
offset := s - (candidate .offset - e .cur )
if offset < maxMatchOffset && uint32 (cv ) == load3232 (src , candidate .offset -e .cur ) {
e .table [nextHash ] = tableEntry {offset : nextS + e .cur }
break
}
cv = now
s = nextS
nextS ++
candidate = e .table [nextHash ]
now >>= 8
e .table [nextHash ] = tableEntry {offset : s + e .cur }
offset = s - (candidate .offset - e .cur )
if offset < maxMatchOffset && uint32 (cv ) == load3232 (src , candidate .offset -e .cur ) {
e .table [nextHash ] = tableEntry {offset : nextS + e .cur }
break
}
cv = now
s = nextS
}
for {
t := candidate .offset - e .cur
var l = int32 (4 )
if false {
l = e .matchlenLong (s +4 , t +4 , src ) + 4
} else {
a := src [s +4 :]
b := src [t +4 :]
for len (a ) >= 8 {
if diff := binary .LittleEndian .Uint64 (a ) ^ binary .LittleEndian .Uint64 (b ); diff != 0 {
l += int32 (bits .TrailingZeros64 (diff ) >> 3 )
break
}
l += 8
a = a [8 :]
b = b [8 :]
}
if len (a ) < 8 {
b = b [:len (a )]
for i := range a {
if a [i ] != b [i ] {
break
}
l ++
}
}
}
for t > 0 && s > nextEmit && src [t -1 ] == src [s -1 ] {
s --
t --
l ++
}
if nextEmit < s {
if false {
emitLiteral (dst , src [nextEmit :s ])
} else {
for _ , v := range src [nextEmit :s ] {
dst .tokens [dst .n ] = token (v )
dst .litHist [v ]++
dst .n ++
}
}
}
if false {
dst .AddMatchLong (l , uint32 (s -t -baseMatchOffset ))
} else {
xoffset := uint32 (s - t - baseMatchOffset )
xlength := l
oc := offsetCode (xoffset )
xoffset |= oc << 16
for xlength > 0 {
xl := xlength
if xl > 258 {
if xl > 258 +baseMatchLength {
xl = 258
} else {
xl = 258 - baseMatchLength
}
}
xlength -= xl
xl -= baseMatchLength
dst .extraHist [lengthCodes1 [uint8 (xl )]]++
dst .offHist [oc ]++
dst .tokens [dst .n ] = token (matchType | uint32 (xl )<<lengthShift | xoffset )
dst .n ++
}
}
s += l
nextEmit = s
if nextS >= s {
s = nextS + 1
}
if s >= sLimit {
if int (s +l +8 ) < len (src ) {
cv := load6432 (src , s )
e .table [hashLen (cv , tableBits , hashBytes )] = tableEntry {offset : s + e .cur }
}
goto emitRemainder
}
x := load6432 (src , s -2 )
o := e .cur + s - 2
prevHash := hashLen (x , tableBits , hashBytes )
e .table [prevHash ] = tableEntry {offset : o }
x >>= 16
currHash := hashLen (x , tableBits , hashBytes )
candidate = e .table [currHash ]
e .table [currHash ] = tableEntry {offset : o + 2 }
offset := s - (candidate .offset - e .cur )
if offset > maxMatchOffset || uint32 (x ) != load3232 (src , candidate .offset -e .cur ) {
cv = x >> 8
s ++
break
}
}
}
emitRemainder :
if int (nextEmit ) < len (src ) {
if dst .n == 0 {
return
}
emitLiteral (dst , src [nextEmit :])
}
}
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 .