diff options
Diffstat (limited to 'src/pkg/compress')
-rw-r--r-- | src/pkg/compress/bzip2/bzip2_test.go | 12 | ||||
-rw-r--r-- | src/pkg/compress/bzip2/huffman.go | 32 | ||||
-rw-r--r-- | src/pkg/compress/flate/fixedhuff.go | 4 | ||||
-rw-r--r-- | src/pkg/compress/flate/flate_test.go | 2 | ||||
-rw-r--r-- | src/pkg/compress/flate/inflate.go | 4 | ||||
-rw-r--r-- | src/pkg/compress/flate/reader_test.go | 2 | ||||
-rw-r--r-- | src/pkg/compress/gzip/gunzip.go | 15 | ||||
-rw-r--r-- | src/pkg/compress/gzip/gunzip_test.go | 36 | ||||
-rw-r--r-- | src/pkg/compress/gzip/gzip.go | 8 | ||||
-rw-r--r-- | src/pkg/compress/gzip/gzip_test.go | 2 | ||||
-rw-r--r-- | src/pkg/compress/lzw/reader.go | 4 | ||||
-rw-r--r-- | src/pkg/compress/lzw/reader_test.go | 4 | ||||
-rw-r--r-- | src/pkg/compress/lzw/writer.go | 4 | ||||
-rw-r--r-- | src/pkg/compress/zlib/example_test.go | 2 | ||||
-rw-r--r-- | src/pkg/compress/zlib/reader.go | 3 | ||||
-rw-r--r-- | src/pkg/compress/zlib/reader_test.go | 2 | ||||
-rw-r--r-- | src/pkg/compress/zlib/writer.go | 4 | ||||
-rw-r--r-- | src/pkg/compress/zlib/writer_test.go | 2 |
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) |