...

Source file src/compress/zlib/reader.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	/*
     6	Package zlib implements reading and writing of zlib format compressed data,
     7	as specified in RFC 1950.
     8	
     9	The implementation provides filters that uncompress during reading
    10	and compress during writing.  For example, to write compressed data
    11	to a buffer:
    12	
    13		var b bytes.Buffer
    14		w := zlib.NewWriter(&b)
    15		w.Write([]byte("hello, world\n"))
    16		w.Close()
    17	
    18	and to read that data back:
    19	
    20		r, err := zlib.NewReader(&b)
    21		io.Copy(os.Stdout, r)
    22		r.Close()
    23	*/
    24	package zlib
    25	
    26	import (
    27		"bufio"
    28		"compress/flate"
    29		"errors"
    30		"hash"
    31		"hash/adler32"
    32		"io"
    33	)
    34	
    35	const zlibDeflate = 8
    36	
    37	var (
    38		// ErrChecksum is returned when reading ZLIB data that has an invalid checksum.
    39		ErrChecksum = errors.New("zlib: invalid checksum")
    40		// ErrDictionary is returned when reading ZLIB data that has an invalid dictionary.
    41		ErrDictionary = errors.New("zlib: invalid dictionary")
    42		// ErrHeader is returned when reading ZLIB data that has an invalid header.
    43		ErrHeader = errors.New("zlib: invalid header")
    44	)
    45	
    46	type reader struct {
    47		r            flate.Reader
    48		decompressor io.ReadCloser
    49		digest       hash.Hash32
    50		err          error
    51		scratch      [4]byte
    52	}
    53	
    54	// Resetter resets a ReadCloser returned by NewReader or NewReaderDict
    55	// to switch to a new underlying Reader. This permits reusing a ReadCloser
    56	// instead of allocating a new one.
    57	type Resetter interface {
    58		// Reset discards any buffered data and resets the Resetter as if it was
    59		// newly initialized with the given reader.
    60		Reset(r io.Reader, dict []byte) error
    61	}
    62	
    63	// NewReader creates a new ReadCloser.
    64	// Reads from the returned ReadCloser read and decompress data from r.
    65	// If r does not implement io.ByteReader, the decompressor may read more
    66	// data than necessary from r.
    67	// It is the caller's responsibility to call Close on the ReadCloser when done.
    68	//
    69	// The ReadCloser returned by NewReader also implements Resetter.
    70	func NewReader(r io.Reader) (io.ReadCloser, error) {
    71		return NewReaderDict(r, nil)
    72	}
    73	
    74	// NewReaderDict is like NewReader but uses a preset dictionary.
    75	// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
    76	// If the compressed data refers to a different dictionary, NewReaderDict returns ErrDictionary.
    77	//
    78	// The ReadCloser returned by NewReaderDict also implements Resetter.
    79	func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
    80		z := new(reader)
    81		err := z.Reset(r, dict)
    82		if err != nil {
    83			return nil, err
    84		}
    85		return z, nil
    86	}
    87	
    88	func (z *reader) Read(p []byte) (int, error) {
    89		if z.err != nil {
    90			return 0, z.err
    91		}
    92	
    93		var n int
    94		n, z.err = z.decompressor.Read(p)
    95		z.digest.Write(p[0:n])
    96		if z.err != io.EOF {
    97			// In the normal case we return here.
    98			return n, z.err
    99		}
   100	
   101		// Finished file; check checksum.
   102		if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
   103			if err == io.EOF {
   104				err = io.ErrUnexpectedEOF
   105			}
   106			z.err = err
   107			return n, z.err
   108		}
   109		// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
   110		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
   111		if checksum != z.digest.Sum32() {
   112			z.err = ErrChecksum
   113			return n, z.err
   114		}
   115		return n, io.EOF
   116	}
   117	
   118	// Calling Close does not close the wrapped io.Reader originally passed to NewReader.
   119	// In order for the ZLIB checksum to be verified, the reader must be
   120	// fully consumed until the io.EOF.
   121	func (z *reader) Close() error {
   122		if z.err != nil && z.err != io.EOF {
   123			return z.err
   124		}
   125		z.err = z.decompressor.Close()
   126		return z.err
   127	}
   128	
   129	func (z *reader) Reset(r io.Reader, dict []byte) error {
   130		*z = reader{decompressor: z.decompressor}
   131		if fr, ok := r.(flate.Reader); ok {
   132			z.r = fr
   133		} else {
   134			z.r = bufio.NewReader(r)
   135		}
   136	
   137		// Read the header (RFC 1950 section 2.2.).
   138		_, z.err = io.ReadFull(z.r, z.scratch[0:2])
   139		if z.err != nil {
   140			if z.err == io.EOF {
   141				z.err = io.ErrUnexpectedEOF
   142			}
   143			return z.err
   144		}
   145		h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
   146		if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
   147			z.err = ErrHeader
   148			return z.err
   149		}
   150		haveDict := z.scratch[1]&0x20 != 0
   151		if haveDict {
   152			_, z.err = io.ReadFull(z.r, z.scratch[0:4])
   153			if z.err != nil {
   154				if z.err == io.EOF {
   155					z.err = io.ErrUnexpectedEOF
   156				}
   157				return z.err
   158			}
   159			checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
   160			if checksum != adler32.Checksum(dict) {
   161				z.err = ErrDictionary
   162				return z.err
   163			}
   164		}
   165	
   166		if z.decompressor == nil {
   167			if haveDict {
   168				z.decompressor = flate.NewReaderDict(z.r, dict)
   169			} else {
   170				z.decompressor = flate.NewReader(z.r)
   171			}
   172		} else {
   173			z.decompressor.(flate.Resetter).Reset(z.r, dict)
   174		}
   175		z.digest = adler32.New()
   176		return nil
   177	}
   178	

View as plain text