summaryrefslogtreecommitdiffstats
path: root/src/compress/lzw/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/compress/lzw/reader.go')
-rw-r--r--src/compress/lzw/reader.go290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/compress/lzw/reader.go b/src/compress/lzw/reader.go
new file mode 100644
index 0000000..18df970
--- /dev/null
+++ b/src/compress/lzw/reader.go
@@ -0,0 +1,290 @@
+// Copyright 2011 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 lzw implements the Lempel-Ziv-Welch compressed data format,
+// described in T. A. Welch, “A Technique for High-Performance Data
+// Compression”, Computer, 17(6) (June 1984), pp 8-19.
+//
+// In particular, it implements LZW as used by the GIF and PDF file
+// formats, which means variable-width codes up to 12 bits and the first
+// two non-literal codes are a clear code and an EOF code.
+//
+// The TIFF file format uses a similar but incompatible version of the LZW
+// algorithm. See the golang.org/x/image/tiff/lzw package for an
+// implementation.
+package lzw
+
+// TODO(nigeltao): check that PDF uses LZW in the same way as GIF,
+// modulo LSB/MSB packing order.
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+)
+
+// Order specifies the bit ordering in an LZW data stream.
+type Order int
+
+const (
+ // LSB means Least Significant Bits first, as used in the GIF file format.
+ LSB Order = iota
+ // MSB means Most Significant Bits first, as used in the TIFF and PDF
+ // file formats.
+ MSB
+)
+
+const (
+ maxWidth = 12
+ decoderInvalidCode = 0xffff
+ flushBuffer = 1 << maxWidth
+)
+
+// 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(*Reader) (uint16, error) // readLSB or readMSB
+ litWidth int // width in bits of literal codes
+ err error
+
+ // The first 1<<litWidth codes are literal codes.
+ // The next two codes mean clear and EOF.
+ // Other valid codes are in the range [lo, hi] where lo := clear + 2,
+ // with the upper bound incrementing on each code seen.
+ //
+ // overflow is the code at which hi overflows the code width. It always
+ // equals 1 << width.
+ //
+ // last is the most recently seen code, or decoderInvalidCode.
+ //
+ // An invariant is that hi < overflow.
+ clear, eof, hi, overflow, last uint16
+
+ // Each code c in [lo, hi] expands to two or more bytes. For c != hi:
+ // suffix[c] is the last of these bytes.
+ // prefix[c] is the code for all but the last byte.
+ // This code can either be a literal code or another code in [lo, c).
+ // The c == hi case is a special case.
+ suffix [1 << maxWidth]uint8
+ prefix [1 << maxWidth]uint16
+
+ // output is the temporary output buffer.
+ // Literal codes are accumulated from the start of the buffer.
+ // Non-literal codes decode to a sequence of suffixes that are first
+ // written right-to-left from the end of the buffer before being copied
+ // to the start of the buffer.
+ // It is flushed when it contains >= 1<<maxWidth bytes,
+ // so that there is always room to decode an entire code.
+ output [2 * 1 << maxWidth]byte
+ o int // write index into output
+ toRead []byte // bytes to return from Read
+}
+
+// readLSB returns the next code for "Least Significant Bits first" data.
+func (r *Reader) readLSB() (uint16, error) {
+ for r.nBits < r.width {
+ x, err := r.r.ReadByte()
+ if err != nil {
+ return 0, err
+ }
+ r.bits |= uint32(x) << r.nBits
+ r.nBits += 8
+ }
+ 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 (r *Reader) readMSB() (uint16, error) {
+ for r.nBits < r.width {
+ x, err := r.r.ReadByte()
+ if err != nil {
+ return 0, err
+ }
+ r.bits |= uint32(x) << (24 - r.nBits)
+ r.nBits += 8
+ }
+ code := uint16(r.bits >> (32 - r.width))
+ r.bits <<= r.width
+ r.nBits -= r.width
+ return code, nil
+}
+
+// Read implements io.Reader, reading uncompressed bytes from its underlying Reader.
+func (r *Reader) Read(b []byte) (int, error) {
+ for {
+ if len(r.toRead) > 0 {
+ n := copy(b, r.toRead)
+ r.toRead = r.toRead[n:]
+ return n, nil
+ }
+ if r.err != nil {
+ return 0, r.err
+ }
+ 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 (r *Reader) decode() {
+ // Loop over the code stream, converting codes into decompressed bytes.
+loop:
+ for {
+ code, err := r.read(r)
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ r.err = err
+ break
+ }
+ switch {
+ case code < r.clear:
+ // We have a literal code.
+ r.output[r.o] = uint8(code)
+ r.o++
+ if r.last != decoderInvalidCode {
+ // Save what the hi code expands to.
+ r.suffix[r.hi] = uint8(code)
+ r.prefix[r.hi] = r.last
+ }
+ 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 == r.eof:
+ r.err = io.EOF
+ break loop
+ 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 = r.last
+ for c >= r.clear {
+ c = r.prefix[c]
+ }
+ r.output[i] = uint8(c)
+ i--
+ c = r.last
+ }
+ // Copy the suffix chain into output and then write that to w.
+ for c >= r.clear {
+ r.output[i] = r.suffix[c]
+ i--
+ c = r.prefix[c]
+ }
+ 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.
+ r.suffix[r.hi] = uint8(c)
+ r.prefix[r.hi] = r.last
+ }
+ default:
+ r.err = errors.New("lzw: invalid code")
+ break loop
+ }
+ r.last, r.hi = code, r.hi+1
+ if r.hi >= r.overflow {
+ if r.hi > r.overflow {
+ panic("unreachable")
+ }
+ 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.
+ r.hi--
+ } else {
+ r.width++
+ r.overflow = 1 << r.width
+ }
+ }
+ if r.o >= flushBuffer {
+ break
+ }
+ }
+ // Flush pending output.
+ r.toRead = r.output[:r.o]
+ r.o = 0
+}
+
+var errClosed = errors.New("lzw: reader/writer is closed")
+
+// 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,
+// the decompressor may read more data than necessary 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
+// 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 {
+ 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:
+ r.read = (*Reader).readLSB
+ case MSB:
+ r.read = (*Reader).readMSB
+ default:
+ r.err = errors.New("lzw: unknown order")
+ return
+ }
+ if litWidth < 2 || 8 < litWidth {
+ r.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
+ return
+ }
+
+ 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
+}