diff options
Diffstat (limited to 'libgo/go/compress/lzw/reader.go')
-rw-r--r-- | libgo/go/compress/lzw/reader.go | 207 |
1 files changed, 114 insertions, 93 deletions
diff --git a/libgo/go/compress/lzw/reader.go b/libgo/go/compress/lzw/reader.go index f08021190c2..952870a56a2 100644 --- a/libgo/go/compress/lzw/reader.go +++ b/libgo/go/compress/lzw/reader.go @@ -42,15 +42,15 @@ const ( flushBuffer = 1 << maxWidth ) -// decoder is the state from which the readXxx method converts a byte -// stream into a code stream. -type decoder struct { +// Reader is an io.Reader which can be used to read compressed data in the +// LZW format. +type Reader struct { r io.ByteReader bits uint32 nBits uint width uint - read func(*decoder) (uint16, error) // readLSB or readMSB - litWidth int // width in bits of literal codes + read func(*Reader) (uint16, error) // readLSB or readMSB + litWidth int // width in bits of literal codes err error // The first 1<<litWidth codes are literal codes. @@ -87,148 +87,158 @@ type decoder struct { } // readLSB returns the next code for "Least Significant Bits first" data. -func (d *decoder) readLSB() (uint16, error) { - for d.nBits < d.width { - x, err := d.r.ReadByte() +func (r *Reader) readLSB() (uint16, error) { + for r.nBits < r.width { + x, err := r.r.ReadByte() if err != nil { return 0, err } - d.bits |= uint32(x) << d.nBits - d.nBits += 8 + r.bits |= uint32(x) << r.nBits + r.nBits += 8 } - code := uint16(d.bits & (1<<d.width - 1)) - d.bits >>= d.width - d.nBits -= d.width + code := uint16(r.bits & (1<<r.width - 1)) + r.bits >>= r.width + r.nBits -= r.width return code, nil } // readMSB returns the next code for "Most Significant Bits first" data. -func (d *decoder) readMSB() (uint16, error) { - for d.nBits < d.width { - x, err := d.r.ReadByte() +func (r *Reader) readMSB() (uint16, error) { + for r.nBits < r.width { + x, err := r.r.ReadByte() if err != nil { return 0, err } - d.bits |= uint32(x) << (24 - d.nBits) - d.nBits += 8 + r.bits |= uint32(x) << (24 - r.nBits) + r.nBits += 8 } - code := uint16(d.bits >> (32 - d.width)) - d.bits <<= d.width - d.nBits -= d.width + code := uint16(r.bits >> (32 - r.width)) + r.bits <<= r.width + r.nBits -= r.width return code, nil } -func (d *decoder) Read(b []byte) (int, error) { +// Read implements io.Reader, reading uncompressed bytes from its underlying Reader. +func (r *Reader) Read(b []byte) (int, error) { for { - if len(d.toRead) > 0 { - n := copy(b, d.toRead) - d.toRead = d.toRead[n:] + if len(r.toRead) > 0 { + n := copy(b, r.toRead) + r.toRead = r.toRead[n:] return n, nil } - if d.err != nil { - return 0, d.err + if r.err != nil { + return 0, r.err } - d.decode() + r.decode() } } // decode decompresses bytes from r and leaves them in d.toRead. // read specifies how to decode bytes into codes. // litWidth is the width in bits of literal codes. -func (d *decoder) decode() { +func (r *Reader) decode() { // Loop over the code stream, converting codes into decompressed bytes. loop: for { - code, err := d.read(d) + code, err := r.read(r) if err != nil { if err == io.EOF { err = io.ErrUnexpectedEOF } - d.err = err + r.err = err break } switch { - case code < d.clear: + case code < r.clear: // We have a literal code. - d.output[d.o] = uint8(code) - d.o++ - if d.last != decoderInvalidCode { + r.output[r.o] = uint8(code) + r.o++ + if r.last != decoderInvalidCode { // Save what the hi code expands to. - d.suffix[d.hi] = uint8(code) - d.prefix[d.hi] = d.last + r.suffix[r.hi] = uint8(code) + r.prefix[r.hi] = r.last } - case code == d.clear: - d.width = 1 + uint(d.litWidth) - d.hi = d.eof - d.overflow = 1 << d.width - d.last = decoderInvalidCode + case code == r.clear: + r.width = 1 + uint(r.litWidth) + r.hi = r.eof + r.overflow = 1 << r.width + r.last = decoderInvalidCode continue - case code == d.eof: - d.err = io.EOF + case code == r.eof: + r.err = io.EOF break loop - case code <= d.hi: - c, i := code, len(d.output)-1 - if code == d.hi && d.last != decoderInvalidCode { + case code <= r.hi: + c, i := code, len(r.output)-1 + if code == r.hi && r.last != decoderInvalidCode { // code == hi is a special case which expands to the last expansion // followed by the head of the last expansion. To find the head, we walk // the prefix chain until we find a literal code. - c = d.last - for c >= d.clear { - c = d.prefix[c] + c = r.last + for c >= r.clear { + c = r.prefix[c] } - d.output[i] = uint8(c) + r.output[i] = uint8(c) i-- - c = d.last + c = r.last } // Copy the suffix chain into output and then write that to w. - for c >= d.clear { - d.output[i] = d.suffix[c] + for c >= r.clear { + r.output[i] = r.suffix[c] i-- - c = d.prefix[c] + c = r.prefix[c] } - d.output[i] = uint8(c) - d.o += copy(d.output[d.o:], d.output[i:]) - if d.last != decoderInvalidCode { + r.output[i] = uint8(c) + r.o += copy(r.output[r.o:], r.output[i:]) + if r.last != decoderInvalidCode { // Save what the hi code expands to. - d.suffix[d.hi] = uint8(c) - d.prefix[d.hi] = d.last + r.suffix[r.hi] = uint8(c) + r.prefix[r.hi] = r.last } default: - d.err = errors.New("lzw: invalid code") + r.err = errors.New("lzw: invalid code") break loop } - d.last, d.hi = code, d.hi+1 - if d.hi >= d.overflow { - if d.hi > d.overflow { + r.last, r.hi = code, r.hi+1 + if r.hi >= r.overflow { + if r.hi > r.overflow { panic("unreachable") } - if d.width == maxWidth { - d.last = decoderInvalidCode + if r.width == maxWidth { + r.last = decoderInvalidCode // Undo the d.hi++ a few lines above, so that (1) we maintain // the invariant that d.hi < d.overflow, and (2) d.hi does not // eventually overflow a uint16. - d.hi-- + r.hi-- } else { - d.width++ - d.overflow = 1 << d.width + r.width++ + r.overflow = 1 << r.width } } - if d.o >= flushBuffer { + if r.o >= flushBuffer { break } } // Flush pending output. - d.toRead = d.output[:d.o] - d.o = 0 + r.toRead = r.output[:r.o] + r.o = 0 } var errClosed = errors.New("lzw: reader/writer is closed") -func (d *decoder) Close() error { - d.err = errClosed // in case any Reads come along +// Close closes the Reader and returns an error for any future read operation. +// It does not close the underlying io.Reader. +func (r *Reader) Close() error { + r.err = errClosed // in case any Reads come along return nil } +// Reset clears the Reader's state and allows it to be reused again +// as a new Reader. +func (r *Reader) Reset(src io.Reader, order Order, litWidth int) { + *r = Reader{} + r.init(src, order, litWidth) +} + // NewReader creates a new io.ReadCloser. // Reads from the returned io.ReadCloser read and decompress data from r. // If r does not also implement io.ByteReader, @@ -238,32 +248,43 @@ func (d *decoder) Close() error { // The number of bits to use for literal codes, litWidth, must be in the // range [2,8] and is typically 8. It must equal the litWidth // used during compression. +// +// It is guaranteed that the underlying type of the returned io.ReadCloser +// is a *Reader. func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser { - d := new(decoder) + return newReader(r, order, litWidth) +} + +func newReader(src io.Reader, order Order, litWidth int) *Reader { + r := new(Reader) + r.init(src, order, litWidth) + return r +} + +func (r *Reader) init(src io.Reader, order Order, litWidth int) { switch order { case LSB: - d.read = (*decoder).readLSB + r.read = (*Reader).readLSB case MSB: - d.read = (*decoder).readMSB + r.read = (*Reader).readMSB default: - d.err = errors.New("lzw: unknown order") - return d + r.err = errors.New("lzw: unknown order") + return } if litWidth < 2 || 8 < litWidth { - d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) - return d + r.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth) + return } - if br, ok := r.(io.ByteReader); ok { - d.r = br - } else { - d.r = bufio.NewReader(r) - } - d.litWidth = litWidth - d.width = 1 + uint(litWidth) - d.clear = uint16(1) << uint(litWidth) - d.eof, d.hi = d.clear+1, d.clear+1 - d.overflow = uint16(1) << d.width - d.last = decoderInvalidCode - return d + br, ok := src.(io.ByteReader) + if !ok && src != nil { + br = bufio.NewReader(src) + } + r.r = br + r.litWidth = litWidth + r.width = 1 + uint(litWidth) + r.clear = uint16(1) << uint(litWidth) + r.eof, r.hi = r.clear+1, r.clear+1 + r.overflow = uint16(1) << r.width + r.last = decoderInvalidCode } |