summaryrefslogtreecommitdiff
path: root/libgo/go/compress/lzw/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/compress/lzw/reader.go')
-rw-r--r--libgo/go/compress/lzw/reader.go207
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
}