aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/compress
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-09-24 21:46:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-24 21:46:21 +0000
commitdd931d9b48647e898dc80927c532ae93cc09e192 (patch)
tree71be2295cd79b8a182f6130611658db8628772d5 /libgo/go/compress
parent779d8a5ad09b01428726ea5a0e6c87bd9ac3c0e4 (diff)
downloadgcc-dd931d9b48647e898dc80927c532ae93cc09e192.zip
gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.gz
gcc-dd931d9b48647e898dc80927c532ae93cc09e192.tar.bz2
libgo: update to Go 1.11
Reviewed-on: https://go-review.googlesource.com/136435 gotools/: * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to make sure it is writable. (check-go-tools): Likewise. (check-vet): Copy internal/objabi to check-vet-dir. * Makefile.in: Rebuild. From-SVN: r264546
Diffstat (limited to 'libgo/go/compress')
-rw-r--r--libgo/go/compress/bzip2/bzip2.go2
-rw-r--r--libgo/go/compress/bzip2/huffman.go92
-rw-r--r--libgo/go/compress/flate/deflate.go2
-rw-r--r--libgo/go/compress/flate/inflate.go65
-rw-r--r--libgo/go/compress/gzip/gzip.go12
-rw-r--r--libgo/go/compress/gzip/gzip_test.go38
-rw-r--r--libgo/go/compress/gzip/issue14937_test.go4
-rw-r--r--libgo/go/compress/lzw/reader_test.go2
-rw-r--r--libgo/go/compress/zlib/reader_test.go2
-rw-r--r--libgo/go/compress/zlib/writer.go2
10 files changed, 126 insertions, 95 deletions
diff --git a/libgo/go/compress/bzip2/bzip2.go b/libgo/go/compress/bzip2/bzip2.go
index f07c7e8..c40129b 100644
--- a/libgo/go/compress/bzip2/bzip2.go
+++ b/libgo/go/compress/bzip2/bzip2.go
@@ -8,7 +8,7 @@ package bzip2
import "io"
// There's no RFC for bzip2. I used the Wikipedia page for reference and a lot
-// of guessing: http://en.wikipedia.org/wiki/Bzip2
+// of guessing: https://en.wikipedia.org/wiki/Bzip2
// The source code to pyflate was useful for debugging:
// http://www.paul.sladen.org/projects/pyflate
diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go
index dbba9a5..36ae954 100644
--- a/libgo/go/compress/bzip2/huffman.go
+++ b/libgo/go/compress/bzip2/huffman.go
@@ -43,30 +43,34 @@ func (t *huffmanTree) Decode(br *bitReader) (v uint16) {
if br.bits > 0 {
// Get next bit - fast path.
br.bits--
- bit = 0 - (uint16(br.n>>br.bits) & 1)
+ bit = uint16(br.n>>(br.bits&63)) & 1
} else {
// Get next bit - slow path.
// Use ReadBits to retrieve a single bit
// from the underling io.ByteReader.
- bit = 0 - uint16(br.ReadBits(1))
+ bit = uint16(br.ReadBits(1))
}
- // now
- // bit = 0xffff if the next bit was 1
- // bit = 0x0000 if the next bit was 0
- // 1 means left, 0 means right.
- //
- // if bit == 0xffff {
- // nodeIndex = node.left
- // } else {
- // nodeIndex = node.right
- // }
- nodeIndex = (bit & node.left) | (^bit & node.right)
+ // Trick a compiler into generating conditional move instead of branch,
+ // by making both loads unconditional.
+ l, r := node.left, node.right
+
+ if bit == 1 {
+ nodeIndex = l
+ } else {
+ nodeIndex = r
+ }
if nodeIndex == invalidNodeValue {
// We found a leaf. Use the value of bit to decide
// whether is a left or a right value.
- return (bit & node.leftValue) | (^bit & node.rightValue)
+ l, r := node.leftValue, node.rightValue
+ if bit == 1 {
+ v = l
+ } else {
+ v = r
+ }
+ return
}
}
}
@@ -90,13 +94,24 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) {
// First we sort the code length assignments by ascending code length,
// using the symbol value to break ties.
- pairs := huffmanSymbolLengthPairs(make([]huffmanSymbolLengthPair, len(lengths)))
+ pairs := make([]huffmanSymbolLengthPair, len(lengths))
for i, length := range lengths {
pairs[i].value = uint16(i)
pairs[i].length = length
}
- sort.Sort(pairs)
+ sort.Slice(pairs, func(i, j int) bool {
+ if pairs[i].length < pairs[j].length {
+ return true
+ }
+ if pairs[i].length > pairs[j].length {
+ return false
+ }
+ if pairs[i].value < pairs[j].value {
+ return true
+ }
+ return false
+ })
// Now we assign codes to the symbols, starting with the longest code.
// We keep the codes packed into a uint32, at the most-significant end.
@@ -105,7 +120,7 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) {
code := uint32(0)
length := uint8(32)
- codes := huffmanCodes(make([]huffmanCode, len(lengths)))
+ codes := make([]huffmanCode, len(lengths))
for i := len(pairs) - 1; i >= 0; i-- {
if length > pairs[i].length {
length = pairs[i].length
@@ -120,7 +135,9 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) {
// Now we can sort by the code so that the left half of each branch are
// grouped together, recursively.
- sort.Sort(codes)
+ sort.Slice(codes, func(i, j int) bool {
+ return codes[i].code < codes[j].code
+ })
t.nodes = make([]huffmanNode, len(codes))
_, err := buildHuffmanNode(&t, codes, 0)
@@ -133,30 +150,6 @@ type huffmanSymbolLengthPair struct {
length uint8
}
-// huffmanSymbolLengthPair is used to provide an interface for sorting.
-type huffmanSymbolLengthPairs []huffmanSymbolLengthPair
-
-func (h huffmanSymbolLengthPairs) Len() int {
- return len(h)
-}
-
-func (h huffmanSymbolLengthPairs) Less(i, j int) bool {
- if h[i].length < h[j].length {
- return true
- }
- if h[i].length > h[j].length {
- return false
- }
- if h[i].value < h[j].value {
- return true
- }
- return false
-}
-
-func (h huffmanSymbolLengthPairs) Swap(i, j int) {
- h[i], h[j] = h[j], h[i]
-}
-
// huffmanCode contains a symbol, its code and code length.
type huffmanCode struct {
code uint32
@@ -164,21 +157,6 @@ type huffmanCode struct {
value uint16
}
-// huffmanCodes is used to provide an interface for sorting.
-type huffmanCodes []huffmanCode
-
-func (n huffmanCodes) Len() int {
- return len(n)
-}
-
-func (n huffmanCodes) Less(i, j int) bool {
- return n[i].code < n[j].code
-}
-
-func (n huffmanCodes) Swap(i, j int) {
- n[i], n[j] = n[j], n[i]
-}
-
// buildHuffmanNode takes a slice of sorted huffmanCodes and builds a node in
// the Huffman tree at the given level. It returns the index of the newly
// constructed node.
diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go
index 4d6a535..8b92f15 100644
--- a/libgo/go/compress/flate/deflate.go
+++ b/libgo/go/compress/flate/deflate.go
@@ -720,7 +720,7 @@ func (w *Writer) Write(data []byte) (n int, err error) {
// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
func (w *Writer) Flush() error {
// For more about flushing:
- // http://www.bolet.org/~pornin/deflate-flush.html
+ // https://www.bolet.org/~pornin/deflate-flush.html
return w.d.syncFlush()
}
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index faa33cc..25e81f3 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -10,7 +10,7 @@ package flate
import (
"bufio"
"io"
- mathbits "math/bits"
+ "math/bits"
"strconv"
"sync"
)
@@ -113,7 +113,7 @@ type huffmanDecoder struct {
// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a
// degenerate case where the tree has only a single symbol with length 1. Empty
// trees are permitted.
-func (h *huffmanDecoder) init(bits []int) bool {
+func (h *huffmanDecoder) init(lengths []int) bool {
// Sanity enables additional runtime tests during Huffman
// table construction. It's intended to be used during
// development to supplement the currently ad-hoc unit tests.
@@ -127,7 +127,7 @@ func (h *huffmanDecoder) init(bits []int) bool {
// compute min and max length.
var count [maxCodeLen]int
var min, max int
- for _, n := range bits {
+ for _, n := range lengths {
if n == 0 {
continue
}
@@ -177,7 +177,7 @@ func (h *huffmanDecoder) init(bits []int) bool {
link := nextcode[huffmanChunkBits+1] >> 1
h.links = make([][]uint32, huffmanNumChunks-link)
for j := uint(link); j < huffmanNumChunks; j++ {
- reverse := int(mathbits.Reverse16(uint16(j)))
+ reverse := int(bits.Reverse16(uint16(j)))
reverse >>= uint(16 - huffmanChunkBits)
off := j - uint(link)
if sanity && h.chunks[reverse] != 0 {
@@ -188,14 +188,14 @@ func (h *huffmanDecoder) init(bits []int) bool {
}
}
- for i, n := range bits {
+ for i, n := range lengths {
if n == 0 {
continue
}
code := nextcode[n]
nextcode[n]++
chunk := uint32(i<<huffmanValueShift | n)
- reverse := int(mathbits.Reverse16(uint16(code)))
+ reverse := int(bits.Reverse16(uint16(code)))
reverse >>= uint(16 - n)
if n <= huffmanChunkBits {
for off := reverse; off < len(h.chunks); off += 1 << uint(n) {
@@ -557,7 +557,7 @@ readLiteral:
return
}
}
- dist = int(mathbits.Reverse8(uint8(f.b & 0x1F << 3)))
+ dist = int(bits.Reverse8(uint8(f.b & 0x1F << 3)))
f.b >>= 5
f.nb -= 5
} else {
@@ -629,10 +629,7 @@ func (f *decompressor) dataBlock() {
nr, err := io.ReadFull(f.r, f.buf[0:4])
f.roffset += int64(nr)
if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- f.err = err
+ f.err = noEOF(err)
return
}
n := int(f.buf[0]) | int(f.buf[1])<<8
@@ -665,10 +662,7 @@ func (f *decompressor) copyData() {
f.copyLen -= cnt
f.dict.writeMark(cnt)
if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- f.err = err
+ f.err = noEOF(err)
return
}
@@ -690,13 +684,18 @@ func (f *decompressor) finishBlock() {
f.step = (*decompressor).nextBlock
}
+// noEOF returns err, unless err == io.EOF, in which case it returns io.ErrUnexpectedEOF.
+func noEOF(e error) error {
+ if e == io.EOF {
+ return io.ErrUnexpectedEOF
+ }
+ return e
+}
+
func (f *decompressor) moreBits() error {
c, err := f.r.ReadByte()
if err != nil {
- if err == io.EOF {
- err = io.ErrUnexpectedEOF
- }
- return err
+ return noEOF(err)
}
f.roffset++
f.b |= uint32(c) << f.nb
@@ -711,25 +710,37 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) {
// cases, the chunks slice will be 0 for the invalid sequence, leading it
// satisfy the n == 0 check below.
n := uint(h.min)
+ // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
+ // but is smart enough to keep local variables in registers, so use nb and b,
+ // inline call to moreBits and reassign b,nb back to f on return.
+ nb, b := f.nb, f.b
for {
- for f.nb < n {
- if err := f.moreBits(); err != nil {
- return 0, err
+ for nb < n {
+ c, err := f.r.ReadByte()
+ if err != nil {
+ f.b = b
+ f.nb = nb
+ return 0, noEOF(err)
}
+ f.roffset++
+ b |= uint32(c) << (nb & 31)
+ nb += 8
}
- chunk := h.chunks[f.b&(huffmanNumChunks-1)]
+ chunk := h.chunks[b&(huffmanNumChunks-1)]
n = uint(chunk & huffmanCountMask)
if n > huffmanChunkBits {
- chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask]
+ chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask]
n = uint(chunk & huffmanCountMask)
}
- if n <= f.nb {
+ if n <= nb {
if n == 0 {
+ f.b = b
+ f.nb = nb
f.err = CorruptInputError(f.roffset)
return 0, f.err
}
- f.b >>= n
- f.nb -= n
+ f.b = b >> (n & 31)
+ f.nb = nb - n
return int(chunk >> huffmanValueShift), nil
}
}
diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go
index 0cc44c5..eaeb185 100644
--- a/libgo/go/compress/gzip/gzip.go
+++ b/libgo/go/compress/gzip/gzip.go
@@ -41,7 +41,7 @@ type Writer struct {
// NewWriter returns a new Writer.
// Writes to the returned writer are compressed and written to w.
//
-// It is the caller's responsibility to call Close on the WriteCloser when done.
+// It is the caller's responsibility to call Close on the Writer when done.
// Writes may be buffered and not flushed until Close.
//
// Callers that wish to set the fields in Writer.Header must do so before
@@ -165,26 +165,26 @@ func (z *Writer) Write(p []byte) (int, error) {
z.buf[8] = 4
}
z.buf[9] = z.OS
- n, z.err = z.w.Write(z.buf[:10])
+ _, z.err = z.w.Write(z.buf[:10])
if z.err != nil {
- return n, z.err
+ return 0, z.err
}
if z.Extra != nil {
z.err = z.writeBytes(z.Extra)
if z.err != nil {
- return n, z.err
+ return 0, z.err
}
}
if z.Name != "" {
z.err = z.writeString(z.Name)
if z.err != nil {
- return n, z.err
+ return 0, z.err
}
}
if z.Comment != "" {
z.err = z.writeString(z.Comment)
if z.err != nil {
- return n, z.err
+ return 0, z.err
}
}
if z.compressor == nil {
diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go
index 865c529..e16aba1 100644
--- a/libgo/go/compress/gzip/gzip_test.go
+++ b/libgo/go/compress/gzip/gzip_test.go
@@ -7,6 +7,7 @@ package gzip
import (
"bufio"
"bytes"
+ "io"
"io/ioutil"
"reflect"
"testing"
@@ -233,3 +234,40 @@ func TestWriterReset(t *testing.T) {
t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String())
}
}
+
+type limitedWriter struct {
+ N int
+}
+
+func (l *limitedWriter) Write(p []byte) (n int, err error) {
+ if n := l.N; n < len(p) {
+ l.N = 0
+ return n, io.ErrShortWrite
+ }
+ l.N -= len(p)
+ return len(p), nil
+}
+
+// Write should never return more bytes than the input slice.
+func TestLimitedWrite(t *testing.T) {
+ msg := []byte("a")
+
+ for lim := 2; lim < 20; lim++ {
+ z := NewWriter(&limitedWriter{lim})
+ if n, _ := z.Write(msg); n > len(msg) {
+ t.Errorf("Write() = %d, want %d or less", n, len(msg))
+ }
+
+ z.Reset(&limitedWriter{lim})
+ z.Header = Header{
+ Comment: "comment",
+ Extra: []byte("extra"),
+ ModTime: time.Now(),
+ Name: "name",
+ OS: 1,
+ }
+ if n, _ := z.Write(msg); n > len(msg) {
+ t.Errorf("Write() = %d, want %d or less", n, len(msg))
+ }
+ }
+}
diff --git a/libgo/go/compress/gzip/issue14937_test.go b/libgo/go/compress/gzip/issue14937_test.go
index 30c1390..7a19672 100644
--- a/libgo/go/compress/gzip/issue14937_test.go
+++ b/libgo/go/compress/gzip/issue14937_test.go
@@ -21,6 +21,10 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
if testenv.Builder() == "" {
t.Skip("skipping test on non-builder")
}
+ if !testenv.HasSrc() {
+ t.Skip("skipping; no GOROOT available")
+ }
+
goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
if err != nil {
t.Fatal("error evaluating GOROOT: ", err)
diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go
index f8974de..98bbfbb 100644
--- a/libgo/go/compress/lzw/reader_test.go
+++ b/libgo/go/compress/lzw/reader_test.go
@@ -66,7 +66,7 @@ var lzwTests = []lzwTest{
"\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04",
io.ErrUnexpectedEOF,
},
- // This example comes from http://en.wikipedia.org/wiki/Graphics_Interchange_Format.
+ // This example comes from https://en.wikipedia.org/wiki/Graphics_Interchange_Format.
{
"gif;LSB;8",
"\x28\xff\xff\xff\x28\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
diff --git a/libgo/go/compress/zlib/reader_test.go b/libgo/go/compress/zlib/reader_test.go
index 7e27aec..70e33ba 100644
--- a/libgo/go/compress/zlib/reader_test.go
+++ b/libgo/go/compress/zlib/reader_test.go
@@ -19,7 +19,7 @@ type zlibTest struct {
}
// Compare-to-golden test data was generated by the ZLIB example program at
-// http://www.zlib.net/zpipe.c
+// https://www.zlib.net/zpipe.c
var zlibTests = []zlibTest{
{
diff --git a/libgo/go/compress/zlib/writer.go b/libgo/go/compress/zlib/writer.go
index 1620c00..a7b2194 100644
--- a/libgo/go/compress/zlib/writer.go
+++ b/libgo/go/compress/zlib/writer.go
@@ -38,7 +38,7 @@ type Writer struct {
// NewWriter creates a new Writer.
// Writes to the returned Writer are compressed and written to w.
//
-// It is the caller's responsibility to call Close on the WriteCloser when done.
+// It is the caller's responsibility to call Close on the Writer when done.
// Writes may be buffered and not flushed until Close.
func NewWriter(w io.Writer) *Writer {
z, _ := NewWriterLevelDict(w, DefaultCompression, nil)