// 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 import ( "bufio" "errors" "fmt" "io" ) // A writer is a buffered, flushable writer. type writer interface { io.ByteWriter Flush() error } // An errWriteCloser is an io.WriteCloser that always returns a given error. type errWriteCloser struct { err error } func (e *errWriteCloser) Write([]byte) (int, error) { return 0, e.err } func (e *errWriteCloser) Close() error { return e.err } const ( // A code is a 12 bit value, stored as a uint32 when encoding to avoid // type conversions when shifting bits. maxCode = 1<<12 - 1 invalidCode = 1<<32 - 1 // There are 1<<12 possible codes, which is an upper bound on the number of // valid hash table entries at any given point in time. tableSize is 4x that. tableSize = 4 * 1 << 12 tableMask = tableSize - 1 // A hash table entry is a uint32. Zero is an invalid entry since the // lower 12 bits of a valid entry must be a non-literal code. invalidEntry = 0 ) // encoder is LZW compressor. type encoder struct { // w is the writer that compressed bytes are written to. w writer // order, write, bits, nBits and width are the state for // converting a code stream into a byte stream. order Order write func(*encoder, uint32) error bits uint32 nBits uint width uint // litWidth is the width in bits of literal codes. litWidth uint // hi is the code implied by the next code emission. // overflow is the code at which hi overflows the code width. hi, overflow uint32 // savedCode is the accumulated code at the end of the most recent Write // call. It is equal to invalidCode if there was no such call. savedCode uint32 // err is the first error encountered during writing. Closing the encoder // will make any future Write calls return errClosed err error // table is the hash table from 20-bit keys to 12-bit values. Each table // entry contains key<<12|val and collisions resolve by linear probing. // The keys consist of a 12-bit code prefix and an 8-bit byte suffix. // The values are a 12-bit code. table [tableSize]uint32 } // writeLSB writes the code c for "Least Significant Bits first" data. func (e *encoder) writeLSB(c uint32) error { e.bits |= c << e.nBits e.nBits += e.width for e.nBits >= 8 { if err := e.w.WriteByte(uint8(e.bits)); err != nil { return err } e.bits >>= 8 e.nBits -= 8 } return nil } // writeMSB writes the code c for "Most Significant Bits first" data. func (e *encoder) writeMSB(c uint32) error { e.bits |= c << (32 - e.width - e.nBits) e.nBits += e.width for e.nBits >= 8 { if err := e.w.WriteByte(uint8(e.bits >> 24)); err != nil { return err } e.bits <<= 8 e.nBits -= 8 } return nil } // errOutOfCodes is an internal error that means that the encoder has run out // of unused codes and a clear code needs to be sent next. var errOutOfCodes = errors.New("lzw: out of codes") // incHi increments e.hi and checks for both overflow and running out of // unused codes. In the latter case, incHi sends a clear code, resets the // encoder state and returns errOutOfCodes. func (e *encoder) incHi() error { e.hi++ if e.hi == e.overflow { e.width++ e.overflow <<= 1 } if e.hi == maxCode { clear := uint32(1) << e.litWidth if err := e.write(e, clear); err != nil { return err } e.width = e.litWidth + 1 e.hi = clear + 1 e.overflow = clear << 1 for i := range e.table { e.table[i] = invalidEntry } return errOutOfCodes } return nil } // Write writes a compressed representation of p to e's underlying writer. func (e *encoder) Write(p []byte) (n int, err error) { if e.err != nil { return 0, e.err } if len(p) == 0 { return 0, nil } if maxLit := uint8(1<<e.litWidth - 1); maxLit != 0xff { for _, x := range p { if x > maxLit { e.err = errors.New("lzw: input byte too large for the litWidth") return 0, e.err } } } n = len(p) code := e.savedCode if code == invalidCode { // The first code sent is always a literal code. code, p = uint32(p[0]), p[1:] } loop: for _, x := range p { literal := uint32(x) key := code<<8 | literal // If there is a hash table hit for this key then we continue the loop // and do not emit a code yet. hash := (key>>12 ^ key) & tableMask for h, t := hash, e.table[hash]; t != invalidEntry; { if key == t>>12 { code = t & maxCode continue loop } h = (h + 1) & tableMask t = e.table[h] } // Otherwise, write the current code, and literal becomes the start of // the next emitted code. if e.err = e.write(e, code); e.err != nil { return 0, e.err } code = literal // Increment e.hi, the next implied code. If we run out of codes, reset // the encoder state (including clearing the hash table) and continue. if err1 := e.incHi(); err1 != nil { if err1 == errOutOfCodes { continue } e.err = err1 return 0, e.err } // Otherwise, insert key -> e.hi into the map that e.table represents. for { if e.table[hash] == invalidEntry { e.table[hash] = (key << 12) | e.hi break } hash = (hash + 1) & tableMask } } e.savedCode = code return n, nil } // Close closes the encoder, flushing any pending output. It does not close or // flush e's underlying writer. func (e *encoder) Close() error { if e.err != nil { if e.err == errClosed { return nil } return e.err } // Make any future calls to Write return errClosed. e.err = errClosed // Write the savedCode if valid. if e.savedCode != invalidCode { if err := e.write(e, e.savedCode); err != nil { return err } if err := e.incHi(); err != nil && err != errOutOfCodes { return err } } // Write the eof code. eof := uint32(1)<<e.litWidth + 1 if err := e.write(e, eof); err != nil { return err } // Write the final bits. if e.nBits > 0 { if e.order == MSB { e.bits >>= 24 } if err := e.w.WriteByte(uint8(e.bits)); err != nil { return err } } return e.w.Flush() } // 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 // range [2,8] and is typically 8. Input bytes must be less than 1<<litWidth. func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser { var write func(*encoder, uint32) error switch order { case LSB: write = (*encoder).writeLSB case MSB: write = (*encoder).writeMSB default: return &errWriteCloser{errors.New("lzw: unknown order")} } if litWidth < 2 || 8 < litWidth { return &errWriteCloser{fmt.Errorf("lzw: litWidth %d out of range", litWidth)} } bw, ok := w.(writer) if !ok { bw = bufio.NewWriter(w) } lw := uint(litWidth) return &encoder{ w: bw, order: order, write: write, width: 1 + lw, litWidth: lw, hi: 1<<lw + 1, overflow: 1 << (lw + 1), savedCode: invalidCode, } }