gzip.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package flate
  2. import (
  3. "hash/crc32"
  4. "time"
  5. "github.com/andybalholm/brotli/matchfinder"
  6. )
  7. func NewGZIPEncoder() matchfinder.Encoder {
  8. return &gzipEncoder{
  9. f: NewEncoder(),
  10. }
  11. }
  12. type gzipEncoder struct {
  13. f matchfinder.Encoder
  14. length uint32
  15. crc uint32
  16. wroteHeader bool
  17. }
  18. func (g *gzipEncoder) Reset() {
  19. g.f.Reset()
  20. g.length = 0
  21. g.crc = 0
  22. g.wroteHeader = false
  23. }
  24. func appendUint32(dst []byte, n uint32) []byte {
  25. return append(dst,
  26. byte(n),
  27. byte(n>>8),
  28. byte(n>>16),
  29. byte(n>>24),
  30. )
  31. }
  32. func (g *gzipEncoder) Encode(dst []byte, src []byte, matches []matchfinder.Match, lastBlock bool) []byte {
  33. if !g.wroteHeader {
  34. dst = append(dst,
  35. 0x1f, 0x8b, // magic number
  36. 8, // CM = flate
  37. 0, // FLG
  38. )
  39. dst = appendUint32(dst, uint32(time.Now().Unix()))
  40. dst = append(dst,
  41. 0, // XFL
  42. 255, // OS (unspecified)
  43. )
  44. g.wroteHeader = true
  45. }
  46. dst = g.f.Encode(dst, src, matches, lastBlock)
  47. g.length += uint32(len(src))
  48. g.crc = crc32.Update(g.crc, crc32.IEEETable, src)
  49. if lastBlock {
  50. dst = appendUint32(dst, g.crc)
  51. dst = appendUint32(dst, g.length)
  52. }
  53. return dst
  54. }