1 // Copyright 2010 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.
16 // These constants are copied from the flate package, so that code that imports
17 // "compress/gzip" does not also have to import "compress/flate".
19 NoCompression
= flate
.NoCompression
20 BestSpeed
= flate
.BestSpeed
21 BestCompression
= flate
.BestCompression
22 DefaultCompression
= flate
.DefaultCompression
25 // A Writer is an io.WriteCloser that satisfies writes by compressing data written
26 // to its wrapped io.Writer.
31 compressor
*flate
.Writer
39 // NewWriter creates a new Writer that satisfies writes by compressing data
42 // It is the caller's responsibility to call Close on the WriteCloser when done.
43 // Writes may be buffered and not flushed until Close.
45 // Callers that wish to set the fields in Writer.Header must do so before
46 // the first call to Write or Close. The Comment and Name header fields are
47 // UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO
48 // 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an
50 func NewWriter(w io
.Writer
) *Writer
{
51 z
, _
:= NewWriterLevel(w
, DefaultCompression
)
55 // NewWriterLevel is like NewWriter but specifies the compression level instead
56 // of assuming DefaultCompression.
58 // The compression level can be DefaultCompression, NoCompression, or any
59 // integer value between BestSpeed and BestCompression inclusive. The error
60 // returned will be nil if the level is valid.
61 func NewWriterLevel(w io
.Writer
, level
int) (*Writer
, error
) {
62 if level
< DefaultCompression || level
> BestCompression
{
63 return nil, fmt
.Errorf("gzip: invalid compression level: %d", level
)
71 digest
: crc32
.NewIEEE(),
75 // GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
76 func put2(p
[]byte, v
uint16) {
81 func put4(p
[]byte, v
uint32) {
88 // writeBytes writes a length-prefixed byte slice to z.w.
89 func (z
*Writer
) writeBytes(b
[]byte) error
{
91 return errors
.New("gzip.Write: Extra data is too large")
93 put2(z
.buf
[0:2], uint16(len(b
)))
94 _
, err
:= z
.w
.Write(z
.buf
[0:2])
102 // writeString writes a UTF-8 string s in GZIP's format to z.w.
103 // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
104 func (z
*Writer
) writeString(s
string) (err error
) {
105 // GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
107 for _
, v
:= range s
{
108 if v
== 0 || v
> 0xff {
109 return errors
.New("gzip.Write: non-Latin-1 header string")
116 b
:= make([]byte, 0, len(s
))
117 for _
, v
:= range s
{
118 b
= append(b
, byte(v
))
120 _
, err
= z
.w
.Write(b
)
122 _
, err
= io
.WriteString(z
.w
, s
)
127 // GZIP strings are NUL-terminated.
129 _
, err
= z
.w
.Write(z
.buf
[0:1])
133 // Write writes a compressed form of p to the underlying io.Writer. The
134 // compressed bytes are not necessarily flushed until the Writer is closed.
135 func (z
*Writer
) Write(p
[]byte) (int, error
) {
140 // Write the GZIP header lazily.
141 if z
.compressor
== nil {
144 z
.buf
[2] = gzipDeflate
155 put4(z
.buf
[4:8], uint32(z
.ModTime
.Unix()))
156 if z
.level
== BestCompression
{
158 } else if z
.level
== BestSpeed
{
164 n
, z
.err
= z
.w
.Write(z
.buf
[0:10])
169 z
.err
= z
.writeBytes(z
.Extra
)
175 z
.err
= z
.writeString(z
.Name
)
181 z
.err
= z
.writeString(z
.Comment
)
186 z
.compressor
, _
= flate
.NewWriter(z
.w
, z
.level
)
188 z
.size
+= uint32(len(p
))
190 n
, z
.err
= z
.compressor
.Write(p
)
194 // Flush flushes any pending compressed data to the underlying writer.
196 // It is useful mainly in compressed network protocols, to ensure that
197 // a remote reader has enough data to reconstruct a packet. Flush does
198 // not return until the data has been written. If the underlying
199 // writer returns an error, Flush returns that error.
201 // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
202 func (z
*Writer
) Flush() error
{
209 if z
.compressor
== nil {
212 z
.err
= z
.compressor
.Flush()
216 // Close closes the Writer. It does not close the underlying io.Writer.
217 func (z
*Writer
) Close() error
{
225 if z
.compressor
== nil {
231 z
.err
= z
.compressor
.Close()
235 put4(z
.buf
[0:4], z
.digest
.Sum32())
236 put4(z
.buf
[4:8], z
.size
)
237 _
, z
.err
= z
.w
.Write(z
.buf
[0:8])