package flate
import "fmt"
type fastEncL5 struct {
fastGen
table [tableSize ]tableEntry
bTable [tableSize ]tableEntryPrev
}
func (e *fastEncL5 ) Encode (dst *tokens , src []byte ) {
const (
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
hashShortBytes = 4
)
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 {}
}
for i := range e .bTable [:] {
e .bTable [i ] = tableEntryPrev {}
}
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
}
for i := range e .bTable [:] {
v := e .bTable [i ]
if v .Cur .offset <= minOff {
v .Cur .offset = 0
v .Prev .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 .bTable [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 = 6
const doEvery = 1
nextS := s
var l int32
var t int32
for {
nextHashS := hashLen (cv , tableBits , hashShortBytes )
nextHashL := hash7 (cv , tableBits )
s = nextS
nextS = s + doEvery + (s -nextEmit )>>skipLog
if nextS > sLimit {
goto emitRemainder
}
sCandidate := e .table [nextHashS ]
lCandidate := e .bTable [nextHashL ]
next := load6432 (src , nextS )
entry := tableEntry {offset : s + e .cur }
e .table [nextHashS ] = entry
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = entry , eLong .Cur
nextHashS = hashLen (next , tableBits , hashShortBytes )
nextHashL = hash7 (next , tableBits )
t = lCandidate .Cur .offset - e .cur
if s -t < maxMatchOffset {
if uint32 (cv ) == load3232 (src , lCandidate .Cur .offset -e .cur ) {
e .table [nextHashS ] = tableEntry {offset : nextS + e .cur }
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : nextS + e .cur }, eLong .Cur
t2 := lCandidate .Prev .offset - e .cur
if s -t2 < maxMatchOffset && uint32 (cv ) == load3232 (src , lCandidate .Prev .offset -e .cur ) {
l = e .matchlen (s +4 , t +4 , src ) + 4
ml1 := e .matchlen (s +4 , t2 +4 , src ) + 4
if ml1 > l {
t = t2
l = ml1
break
}
}
break
}
t = lCandidate .Prev .offset - e .cur
if s -t < maxMatchOffset && uint32 (cv ) == load3232 (src , lCandidate .Prev .offset -e .cur ) {
e .table [nextHashS ] = tableEntry {offset : nextS + e .cur }
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : nextS + e .cur }, eLong .Cur
break
}
}
t = sCandidate .offset - e .cur
if s -t < maxMatchOffset && uint32 (cv ) == load3232 (src , sCandidate .offset -e .cur ) {
l = e .matchlen (s +4 , t +4 , src ) + 4
lCandidate = e .bTable [nextHashL ]
e .table [nextHashS ] = tableEntry {offset : nextS + e .cur }
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : nextS + e .cur }, eLong .Cur
t2 := lCandidate .Cur .offset - e .cur
if nextS -t2 < maxMatchOffset {
if load3232 (src , lCandidate .Cur .offset -e .cur ) == uint32 (next ) {
ml := e .matchlen (nextS +4 , t2 +4 , src ) + 4
if ml > l {
t = t2
s = nextS
l = ml
break
}
}
t2 = lCandidate .Prev .offset - e .cur
if nextS -t2 < maxMatchOffset && load3232 (src , lCandidate .Prev .offset -e .cur ) == uint32 (next ) {
ml := e .matchlen (nextS +4 , t2 +4 , src ) + 4
if ml > l {
t = t2
s = nextS
l = ml
break
}
}
}
break
}
cv = next
}
if l == 0 {
l = e .matchlenLong (s +4 , t +4 , src ) + 4
} else if l == maxMatchLength {
l += e .matchlenLong (s +l , t +l , src )
}
if sAt := s + l ; l < 30 && sAt < sLimit {
const skipBeginning = 2
eLong := e .bTable [hash7 (load6432 (src , sAt ), tableBits )].Cur .offset
t2 := eLong - e .cur - l + skipBeginning
s2 := s + skipBeginning
off := s2 - t2
if t2 >= 0 && off < maxMatchOffset && off > 0 {
if l2 := e .matchlenLong (s2 , t2 , src ); l2 > l {
t = t2
l = l2
s = s2
}
}
}
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 debugDeflate {
if t >= s {
panic (fmt .Sprintln ("s-t" , s , t ))
}
if (s - t ) > maxMatchOffset {
panic (fmt .Sprintln ("mmo" , s -t ))
}
if l < baseMatchLength {
panic ("bml" )
}
}
dst .AddMatchLong (l , uint32 (s -t -baseMatchOffset ))
s += l
nextEmit = s
if nextS >= s {
s = nextS + 1
}
if s >= sLimit {
goto emitRemainder
}
if true {
const hashEvery = 3
i := s - l + 1
if i < s -1 {
cv := load6432 (src , i )
t := tableEntry {offset : i + e .cur }
e .table [hashLen (cv , tableBits , hashShortBytes )] = t
eLong := &e .bTable [hash7 (cv , tableBits )]
eLong .Cur , eLong .Prev = t , eLong .Cur
cv >>= 8
t = tableEntry {offset : t .offset + 1 }
eLong = &e .bTable [hash7 (cv , tableBits )]
eLong .Cur , eLong .Prev = t , eLong .Cur
cv >>= 8
t = tableEntry {offset : t .offset + 1 }
e .table [hashLen (cv , tableBits , hashShortBytes )] = t
i += 4
for ; i < s -1 ; i += hashEvery {
cv := load6432 (src , i )
t := tableEntry {offset : i + e .cur }
t2 := tableEntry {offset : t .offset + 1 }
eLong := &e .bTable [hash7 (cv , tableBits )]
eLong .Cur , eLong .Prev = t , eLong .Cur
e .table [hashLen (cv >>8 , tableBits , hashShortBytes )] = t2
}
}
}
x := load6432 (src , s -1 )
o := e .cur + s - 1
prevHashS := hashLen (x , tableBits , hashShortBytes )
prevHashL := hash7 (x , tableBits )
e .table [prevHashS ] = tableEntry {offset : o }
eLong := &e .bTable [prevHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : o }, eLong .Cur
cv = x >> 8
}
emitRemainder :
if int (nextEmit ) < len (src ) {
if dst .n == 0 {
return
}
emitLiteral (dst , src [nextEmit :])
}
}
type fastEncL5Window struct {
hist []byte
cur int32
maxOffset int32
table [tableSize ]tableEntry
bTable [tableSize ]tableEntryPrev
}
func (e *fastEncL5Window ) Encode (dst *tokens , src []byte ) {
const (
inputMargin = 12 - 1
minNonLiteralBlockSize = 1 + 1 + inputMargin
hashShortBytes = 4
)
maxMatchOffset := e .maxOffset
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 {}
}
for i := range e .bTable [:] {
e .bTable [i ] = tableEntryPrev {}
}
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
}
for i := range e .bTable [:] {
v := e .bTable [i ]
if v .Cur .offset <= minOff {
v .Cur .offset = 0
v .Prev .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 .bTable [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 = 6
const doEvery = 1
nextS := s
var l int32
var t int32
for {
nextHashS := hashLen (cv , tableBits , hashShortBytes )
nextHashL := hash7 (cv , tableBits )
s = nextS
nextS = s + doEvery + (s -nextEmit )>>skipLog
if nextS > sLimit {
goto emitRemainder
}
sCandidate := e .table [nextHashS ]
lCandidate := e .bTable [nextHashL ]
next := load6432 (src , nextS )
entry := tableEntry {offset : s + e .cur }
e .table [nextHashS ] = entry
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = entry , eLong .Cur
nextHashS = hashLen (next , tableBits , hashShortBytes )
nextHashL = hash7 (next , tableBits )
t = lCandidate .Cur .offset - e .cur
if s -t < maxMatchOffset {
if uint32 (cv ) == load3232 (src , lCandidate .Cur .offset -e .cur ) {
e .table [nextHashS ] = tableEntry {offset : nextS + e .cur }
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : nextS + e .cur }, eLong .Cur
t2 := lCandidate .Prev .offset - e .cur
if s -t2 < maxMatchOffset && uint32 (cv ) == load3232 (src , lCandidate .Prev .offset -e .cur ) {
l = e .matchlen (s +4 , t +4 , src ) + 4
ml1 := e .matchlen (s +4 , t2 +4 , src ) + 4
if ml1 > l {
t = t2
l = ml1
break
}
}
break
}
t = lCandidate .Prev .offset - e .cur
if s -t < maxMatchOffset && uint32 (cv ) == load3232 (src , lCandidate .Prev .offset -e .cur ) {
e .table [nextHashS ] = tableEntry {offset : nextS + e .cur }
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : nextS + e .cur }, eLong .Cur
break
}
}
t = sCandidate .offset - e .cur
if s -t < maxMatchOffset && uint32 (cv ) == load3232 (src , sCandidate .offset -e .cur ) {
l = e .matchlen (s +4 , t +4 , src ) + 4
lCandidate = e .bTable [nextHashL ]
e .table [nextHashS ] = tableEntry {offset : nextS + e .cur }
eLong := &e .bTable [nextHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : nextS + e .cur }, eLong .Cur
t2 := lCandidate .Cur .offset - e .cur
if nextS -t2 < maxMatchOffset {
if load3232 (src , lCandidate .Cur .offset -e .cur ) == uint32 (next ) {
ml := e .matchlen (nextS +4 , t2 +4 , src ) + 4
if ml > l {
t = t2
s = nextS
l = ml
break
}
}
t2 = lCandidate .Prev .offset - e .cur
if nextS -t2 < maxMatchOffset && load3232 (src , lCandidate .Prev .offset -e .cur ) == uint32 (next ) {
ml := e .matchlen (nextS +4 , t2 +4 , src ) + 4
if ml > l {
t = t2
s = nextS
l = ml
break
}
}
}
break
}
cv = next
}
if l == 0 {
l = e .matchlenLong (s +4 , t +4 , src ) + 4
} else if l == maxMatchLength {
l += e .matchlenLong (s +l , t +l , src )
}
if sAt := s + l ; l < 30 && sAt < sLimit {
const skipBeginning = 2
eLong := e .bTable [hash7 (load6432 (src , sAt ), tableBits )].Cur .offset
t2 := eLong - e .cur - l + skipBeginning
s2 := s + skipBeginning
off := s2 - t2
if t2 >= 0 && off < maxMatchOffset && off > 0 {
if l2 := e .matchlenLong (s2 , t2 , src ); l2 > l {
t = t2
l = l2
s = s2
}
}
}
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 debugDeflate {
if t >= s {
panic (fmt .Sprintln ("s-t" , s , t ))
}
if (s - t ) > maxMatchOffset {
panic (fmt .Sprintln ("mmo" , s -t ))
}
if l < baseMatchLength {
panic ("bml" )
}
}
dst .AddMatchLong (l , uint32 (s -t -baseMatchOffset ))
s += l
nextEmit = s
if nextS >= s {
s = nextS + 1
}
if s >= sLimit {
goto emitRemainder
}
if true {
const hashEvery = 3
i := s - l + 1
if i < s -1 {
cv := load6432 (src , i )
t := tableEntry {offset : i + e .cur }
e .table [hashLen (cv , tableBits , hashShortBytes )] = t
eLong := &e .bTable [hash7 (cv , tableBits )]
eLong .Cur , eLong .Prev = t , eLong .Cur
cv >>= 8
t = tableEntry {offset : t .offset + 1 }
eLong = &e .bTable [hash7 (cv , tableBits )]
eLong .Cur , eLong .Prev = t , eLong .Cur
cv >>= 8
t = tableEntry {offset : t .offset + 1 }
e .table [hashLen (cv , tableBits , hashShortBytes )] = t
i += 4
for ; i < s -1 ; i += hashEvery {
cv := load6432 (src , i )
t := tableEntry {offset : i + e .cur }
t2 := tableEntry {offset : t .offset + 1 }
eLong := &e .bTable [hash7 (cv , tableBits )]
eLong .Cur , eLong .Prev = t , eLong .Cur
e .table [hashLen (cv >>8 , tableBits , hashShortBytes )] = t2
}
}
}
x := load6432 (src , s -1 )
o := e .cur + s - 1
prevHashS := hashLen (x , tableBits , hashShortBytes )
prevHashL := hash7 (x , tableBits )
e .table [prevHashS ] = tableEntry {offset : o }
eLong := &e .bTable [prevHashL ]
eLong .Cur , eLong .Prev = tableEntry {offset : o }, eLong .Cur
cv = x >> 8
}
emitRemainder :
if int (nextEmit ) < len (src ) {
if dst .n == 0 {
return
}
emitLiteral (dst , src [nextEmit :])
}
}
func (e *fastEncL5Window ) Reset () {
if cap (e .hist ) < allocHistory {
e .hist = make ([]byte , 0 , allocHistory )
}
if e .cur <= int32 (bufferReset ) {
e .cur += e .maxOffset + int32 (len (e .hist ))
}
e .hist = e .hist [:0 ]
}
func (e *fastEncL5Window ) addBlock (src []byte ) int32 {
maxMatchOffset := e .maxOffset
if len (e .hist )+len (src ) > cap (e .hist ) {
if cap (e .hist ) == 0 {
e .hist = make ([]byte , 0 , allocHistory )
} else {
if cap (e .hist ) < int (maxMatchOffset *2 ) {
panic ("unexpected buffer size" )
}
offset := int32 (len (e .hist )) - maxMatchOffset
copy (e .hist [0 :maxMatchOffset ], e .hist [offset :])
e .cur += offset
e .hist = e .hist [:maxMatchOffset ]
}
}
s := int32 (len (e .hist ))
e .hist = append (e .hist , src ...)
return s
}
func (e *fastEncL5Window ) matchlen (s , t int32 , src []byte ) int32 {
if debugDecode {
if t >= s {
panic (fmt .Sprint ("t >=s:" , t , s ))
}
if int (s ) >= len (src ) {
panic (fmt .Sprint ("s >= len(src):" , s , len (src )))
}
if t < 0 {
panic (fmt .Sprint ("t < 0:" , t ))
}
if s -t > e .maxOffset {
panic (fmt .Sprint (s , "-" , t , "(" , s -t , ") > maxMatchLength (" , maxMatchOffset , ")" ))
}
}
s1 := int (s ) + maxMatchLength - 4
if s1 > len (src ) {
s1 = len (src )
}
return int32 (matchLen (src [s :s1 ], src [t :]))
}
func (e *fastEncL5Window ) matchlenLong (s , t int32 , src []byte ) int32 {
if debugDeflate {
if t >= s {
panic (fmt .Sprint ("t >=s:" , t , s ))
}
if int (s ) >= len (src ) {
panic (fmt .Sprint ("s >= len(src):" , s , len (src )))
}
if t < 0 {
panic (fmt .Sprint ("t < 0:" , t ))
}
if s -t > e .maxOffset {
panic (fmt .Sprint (s , "-" , t , "(" , s -t , ") > maxMatchLength (" , maxMatchOffset , ")" ))
}
}
return int32 (matchLen (src [s :], src [t :]))
}
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 .