gzip.go (6940B)
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. 4 5 package gzip 6 7 import ( 8 "errors" 9 "fmt" 10 "hash/crc32" 11 "io" 12 13 "github.com/klauspost/compress/flate" 14 ) 15 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". 18 const ( 19 NoCompression = flate.NoCompression 20 BestSpeed = flate.BestSpeed 21 BestCompression = flate.BestCompression 22 DefaultCompression = flate.DefaultCompression 23 ConstantCompression = flate.ConstantCompression 24 HuffmanOnly = flate.HuffmanOnly 25 26 // StatelessCompression will do compression but without maintaining any state 27 // between Write calls. 28 // There will be no memory kept between Write calls, 29 // but compression and speed will be suboptimal. 30 // Because of this, the size of actual Write calls will affect output size. 31 StatelessCompression = -3 32 ) 33 34 // A Writer is an io.WriteCloser. 35 // Writes to a Writer are compressed and written to w. 36 type Writer struct { 37 Header // written at first call to Write, Flush, or Close 38 w io.Writer 39 level int 40 err error 41 compressor *flate.Writer 42 digest uint32 // CRC-32, IEEE polynomial (section 8) 43 size uint32 // Uncompressed size (section 2.3.1) 44 wroteHeader bool 45 closed bool 46 buf [10]byte 47 } 48 49 // NewWriter returns a new Writer. 50 // Writes to the returned writer are compressed and written to w. 51 // 52 // It is the caller's responsibility to call Close on the WriteCloser when done. 53 // Writes may be buffered and not flushed until Close. 54 // 55 // Callers that wish to set the fields in Writer.Header must do so before 56 // the first call to Write, Flush, or Close. 57 func NewWriter(w io.Writer) *Writer { 58 z, _ := NewWriterLevel(w, DefaultCompression) 59 return z 60 } 61 62 // NewWriterLevel is like NewWriter but specifies the compression level instead 63 // of assuming DefaultCompression. 64 // 65 // The compression level can be DefaultCompression, NoCompression, or any 66 // integer value between BestSpeed and BestCompression inclusive. The error 67 // returned will be nil if the level is valid. 68 func NewWriterLevel(w io.Writer, level int) (*Writer, error) { 69 if level < StatelessCompression || level > BestCompression { 70 return nil, fmt.Errorf("gzip: invalid compression level: %d", level) 71 } 72 z := new(Writer) 73 z.init(w, level) 74 return z, nil 75 } 76 77 func (z *Writer) init(w io.Writer, level int) { 78 compressor := z.compressor 79 if level != StatelessCompression { 80 if compressor != nil { 81 compressor.Reset(w) 82 } 83 } 84 85 *z = Writer{ 86 Header: Header{ 87 OS: 255, // unknown 88 }, 89 w: w, 90 level: level, 91 compressor: compressor, 92 } 93 } 94 95 // Reset discards the Writer z's state and makes it equivalent to the 96 // result of its original state from NewWriter or NewWriterLevel, but 97 // writing to w instead. This permits reusing a Writer rather than 98 // allocating a new one. 99 func (z *Writer) Reset(w io.Writer) { 100 z.init(w, z.level) 101 } 102 103 // writeBytes writes a length-prefixed byte slice to z.w. 104 func (z *Writer) writeBytes(b []byte) error { 105 if len(b) > 0xffff { 106 return errors.New("gzip.Write: Extra data is too large") 107 } 108 le.PutUint16(z.buf[:2], uint16(len(b))) 109 _, err := z.w.Write(z.buf[:2]) 110 if err != nil { 111 return err 112 } 113 _, err = z.w.Write(b) 114 return err 115 } 116 117 // writeString writes a UTF-8 string s in GZIP's format to z.w. 118 // GZIP (RFC 1952) specifies that strings are NUL-terminated ISO 8859-1 (Latin-1). 119 func (z *Writer) writeString(s string) (err error) { 120 // GZIP stores Latin-1 strings; error if non-Latin-1; convert if non-ASCII. 121 needconv := false 122 for _, v := range s { 123 if v == 0 || v > 0xff { 124 return errors.New("gzip.Write: non-Latin-1 header string") 125 } 126 if v > 0x7f { 127 needconv = true 128 } 129 } 130 if needconv { 131 b := make([]byte, 0, len(s)) 132 for _, v := range s { 133 b = append(b, byte(v)) 134 } 135 _, err = z.w.Write(b) 136 } else { 137 _, err = io.WriteString(z.w, s) 138 } 139 if err != nil { 140 return err 141 } 142 // GZIP strings are NUL-terminated. 143 z.buf[0] = 0 144 _, err = z.w.Write(z.buf[:1]) 145 return err 146 } 147 148 // Write writes a compressed form of p to the underlying io.Writer. The 149 // compressed bytes are not necessarily flushed until the Writer is closed. 150 func (z *Writer) Write(p []byte) (int, error) { 151 if z.err != nil { 152 return 0, z.err 153 } 154 var n int 155 // Write the GZIP header lazily. 156 if !z.wroteHeader { 157 z.wroteHeader = true 158 z.buf[0] = gzipID1 159 z.buf[1] = gzipID2 160 z.buf[2] = gzipDeflate 161 z.buf[3] = 0 162 if z.Extra != nil { 163 z.buf[3] |= 0x04 164 } 165 if z.Name != "" { 166 z.buf[3] |= 0x08 167 } 168 if z.Comment != "" { 169 z.buf[3] |= 0x10 170 } 171 le.PutUint32(z.buf[4:8], uint32(z.ModTime.Unix())) 172 if z.level == BestCompression { 173 z.buf[8] = 2 174 } else if z.level == BestSpeed { 175 z.buf[8] = 4 176 } else { 177 z.buf[8] = 0 178 } 179 z.buf[9] = z.OS 180 n, z.err = z.w.Write(z.buf[:10]) 181 if z.err != nil { 182 return n, z.err 183 } 184 if z.Extra != nil { 185 z.err = z.writeBytes(z.Extra) 186 if z.err != nil { 187 return n, z.err 188 } 189 } 190 if z.Name != "" { 191 z.err = z.writeString(z.Name) 192 if z.err != nil { 193 return n, z.err 194 } 195 } 196 if z.Comment != "" { 197 z.err = z.writeString(z.Comment) 198 if z.err != nil { 199 return n, z.err 200 } 201 } 202 203 if z.compressor == nil && z.level != StatelessCompression { 204 z.compressor, _ = flate.NewWriter(z.w, z.level) 205 } 206 } 207 z.size += uint32(len(p)) 208 z.digest = crc32.Update(z.digest, crc32.IEEETable, p) 209 if z.level == StatelessCompression { 210 return len(p), flate.StatelessDeflate(z.w, p, false, nil) 211 } 212 n, z.err = z.compressor.Write(p) 213 return n, z.err 214 } 215 216 // Flush flushes any pending compressed data to the underlying writer. 217 // 218 // It is useful mainly in compressed network protocols, to ensure that 219 // a remote reader has enough data to reconstruct a packet. Flush does 220 // not return until the data has been written. If the underlying 221 // writer returns an error, Flush returns that error. 222 // 223 // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. 224 func (z *Writer) Flush() error { 225 if z.err != nil { 226 return z.err 227 } 228 if z.closed || z.level == StatelessCompression { 229 return nil 230 } 231 if !z.wroteHeader { 232 z.Write(nil) 233 if z.err != nil { 234 return z.err 235 } 236 } 237 z.err = z.compressor.Flush() 238 return z.err 239 } 240 241 // Close closes the Writer, flushing any unwritten data to the underlying 242 // io.Writer, but does not close the underlying io.Writer. 243 func (z *Writer) Close() error { 244 if z.err != nil { 245 return z.err 246 } 247 if z.closed { 248 return nil 249 } 250 z.closed = true 251 if !z.wroteHeader { 252 z.Write(nil) 253 if z.err != nil { 254 return z.err 255 } 256 } 257 if z.level == StatelessCompression { 258 z.err = flate.StatelessDeflate(z.w, nil, true, nil) 259 } else { 260 z.err = z.compressor.Close() 261 } 262 if z.err != nil { 263 return z.err 264 } 265 le.PutUint32(z.buf[:4], z.digest) 266 le.PutUint32(z.buf[4:8], z.size) 267 _, z.err = z.w.Write(z.buf[:8]) 268 return z.err 269 }