gzip.go 6.8 KB

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