mirror of https://github.com/golang/go.git
compress/flate: tighten the BestSpeed max match offset bound.
Previously, we were off by one. Also fix a comment typo. Change-Id: Ib94d23acc56d5fccd44144f71655481f98803ac8 Reviewed-on: https://go-review.googlesource.com/32149 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com> Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
f135106ec7
commit
590fce4884
|
|
@ -798,3 +798,62 @@ func TestBestSpeedMatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBestSpeedMaxMatchOffset(t *testing.T) {
|
||||||
|
const abc, xyz = "abcdefgh", "stuvwxyz"
|
||||||
|
for _, matchBefore := range []bool{false, true} {
|
||||||
|
for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} {
|
||||||
|
for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ {
|
||||||
|
report := func(desc string, err error) {
|
||||||
|
t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v",
|
||||||
|
matchBefore, extra, offsetAdj, desc, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := maxMatchOffset + offsetAdj
|
||||||
|
|
||||||
|
// Make src to be a []byte of the form
|
||||||
|
// "%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1)
|
||||||
|
// where:
|
||||||
|
// zeros0 is approximately maxMatchOffset zeros.
|
||||||
|
// xyzMaybe is either xyz or the empty string.
|
||||||
|
// zeros1 is between 0 and 30 zeros.
|
||||||
|
// The difference between the two abc's will be offset, which
|
||||||
|
// is maxMatchOffset plus or minus a small adjustment.
|
||||||
|
src := make([]byte, offset+len(abc)+extra)
|
||||||
|
copy(src, abc)
|
||||||
|
if !matchBefore {
|
||||||
|
copy(src[offset-len(xyz):], xyz)
|
||||||
|
}
|
||||||
|
copy(src[offset:], abc)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w, err := NewWriter(buf, BestSpeed)
|
||||||
|
if err != nil {
|
||||||
|
report("NewWriter: ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := w.Write(src); err != nil {
|
||||||
|
report("Write: ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := w.Close(); err != nil {
|
||||||
|
report("Writer.Close: ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := NewReader(buf)
|
||||||
|
dst, err := ioutil.ReadAll(r)
|
||||||
|
r.Close()
|
||||||
|
if err != nil {
|
||||||
|
report("ReadAll: ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(dst, src) {
|
||||||
|
report("", fmt.Errorf("bytes differ after round-tripping"))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func newDeflateFast() *deflateFast {
|
||||||
return &deflateFast{cur: maxStoreBlockSize, prev: make([]byte, 0, maxStoreBlockSize)}
|
return &deflateFast{cur: maxStoreBlockSize, prev: make([]byte, 0, maxStoreBlockSize)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode encodes a block given in src and encodes tokens
|
// encode encodes a block given in src and appends tokens
|
||||||
// to dst and returns the result.
|
// to dst and returns the result.
|
||||||
func (e *deflateFast) encode(dst []token, src []byte) []token {
|
func (e *deflateFast) encode(dst []token, src []byte) []token {
|
||||||
// Ensure that e.cur doesn't wrap.
|
// Ensure that e.cur doesn't wrap.
|
||||||
|
|
@ -116,8 +116,7 @@ func (e *deflateFast) encode(dst []token, src []byte) []token {
|
||||||
nextHash = hash(now)
|
nextHash = hash(now)
|
||||||
|
|
||||||
offset := s - (candidate.offset - e.cur)
|
offset := s - (candidate.offset - e.cur)
|
||||||
// TODO: >= should be >, and add a test for that.
|
if offset > maxMatchOffset || cv != candidate.val {
|
||||||
if offset >= maxMatchOffset || cv != candidate.val {
|
|
||||||
// Out of range or not matched.
|
// Out of range or not matched.
|
||||||
cv = now
|
cv = now
|
||||||
continue
|
continue
|
||||||
|
|
@ -171,8 +170,7 @@ func (e *deflateFast) encode(dst []token, src []byte) []token {
|
||||||
e.table[currHash&tableMask] = tableEntry{offset: e.cur + s, val: uint32(x)}
|
e.table[currHash&tableMask] = tableEntry{offset: e.cur + s, val: uint32(x)}
|
||||||
|
|
||||||
offset := s - (candidate.offset - e.cur)
|
offset := s - (candidate.offset - e.cur)
|
||||||
// TODO: >= should be >, and add a test for that.
|
if offset > maxMatchOffset || uint32(x) != candidate.val {
|
||||||
if offset >= maxMatchOffset || uint32(x) != candidate.val {
|
|
||||||
cv = uint32(x >> 8)
|
cv = uint32(x >> 8)
|
||||||
nextHash = hash(cv)
|
nextHash = hash(cv)
|
||||||
s++
|
s++
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue