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.
6 The zlib package implements reading and writing of zlib
7 format compressed data, as specified in RFC 1950.
9 The implementation provides filters that uncompress during reading
10 and compress during writing. For example, to write compressed data
14 w, err := zlib.NewWriter(&b)
15 w.Write([]byte("hello, world\n"))
18 and to read that data back:
20 r, err := zlib.NewReader(&b)
37 var ChecksumError os.Error = os.ErrorString("zlib checksum error")
38 var HeaderError os.Error = os.ErrorString("invalid zlib header")
39 var UnsupportedError os.Error = os.ErrorString("unsupported zlib format")
43 decompressor io.ReadCloser
49 // NewReader creates a new io.ReadCloser that satisfies reads by decompressing data read from r.
50 // The implementation buffers input and may read more data than necessary from r.
51 // It is the caller's responsibility to call Close on the ReadCloser when done.
52 func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
54 if fr, ok := r.(flate.Reader); ok {
57 z.r = bufio.NewReader(r)
59 _, err := io.ReadFull(z.r, z.scratch[0:2])
63 h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
64 if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
65 return nil, HeaderError
67 if z.scratch[1]&0x20 != 0 {
68 // BUG(nigeltao): The zlib package does not implement the FDICT flag.
69 return nil, UnsupportedError
71 z.digest = adler32.New()
72 z.decompressor = flate.NewReader(z.r)
76 func (z *reader) Read(p []byte) (n int, err os.Error) {
84 n, err = z.decompressor.Read(p)
85 z.digest.Write(p[0:n])
86 if n != 0 || err != os.EOF {
91 // Finished file; check checksum.
92 if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
96 // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
97 checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
98 if checksum != z.digest.Sum32() {
105 // Calling Close does not close the wrapped io.Reader originally passed to NewReader.
106 func (z *reader) Close() os.Error {
110 z.err = z.decompressor.Close()