package flate
import "fmt"
type fastEncL3 struct {
fastGen
table [1 << 16 ]tableEntryPrev
}
func (e *fastEncL3 ) Encode (dst *tokens , src []byte ) {
const (
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
tableBits = 16
tableSize = 1 << tableBits
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 ] = tableEntryPrev {}
}
e .cur = maxMatchOffset
break
}
minOff := e .cur + int32 (len (e .hist )) - maxMatchOffset
for i := range e .table [:] {
v := e .table [i ]
if v .Cur .offset <= minOff {
v .Cur .offset = 0
} else {
v .Cur .offset = v .Cur .offset - e .cur + maxMatchOffset
}
if v .Prev .offset <= minOff {
v .Prev .offset = 0
} else {
v .Prev .offset = v .Prev .offset - e .cur + maxMatchOffset
}
e .table [i ] = 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 = 7
nextS := s
var candidate tableEntry
for {
nextHash := hashLen (cv , tableBits , hashBytes )
s = nextS
nextS = s + 1 + (s -nextEmit )>>skipLog
if nextS > sLimit {
goto emitRemainder
}
candidates := e .table [nextHash ]
now := load6432 (src , nextS )
minOffset := e .cur + s - (maxMatchOffset - 4 )
e .table [nextHash ] = tableEntryPrev {Prev : candidates .Cur , Cur : tableEntry {offset : s + e .cur }}
candidate = candidates .Cur
if candidate .offset < minOffset {
cv = now
continue
}
if uint32 (cv ) == load3232 (src , candidate .offset -e .cur ) {
if candidates .Prev .offset < minOffset || uint32 (cv ) != load3232 (src , candidates .Prev .offset -e .cur ) {
break
}
offset := s - (candidate .offset - e .cur )
o2 := s - (candidates .Prev .offset - e .cur )
l1 , l2 := matchLen (src [s +4 :], src [s -offset +4 :]), matchLen (src [s +4 :], src [s -o2 +4 :])
if l2 > l1 {
candidate = candidates .Prev
}
break
} else {
candidate = candidates .Prev
if candidate .offset > minOffset && uint32 (cv ) == load3232 (src , candidate .offset -e .cur ) {
break
}
}
cv = now
}
for {
t := candidate .offset - e .cur
l := e .matchlenLong (s +4 , t +4 , src ) + 4
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 ++
}
}
}
dst .AddMatchLong (l , uint32 (s -t -baseMatchOffset ))
s += l
nextEmit = s
if nextS >= s {
s = nextS + 1
}
if s >= sLimit {
t += l
if int (t +8 ) < len (src ) && t > 0 {
cv = load6432 (src , t )
nextHash := hashLen (cv , tableBits , hashBytes )
e .table [nextHash ] = tableEntryPrev {
Prev : e .table [nextHash ].Cur ,
Cur : tableEntry {offset : e .cur + t },
}
}
goto emitRemainder
}
for i := s - l + 2 ; i < s -5 ; i += 6 {
nextHash := hashLen (load6432 (src , i ), tableBits , hashBytes )
e .table [nextHash ] = tableEntryPrev {
Prev : e .table [nextHash ].Cur ,
Cur : tableEntry {offset : e .cur + i }}
}
x := load6432 (src , s -2 )
prevHash := hashLen (x , tableBits , hashBytes )
e .table [prevHash ] = tableEntryPrev {
Prev : e .table [prevHash ].Cur ,
Cur : tableEntry {offset : e .cur + s - 2 },
}
x >>= 8
prevHash = hashLen (x , tableBits , hashBytes )
e .table [prevHash ] = tableEntryPrev {
Prev : e .table [prevHash ].Cur ,
Cur : tableEntry {offset : e .cur + s - 1 },
}
x >>= 8
currHash := hashLen (x , tableBits , hashBytes )
candidates := e .table [currHash ]
cv = x
e .table [currHash ] = tableEntryPrev {
Prev : candidates .Cur ,
Cur : tableEntry {offset : s + e .cur },
}
candidate = candidates .Cur
minOffset := e .cur + s - (maxMatchOffset - 4 )
if candidate .offset > minOffset {
if uint32 (cv ) == load3232 (src , candidate .offset -e .cur ) {
continue
}
candidate = candidates .Prev
if candidate .offset > minOffset && uint32 (cv ) == load3232 (src , candidate .offset -e .cur ) {
continue
}
}
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 .