Source file src/pkg/compress/gzip/gzip.go
1
2
3
4
5 package gzip
6
7 import (
8 "compress/flate"
9 "errors"
10 "fmt"
11 "hash"
12 "hash/crc32"
13 "io"
14 )
15
16
17
18 const (
19 NoCompression = flate.NoCompression
20 BestSpeed = flate.BestSpeed
21 BestCompression = flate.BestCompression
22 DefaultCompression = flate.DefaultCompression
23 )
24
25
26
27 type Writer struct {
28 Header
29 w io.Writer
30 level int
31 compressor *flate.Writer
32 digest hash.Hash32
33 size uint32
34 closed bool
35 buf [10]byte
36 err error
37 }
38
39
40
41
42
43
44
45
46
47
48
49
50 func NewWriter(w io.Writer) *Writer {
51 z, _ := NewWriterLevel(w, DefaultCompression)
52 return z
53 }
54
55
56
57
58
59
60
61 func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
62 if level < DefaultCompression || level > BestCompression {
63 return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
64 }
65 return &Writer{
66 Header: Header{
67 OS: 255,
68 },
69 w: w,
70 level: level,
71 digest: crc32.NewIEEE(),
72 }, nil
73 }
74
75
76 func put2(p []byte, v uint16) {
77 p[0] = uint8(v >> 0)
78 p[1] = uint8(v >> 8)
79 }
80
81 func put4(p []byte, v uint32) {
82 p[0] = uint8(v >> 0)
83 p[1] = uint8(v >> 8)
84 p[2] = uint8(v >> 16)
85 p[3] = uint8(v >> 24)
86 }
87
88
89 func (z *Writer) writeBytes(b []byte) error {
90 if len(b) > 0xffff {
91 return errors.New("gzip.Write: Extra data is too large")
92 }
93 put2(z.buf[0:2], uint16(len(b)))
94 _, err := z.w.Write(z.buf[0:2])
95 if err != nil {
96 return err
97 }
98 _, err = z.w.Write(b)
99 return err
100 }
101
102
103
104 func (z *Writer) writeString(s string) (err error) {
105
106 needconv := false
107 for _, v := range s {
108 if v == 0 || v > 0xff {
109 return errors.New("gzip.Write: non-Latin-1 header string")
110 }
111 if v > 0x7f {
112 needconv = true
113 }
114 }
115 if needconv {
116 b := make([]byte, 0, len(s))
117 for _, v := range s {
118 b = append(b, byte(v))
119 }
120 _, err = z.w.Write(b)
121 } else {
122 _, err = io.WriteString(z.w, s)
123 }
124 if err != nil {
125 return err
126 }
127
128 z.buf[0] = 0
129 _, err = z.w.Write(z.buf[0:1])
130 return err
131 }
132
133
134
135 func (z *Writer) Write(p []byte) (int, error) {
136 if z.err != nil {
137 return 0, z.err
138 }
139 var n int
140
141 if z.compressor == nil {
142 z.buf[0] = gzipID1
143 z.buf[1] = gzipID2
144 z.buf[2] = gzipDeflate
145 z.buf[3] = 0
146 if z.Extra != nil {
147 z.buf[3] |= 0x04
148 }
149 if z.Name != "" {
150 z.buf[3] |= 0x08
151 }
152 if z.Comment != "" {
153 z.buf[3] |= 0x10
154 }
155 put4(z.buf[4:8], uint32(z.ModTime.Unix()))
156 if z.level == BestCompression {
157 z.buf[8] = 2
158 } else if z.level == BestSpeed {
159 z.buf[8] = 4
160 } else {
161 z.buf[8] = 0
162 }
163 z.buf[9] = z.OS
164 n, z.err = z.w.Write(z.buf[0:10])
165 if z.err != nil {
166 return n, z.err
167 }
168 if z.Extra != nil {
169 z.err = z.writeBytes(z.Extra)
170 if z.err != nil {
171 return n, z.err
172 }
173 }
174 if z.Name != "" {
175 z.err = z.writeString(z.Name)
176 if z.err != nil {
177 return n, z.err
178 }
179 }
180 if z.Comment != "" {
181 z.err = z.writeString(z.Comment)
182 if z.err != nil {
183 return n, z.err
184 }
185 }
186 z.compressor, _ = flate.NewWriter(z.w, z.level)
187 }
188 z.size += uint32(len(p))
189 z.digest.Write(p)
190 n, z.err = z.compressor.Write(p)
191 return n, z.err
192 }
193
194
195
196
197
198
199
200
201
202 func (z *Writer) Flush() error {
203 if z.err != nil {
204 return z.err
205 }
206 if z.closed {
207 return nil
208 }
209 if z.compressor == nil {
210 z.Write(nil)
211 }
212 z.err = z.compressor.Flush()
213 return z.err
214 }
215
216
217 func (z *Writer) Close() error {
218 if z.err != nil {
219 return z.err
220 }
221 if z.closed {
222 return nil
223 }
224 z.closed = true
225 if z.compressor == nil {
226 z.Write(nil)
227 if z.err != nil {
228 return z.err
229 }
230 }
231 z.err = z.compressor.Close()
232 if z.err != nil {
233 return z.err
234 }
235 put4(z.buf[0:4], z.digest.Sum32())
236 put4(z.buf[4:8], z.size)
237 _, z.err = z.w.Write(z.buf[0:8])
238 return z.err
239 }
View as plain text