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.
26 // Writes to a Writer are compressed and written to w.
32 compressor
*flate
.Writer
40 // NewWriter returns a new Writer.
41 // Writes to the returned writer are compressed and written to w.
43 // It is the caller's responsibility to call Close on the WriteCloser when done.
44 // Writes may be buffered and not flushed until Close.
46 // Callers that wish to set the fields in Writer.Header must do so before
47 // the first call to Write or Close. The Comment and Name header fields are
48 // UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO
49 // 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an
51 func NewWriter(w io
.Writer
) *Writer
{
52 z
, _
:= NewWriterLevel(w
, DefaultCompression
)
56 // NewWriterLevel is like NewWriter but specifies the compression level instead
57 // of assuming DefaultCompression.
59 // The compression level can be DefaultCompression, NoCompression, or any
60 // integer value between BestSpeed and BestCompression inclusive. The error
61 // returned will be nil if the level is valid.
62 func NewWriterLevel(w io
.Writer
, level
int) (*Writer
, error
) {
63 if level
< DefaultCompression || level
> BestCompression
{
64 return nil, fmt
.Errorf("gzip: invalid compression level: %d", level
)
71 func (z
*Writer
) init(w io
.Writer
, level
int) {
76 digest
= crc32
.NewIEEE()
78 compressor
:= z
.compressor
79 if compressor
!= nil {
89 compressor
: compressor
,
93 // Reset discards the Writer z's state and makes it equivalent to the
94 // result of its original state from NewWriter or NewWriterLevel, but
95 // writing to w instead. This permits reusing a Writer rather than
96 // allocating a new one.
97 func (z
*Writer
) Reset(w io
.Writer
) {
101 // GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
102 func put2(p
[]byte, v
uint16) {
107 func put4(p
[]byte, v
uint32) {
110 p
[2] = uint8(v
>> 16)
111 p
[3] = uint8(v
>> 24)
114 // writeBytes writes a length-prefixed byte slice to z.w.
115 func (z
*Writer
) writeBytes(b
[]byte) error
{
117 return errors
.New("gzip.Write: Extra data is too large")
119 put2(z
.buf
[0:2], uint16(len(b
)))
120 _
, err
:= z
.w
.Write(z
.buf
[0:2])
124 _
, err
= z
.w
.Write(b
)
128 // writeString writes a UTF-8 string s in GZIP's format to z.w.
129 // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
130 func (z
*Writer
) writeString(s
string) (err error
) {
131 // GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
133 for _
, v
:= range s
{
134 if v
== 0 || v
> 0xff {
135 return errors
.New("gzip.Write: non-Latin-1 header string")
142 b
:= make([]byte, 0, len(s
))
143 for _
, v
:= range s
{
144 b
= append(b
, byte(v
))
146 _
, err
= z
.w
.Write(b
)
148 _
, err
= io
.WriteString(z
.w
, s
)
153 // GZIP strings are NUL-terminated.
155 _
, err
= z
.w
.Write(z
.buf
[0:1])
159 // Write writes a compressed form of p to the underlying io.Writer. The
160 // compressed bytes are not necessarily flushed until the Writer is closed.
161 func (z
*Writer
) Write(p
[]byte) (int, error
) {
166 // Write the GZIP header lazily.
171 z
.buf
[2] = gzipDeflate
182 put4(z
.buf
[4:8], uint32(z
.ModTime
.Unix()))
183 if z
.level
== BestCompression
{
185 } else if z
.level
== BestSpeed
{
191 n
, z
.err
= z
.w
.Write(z
.buf
[0:10])
196 z
.err
= z
.writeBytes(z
.Extra
)
202 z
.err
= z
.writeString(z
.Name
)
208 z
.err
= z
.writeString(z
.Comment
)
213 if z
.compressor
== nil {
214 z
.compressor
, _
= flate
.NewWriter(z
.w
, z
.level
)
217 z
.size
+= uint32(len(p
))
219 n
, z
.err
= z
.compressor
.Write(p
)
223 // Flush flushes any pending compressed data to the underlying writer.
225 // It is useful mainly in compressed network protocols, to ensure that
226 // a remote reader has enough data to reconstruct a packet. Flush does
227 // not return until the data has been written. If the underlying
228 // writer returns an error, Flush returns that error.
230 // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
231 func (z
*Writer
) Flush() error
{
244 z
.err
= z
.compressor
.Flush()
248 // Close closes the Writer. It does not close the underlying io.Writer.
249 func (z
*Writer
) Close() error
{
263 z
.err
= z
.compressor
.Close()
267 put4(z
.buf
[0:4], z
.digest
.Sum32())
268 put4(z
.buf
[4:8], z
.size
)
269 _
, z
.err
= z
.w
.Write(z
.buf
[0:8])