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 Package zlib implements reading and writing of zlib format compressed data,
7 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 := zlib.NewWriter(&b)
15 w.Write([]byte("hello, world\n"))
18 and to read that data back:
20 r, err := zlib.NewReader(&b)
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")
48 decompressor io
.ReadCloser
54 // NewReader creates a new io.ReadCloser.
55 // Reads from the returned io.ReadCloser read and decompress data from r.
56 // The implementation buffers input and may read more data than necessary from r.
57 // It is the caller's responsibility to call Close on the ReadCloser when done.
58 func NewReader(r io
.Reader
) (io
.ReadCloser
, error
) {
59 return NewReaderDict(r
, nil)
62 // NewReaderDict is like NewReader but uses a preset dictionary.
63 // NewReaderDict ignores the dictionary if the compressed data does not refer to it.
64 func NewReaderDict(r io
.Reader
, dict
[]byte) (io
.ReadCloser
, error
) {
66 if fr
, ok
:= r
.(flate
.Reader
); ok
{
69 z
.r
= bufio
.NewReader(r
)
71 _
, err
:= io
.ReadFull(z
.r
, z
.scratch
[0:2])
75 h
:= uint(z
.scratch
[0])<<8 |
uint(z
.scratch
[1])
76 if (z
.scratch
[0]&0x0f != zlibDeflate
) ||
(h%31
!= 0) {
79 if z
.scratch
[1]&0x20 != 0 {
80 _
, err
= io
.ReadFull(z
.r
, z
.scratch
[0:4])
84 checksum
:= uint32(z
.scratch
[0])<<24 |
uint32(z
.scratch
[1])<<16 |
uint32(z
.scratch
[2])<<8 |
uint32(z
.scratch
[3])
85 if checksum
!= adler32
.Checksum(dict
) {
86 return nil, ErrDictionary
88 z
.decompressor
= flate
.NewReaderDict(z
.r
, dict
)
90 z
.decompressor
= flate
.NewReader(z
.r
)
92 z
.digest
= adler32
.New()
96 func (z
*reader
) Read(p
[]byte) (n
int, err error
) {
104 n
, err
= z
.decompressor
.Read(p
)
105 z
.digest
.Write(p
[0:n
])
106 if n
!= 0 || err
!= io
.EOF
{
111 // Finished file; check checksum.
112 if _
, err
:= io
.ReadFull(z
.r
, z
.scratch
[0:4]); err
!= nil {
116 // ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
117 checksum
:= uint32(z
.scratch
[0])<<24 |
uint32(z
.scratch
[1])<<16 |
uint32(z
.scratch
[2])<<8 |
uint32(z
.scratch
[3])
118 if checksum
!= z
.digest
.Sum32() {
125 // Calling Close does not close the wrapped io.Reader originally passed to NewReader.
126 func (z
*reader
) Close() error
{
130 z
.err
= z
.decompressor
.Close()