summaryrefslogtreecommitdiff
path: root/src/pkg/compress
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/compress')
-rw-r--r--src/pkg/compress/bzip2/bzip2_test.go12
-rw-r--r--src/pkg/compress/bzip2/huffman.go32
-rw-r--r--src/pkg/compress/flate/fixedhuff.go4
-rw-r--r--src/pkg/compress/flate/flate_test.go2
-rw-r--r--src/pkg/compress/flate/inflate.go4
-rw-r--r--src/pkg/compress/flate/reader_test.go2
-rw-r--r--src/pkg/compress/gzip/gunzip.go15
-rw-r--r--src/pkg/compress/gzip/gunzip_test.go36
-rw-r--r--src/pkg/compress/gzip/gzip.go8
-rw-r--r--src/pkg/compress/gzip/gzip_test.go2
-rw-r--r--src/pkg/compress/lzw/reader.go4
-rw-r--r--src/pkg/compress/lzw/reader_test.go4
-rw-r--r--src/pkg/compress/lzw/writer.go4
-rw-r--r--src/pkg/compress/zlib/example_test.go2
-rw-r--r--src/pkg/compress/zlib/reader.go3
-rw-r--r--src/pkg/compress/zlib/reader_test.go2
-rw-r--r--src/pkg/compress/zlib/writer.go4
-rw-r--r--src/pkg/compress/zlib/writer_test.go2
18 files changed, 113 insertions, 29 deletions
diff --git a/src/pkg/compress/bzip2/bzip2_test.go b/src/pkg/compress/bzip2/bzip2_test.go
index ada1f9a00..727249dc4 100644
--- a/src/pkg/compress/bzip2/bzip2_test.go
+++ b/src/pkg/compress/bzip2/bzip2_test.go
@@ -14,7 +14,7 @@ import (
)
func TestBitReader(t *testing.T) {
- buf := bytes.NewBuffer([]byte{0xaa})
+ buf := bytes.NewReader([]byte{0xaa})
br := newBitReader(buf)
if n := br.ReadBits(1); n != 1 {
t.Errorf("read 1 wrong")
@@ -31,7 +31,7 @@ func TestBitReader(t *testing.T) {
}
func TestBitReaderLarge(t *testing.T) {
- buf := bytes.NewBuffer([]byte{0x12, 0x34, 0x56, 0x78})
+ buf := bytes.NewReader([]byte{0x12, 0x34, 0x56, 0x78})
br := newBitReader(buf)
if n := br.ReadBits(32); n != 0x12345678 {
t.Errorf("got: %x want: %x", n, 0x12345678)
@@ -43,7 +43,7 @@ func readerFromHex(s string) io.Reader {
if err != nil {
panic("readerFromHex: bad input")
}
- return bytes.NewBuffer(data)
+ return bytes.NewReader(data)
}
func decompressHex(s string) (out []byte, err error) {
@@ -177,7 +177,7 @@ const (
var testfiles = []string{
// Digits is the digits of the irrational number e. Its decimal representation
- // does not repeat, but there are only 10 posible digits, so it should be
+ // does not repeat, but there are only 10 possible digits, so it should be
// reasonably compressible.
digits: "testdata/e.txt.bz2",
// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
@@ -191,7 +191,7 @@ func benchmarkDecode(b *testing.B, testfile int) {
}
b.SetBytes(int64(len(compressed)))
for i := 0; i < b.N; i++ {
- r := bytes.NewBuffer(compressed)
+ r := bytes.NewReader(compressed)
io.Copy(ioutil.Discard, NewReader(r))
}
}
@@ -201,7 +201,7 @@ func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
func TestBufferOverrun(t *testing.T) {
// Tests https://code.google.com/p/go/issues/detail?id=5747.
- buffer := bytes.NewBuffer([]byte(bufferOverrunBase64))
+ buffer := bytes.NewReader([]byte(bufferOverrunBase64))
decoder := base64.NewDecoder(base64.StdEncoding, buffer)
decompressor := NewReader(decoder)
// This shouldn't panic.
diff --git a/src/pkg/compress/bzip2/huffman.go b/src/pkg/compress/bzip2/huffman.go
index 8f6b0c9ca..75a6223d8 100644
--- a/src/pkg/compress/bzip2/huffman.go
+++ b/src/pkg/compress/bzip2/huffman.go
@@ -190,7 +190,37 @@ func buildHuffmanNode(t *huffmanTree, codes []huffmanCode, level uint32) (nodeIn
right := codes[firstRightIndex:]
if len(left) == 0 || len(right) == 0 {
- return 0, StructuralError("superfluous level in Huffman tree")
+ // There is a superfluous level in the Huffman tree indicating
+ // a bug in the encoder. However, this bug has been observed in
+ // the wild so we handle it.
+
+ // If this function was called recursively then we know that
+ // len(codes) >= 2 because, otherwise, we would have hit the
+ // "leaf node" case, below, and not recursed.
+ //
+ // However, for the initial call it's possible that len(codes)
+ // is zero or one. Both cases are invalid because a zero length
+ // tree cannot encode anything and a length-1 tree can only
+ // encode EOF and so is superfluous. We reject both.
+ if len(codes) < 2 {
+ return 0, StructuralError("empty Huffman tree")
+ }
+
+ // In this case the recursion doesn't always reduce the length
+ // of codes so we need to ensure termination via another
+ // mechanism.
+ if level == 31 {
+ // Since len(codes) >= 2 the only way that the values
+ // can match at all 32 bits is if they are equal, which
+ // is invalid. This ensures that we never enter
+ // infinite recursion.
+ return 0, StructuralError("equal symbols in Huffman tree")
+ }
+
+ if len(left) == 0 {
+ return buildHuffmanNode(t, right, level+1)
+ }
+ return buildHuffmanNode(t, left, level+1)
}
nodeIndex = uint16(t.nextNode)
diff --git a/src/pkg/compress/flate/fixedhuff.go b/src/pkg/compress/flate/fixedhuff.go
index 41a6b25df..9be3d5349 100644
--- a/src/pkg/compress/flate/fixedhuff.go
+++ b/src/pkg/compress/flate/fixedhuff.go
@@ -1,3 +1,7 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package flate
// autogenerated by gen.go, DO NOT EDIT
diff --git a/src/pkg/compress/flate/flate_test.go b/src/pkg/compress/flate/flate_test.go
index 57fea5ab4..068766323 100644
--- a/src/pkg/compress/flate/flate_test.go
+++ b/src/pkg/compress/flate/flate_test.go
@@ -14,7 +14,7 @@ import (
)
func TestUncompressedSource(t *testing.T) {
- decoder := NewReader(bytes.NewBuffer([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11}))
+ decoder := NewReader(bytes.NewReader([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11}))
output := make([]byte, 1)
n, error := decoder.Read(output)
if n != 1 || error != nil {
diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go
index 3eb3b2b83..ce4923eca 100644
--- a/src/pkg/compress/flate/inflate.go
+++ b/src/pkg/compress/flate/inflate.go
@@ -54,7 +54,7 @@ func (e *WriteError) Error() string {
return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error()
}
-// Note that much of the implemenation of huffmanDecoder is also copied
+// Note that much of the implementation of huffmanDecoder is also copied
// into gen.go (in package main) for the purpose of precomputing the
// fixed huffman tables so they can be included statically.
@@ -180,7 +180,7 @@ func (h *huffmanDecoder) init(bits []int) bool {
// the NewReader will introduce its own buffering.
type Reader interface {
io.Reader
- ReadByte() (c byte, err error)
+ io.ByteReader
}
// Decompress state.
diff --git a/src/pkg/compress/flate/reader_test.go b/src/pkg/compress/flate/reader_test.go
index 2a8ebbc94..a62ef741d 100644
--- a/src/pkg/compress/flate/reader_test.go
+++ b/src/pkg/compress/flate/reader_test.go
@@ -29,7 +29,7 @@ const (
var testfiles = []string{
// Digits is the digits of the irrational number e. Its decimal representation
- // does not repeat, but there are only 10 posible digits, so it should be
+ // does not repeat, but there are only 10 possible digits, so it should be
// reasonably compressible.
digits: "../testdata/e.txt",
// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
diff --git a/src/pkg/compress/gzip/gunzip.go b/src/pkg/compress/gzip/gunzip.go
index 1fb9b0964..4f398b194 100644
--- a/src/pkg/compress/gzip/gunzip.go
+++ b/src/pkg/compress/gzip/gunzip.go
@@ -89,6 +89,21 @@ func NewReader(r io.Reader) (*Reader, error) {
return z, nil
}
+// Reset discards the Reader z's state and makes it equivalent to the
+// result of its original state from NewReader, but reading from r instead.
+// This permits reusing a Reader rather than allocating a new one.
+func (z *Reader) Reset(r io.Reader) error {
+ z.r = makeReader(r)
+ if z.digest == nil {
+ z.digest = crc32.NewIEEE()
+ } else {
+ z.digest.Reset()
+ }
+ z.size = 0
+ z.err = nil
+ return z.readHeader(true)
+}
+
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
func get4(p []byte) uint32 {
return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
diff --git a/src/pkg/compress/gzip/gunzip_test.go b/src/pkg/compress/gzip/gunzip_test.go
index 572fb5848..2471038f5 100644
--- a/src/pkg/compress/gzip/gunzip_test.go
+++ b/src/pkg/compress/gzip/gunzip_test.go
@@ -284,7 +284,7 @@ var gunzipTests = []gunzipTest{
func TestDecompressor(t *testing.T) {
b := new(bytes.Buffer)
for _, tt := range gunzipTests {
- in := bytes.NewBuffer(tt.gzip)
+ in := bytes.NewReader(tt.gzip)
gzip, err := NewReader(in)
if err != nil {
t.Errorf("%s: NewReader: %s", tt.name, err)
@@ -303,6 +303,26 @@ func TestDecompressor(t *testing.T) {
if s != tt.raw {
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
}
+
+ // Test Reader Reset.
+ in = bytes.NewReader(tt.gzip)
+ err = gzip.Reset(in)
+ if err != nil {
+ t.Errorf("%s: Reset: %s", tt.name, err)
+ continue
+ }
+ if tt.name != gzip.Name {
+ t.Errorf("%s: got name %s", tt.name, gzip.Name)
+ }
+ b.Reset()
+ n, err = io.Copy(b, gzip)
+ if err != tt.err {
+ t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err)
+ }
+ s = b.String()
+ if s != tt.raw {
+ t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw)
+ }
}
}
@@ -333,3 +353,17 @@ func TestIssue6550(t *testing.T) {
// ok
}
}
+
+func TestInitialReset(t *testing.T) {
+ var r Reader
+ if err := r.Reset(bytes.NewReader(gunzipTests[1].gzip)); err != nil {
+ t.Error(err)
+ }
+ var buf bytes.Buffer
+ if _, err := io.Copy(&buf, &r); err != nil {
+ t.Error(err)
+ }
+ if s := buf.String(); s != gunzipTests[1].raw {
+ t.Errorf("got %q want %q", s, gunzipTests[1].raw)
+ }
+}
diff --git a/src/pkg/compress/gzip/gzip.go b/src/pkg/compress/gzip/gzip.go
index fe32d6871..3a0bf54e1 100644
--- a/src/pkg/compress/gzip/gzip.go
+++ b/src/pkg/compress/gzip/gzip.go
@@ -22,8 +22,8 @@ const (
DefaultCompression = flate.DefaultCompression
)
-// A Writer is an io.WriteCloser that satisfies writes by compressing data written
-// to its wrapped io.Writer.
+// A Writer is an io.WriteCloser.
+// Writes to a Writer are compressed and written to w.
type Writer struct {
Header
w io.Writer
@@ -37,8 +37,8 @@ type Writer struct {
err error
}
-// NewWriter creates a new Writer that satisfies writes by compressing data
-// written to w.
+// 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.
// Writes may be buffered and not flushed until Close.
diff --git a/src/pkg/compress/gzip/gzip_test.go b/src/pkg/compress/gzip/gzip_test.go
index 119be2e13..09271b24e 100644
--- a/src/pkg/compress/gzip/gzip_test.go
+++ b/src/pkg/compress/gzip/gzip_test.go
@@ -85,7 +85,7 @@ func TestRoundTrip(t *testing.T) {
func TestLatin1(t *testing.T) {
latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0}
utf8 := "Äußerung"
- z := Reader{r: bufio.NewReader(bytes.NewBuffer(latin1))}
+ z := Reader{r: bufio.NewReader(bytes.NewReader(latin1))}
s, err := z.readString()
if err != nil {
t.Fatalf("readString: %v", err)
diff --git a/src/pkg/compress/lzw/reader.go b/src/pkg/compress/lzw/reader.go
index efbc758f9..ef5969910 100644
--- a/src/pkg/compress/lzw/reader.go
+++ b/src/pkg/compress/lzw/reader.go
@@ -216,8 +216,8 @@ func (d *decoder) Close() error {
return nil
}
-// NewReader creates a new io.ReadCloser that satisfies reads by decompressing
-// the data read from r.
+// NewReader creates a new io.ReadCloser.
+// Reads from the returned io.ReadCloser read and decompress data from r.
// It is the caller's responsibility to call Close on the ReadCloser when
// finished reading.
// The number of bits to use for literal codes, litWidth, must be in the
diff --git a/src/pkg/compress/lzw/reader_test.go b/src/pkg/compress/lzw/reader_test.go
index 6f155b1bd..9006c91c2 100644
--- a/src/pkg/compress/lzw/reader_test.go
+++ b/src/pkg/compress/lzw/reader_test.go
@@ -127,7 +127,7 @@ func benchmarkDecoder(b *testing.B, n int) {
if len(buf0) > n-i {
buf0 = buf0[:n-i]
}
- io.Copy(w, bytes.NewBuffer(buf0))
+ w.Write(buf0)
}
w.Close()
buf1 := compressed.Bytes()
@@ -135,7 +135,7 @@ func benchmarkDecoder(b *testing.B, n int) {
runtime.GC()
b.StartTimer()
for i := 0; i < b.N; i++ {
- io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1), LSB, 8))
+ io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1), LSB, 8))
}
}
diff --git a/src/pkg/compress/lzw/writer.go b/src/pkg/compress/lzw/writer.go
index b20691864..961b25f94 100644
--- a/src/pkg/compress/lzw/writer.go
+++ b/src/pkg/compress/lzw/writer.go
@@ -225,8 +225,8 @@ func (e *encoder) Close() error {
return e.w.Flush()
}
-// NewWriter creates a new io.WriteCloser that satisfies writes by compressing
-// the data and writing it to w.
+// NewWriter creates a new io.WriteCloser.
+// Writes to the returned io.WriteCloser are compressed and written to w.
// It is the caller's responsibility to call Close on the WriteCloser when
// finished writing.
// The number of bits to use for literal codes, litWidth, must be in the
diff --git a/src/pkg/compress/zlib/example_test.go b/src/pkg/compress/zlib/example_test.go
index b934ffa61..70408895f 100644
--- a/src/pkg/compress/zlib/example_test.go
+++ b/src/pkg/compress/zlib/example_test.go
@@ -25,7 +25,7 @@ func ExampleNewWriter() {
func ExampleNewReader() {
buff := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
- b := bytes.NewBuffer(buff)
+ b := bytes.NewReader(buff)
r, err := zlib.NewReader(b)
if err != nil {
diff --git a/src/pkg/compress/zlib/reader.go b/src/pkg/compress/zlib/reader.go
index d54746f4c..9e1aafda9 100644
--- a/src/pkg/compress/zlib/reader.go
+++ b/src/pkg/compress/zlib/reader.go
@@ -51,7 +51,8 @@ type reader struct {
scratch [4]byte
}
-// NewReader creates a new io.ReadCloser that satisfies reads by decompressing data read from r.
+// NewReader creates a new io.ReadCloser.
+// Reads from the returned io.ReadCloser read and decompress data from r.
// The implementation buffers input and may read more data than necessary from r.
// It is the caller's responsibility to call Close on the ReadCloser when done.
func NewReader(r io.Reader) (io.ReadCloser, error) {
diff --git a/src/pkg/compress/zlib/reader_test.go b/src/pkg/compress/zlib/reader_test.go
index 3b02a0868..218ccba14 100644
--- a/src/pkg/compress/zlib/reader_test.go
+++ b/src/pkg/compress/zlib/reader_test.go
@@ -102,7 +102,7 @@ var zlibTests = []zlibTest{
func TestDecompressor(t *testing.T) {
b := new(bytes.Buffer)
for _, tt := range zlibTests {
- in := bytes.NewBuffer(tt.compressed)
+ in := bytes.NewReader(tt.compressed)
zlib, err := NewReaderDict(in, tt.dict)
if err != nil {
if err != tt.err {
diff --git a/src/pkg/compress/zlib/writer.go b/src/pkg/compress/zlib/writer.go
index 99ff6549a..fac7e15a7 100644
--- a/src/pkg/compress/zlib/writer.go
+++ b/src/pkg/compress/zlib/writer.go
@@ -34,8 +34,8 @@ type Writer struct {
wroteHeader bool
}
-// NewWriter creates a new Writer that satisfies writes by compressing data
-// written to w.
+// 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.
// Writes may be buffered and not flushed until Close.
diff --git a/src/pkg/compress/zlib/writer_test.go b/src/pkg/compress/zlib/writer_test.go
index cf9c83254..71ba81aaa 100644
--- a/src/pkg/compress/zlib/writer_test.go
+++ b/src/pkg/compress/zlib/writer_test.go
@@ -120,7 +120,7 @@ func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
}
out := buf.String()
- // Reset and comprses again.
+ // Reset and compress again.
buf2 := new(bytes.Buffer)
zlibw.Reset(buf2)
_, err = zlibw.Write(b0)