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
23 HuffmanOnly
= flate
.HuffmanOnly
26 // A Writer is an io.WriteCloser.
27 // Writes to a Writer are compressed and written to w.
29 Header
// written at first call to Write, Flush, or Close
33 compressor
*flate
.Writer
34 digest
uint32 // CRC-32, IEEE polynomial (section 8)
35 size
uint32 // Uncompressed size (section 2.3.1)
41 // NewWriter returns a new Writer.
42 // Writes to the returned writer are compressed and written to w.
44 // It is the caller's responsibility to call Close on the Writer when done.
45 // Writes may be buffered and not flushed until Close.
47 // Callers that wish to set the fields in Writer.Header must do so before
48 // the first call to Write, Flush, or Close.
49 func NewWriter(w io
.Writer
) *Writer
{
50 z
, _
:= NewWriterLevel(w
, DefaultCompression
)
54 // NewWriterLevel is like NewWriter but specifies the compression level instead
55 // of assuming DefaultCompression.
57 // The compression level can be DefaultCompression, NoCompression, HuffmanOnly
58 // or any integer value between BestSpeed and BestCompression inclusive.
59 // The error returned will be nil if the level is valid.
60 func NewWriterLevel(w io
.Writer
, level
int) (*Writer
, error
) {
61 if level
< HuffmanOnly || level
> BestCompression
{
62 return nil, fmt
.Errorf("gzip: invalid compression level: %d", level
)
69 func (z
*Writer
) init(w io
.Writer
, level
int) {
70 compressor
:= z
.compressor
71 if compressor
!= nil {
80 compressor
: compressor
,
84 // Reset discards the Writer z's state and makes it equivalent to the
85 // result of its original state from NewWriter or NewWriterLevel, but
86 // writing to w instead. This permits reusing a Writer rather than
87 // allocating a new one.
88 func (z
*Writer
) Reset(w io
.Writer
) {
92 // writeBytes writes a length-prefixed byte slice to z.w.
93 func (z
*Writer
) writeBytes(b
[]byte) error
{
95 return errors
.New("gzip.Write: Extra data is too large")
97 le
.PutUint16(z
.buf
[:2], uint16(len(b
)))
98 _
, err
:= z
.w
.Write(z
.buf
[:2])
102 _
, err
= z
.w
.Write(b
)
106 // writeString writes a UTF-8 string s in GZIP's format to z.w.
107 // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1).
108 func (z
*Writer
) writeString(s
string) (err error
) {
109 // GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII.
111 for _
, v
:= range s
{
112 if v
== 0 || v
> 0xff {
113 return errors
.New("gzip.Write: non-Latin-1 header string")
120 b
:= make([]byte, 0, len(s
))
121 for _
, v
:= range s
{
122 b
= append(b
, byte(v
))
124 _
, err
= z
.w
.Write(b
)
126 _
, err
= io
.WriteString(z
.w
, s
)
131 // GZIP strings are NUL-terminated.
133 _
, err
= z
.w
.Write(z
.buf
[:1])
137 // Write writes a compressed form of p to the underlying io.Writer. The
138 // compressed bytes are not necessarily flushed until the Writer is closed.
139 func (z
*Writer
) Write(p
[]byte) (int, error
) {
144 // Write the GZIP header lazily.
147 z
.buf
= [10]byte{0: gzipID1
, 1: gzipID2
, 2: gzipDeflate
}
157 if z
.ModTime
.After(time
.Unix(0, 0)) {
158 // Section 2.3.1, the zero value for MTIME means that the
159 // modified time is not set.
160 le
.PutUint32(z
.buf
[4:8], uint32(z
.ModTime
.Unix()))
162 if z
.level
== BestCompression
{
164 } else if z
.level
== BestSpeed
{
168 _
, z
.err
= z
.w
.Write(z
.buf
[:10])
173 z
.err
= z
.writeBytes(z
.Extra
)
179 z
.err
= z
.writeString(z
.Name
)
185 z
.err
= z
.writeString(z
.Comment
)
190 if z
.compressor
== nil {
191 z
.compressor
, _
= flate
.NewWriter(z
.w
, z
.level
)
194 z
.size
+= uint32(len(p
))
195 z
.digest
= crc32
.Update(z
.digest
, crc32
.IEEETable
, p
)
196 n
, z
.err
= z
.compressor
.Write(p
)
200 // Flush flushes any pending compressed data to the underlying writer.
202 // It is useful mainly in compressed network protocols, to ensure that
203 // a remote reader has enough data to reconstruct a packet. Flush does
204 // not return until the data has been written. If the underlying
205 // writer returns an error, Flush returns that error.
207 // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
208 func (z
*Writer
) Flush() error
{
221 z
.err
= z
.compressor
.Flush()
225 // Close closes the Writer by flushing any unwritten data to the underlying
226 // io.Writer and writing the GZIP footer.
227 // It does not close the underlying io.Writer.
228 func (z
*Writer
) Close() error
{
242 z
.err
= z
.compressor
.Close()
246 le
.PutUint32(z
.buf
[:4], z
.digest
)
247 le
.PutUint32(z
.buf
[4:8], z
.size
)
248 _
, z
.err
= z
.w
.Write(z
.buf
[:8])