diff options
author | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
---|---|---|
committer | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
commit | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/ulikunitz/xz/writer.go | |
parent | 07971ca38143c5faf951d152fba370ddcbe26ad5 (diff) | |
download | terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip |
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/github.com/ulikunitz/xz/writer.go')
-rw-r--r-- | vendor/github.com/ulikunitz/xz/writer.go | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/vendor/github.com/ulikunitz/xz/writer.go b/vendor/github.com/ulikunitz/xz/writer.go new file mode 100644 index 0000000..c126f70 --- /dev/null +++ b/vendor/github.com/ulikunitz/xz/writer.go | |||
@@ -0,0 +1,386 @@ | |||
1 | // Copyright 2014-2017 Ulrich Kunitz. 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 xz | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "hash" | ||
10 | "io" | ||
11 | |||
12 | "github.com/ulikunitz/xz/lzma" | ||
13 | ) | ||
14 | |||
15 | // WriterConfig describe the parameters for an xz writer. | ||
16 | type WriterConfig struct { | ||
17 | Properties *lzma.Properties | ||
18 | DictCap int | ||
19 | BufSize int | ||
20 | BlockSize int64 | ||
21 | // checksum method: CRC32, CRC64 or SHA256 | ||
22 | CheckSum byte | ||
23 | // match algorithm | ||
24 | Matcher lzma.MatchAlgorithm | ||
25 | } | ||
26 | |||
27 | // fill replaces zero values with default values. | ||
28 | func (c *WriterConfig) fill() { | ||
29 | if c.Properties == nil { | ||
30 | c.Properties = &lzma.Properties{LC: 3, LP: 0, PB: 2} | ||
31 | } | ||
32 | if c.DictCap == 0 { | ||
33 | c.DictCap = 8 * 1024 * 1024 | ||
34 | } | ||
35 | if c.BufSize == 0 { | ||
36 | c.BufSize = 4096 | ||
37 | } | ||
38 | if c.BlockSize == 0 { | ||
39 | c.BlockSize = maxInt64 | ||
40 | } | ||
41 | if c.CheckSum == 0 { | ||
42 | c.CheckSum = CRC64 | ||
43 | } | ||
44 | } | ||
45 | |||
46 | // Verify checks the configuration for errors. Zero values will be | ||
47 | // replaced by default values. | ||
48 | func (c *WriterConfig) Verify() error { | ||
49 | if c == nil { | ||
50 | return errors.New("xz: writer configuration is nil") | ||
51 | } | ||
52 | c.fill() | ||
53 | lc := lzma.Writer2Config{ | ||
54 | Properties: c.Properties, | ||
55 | DictCap: c.DictCap, | ||
56 | BufSize: c.BufSize, | ||
57 | Matcher: c.Matcher, | ||
58 | } | ||
59 | if err := lc.Verify(); err != nil { | ||
60 | return err | ||
61 | } | ||
62 | if c.BlockSize <= 0 { | ||
63 | return errors.New("xz: block size out of range") | ||
64 | } | ||
65 | if err := verifyFlags(c.CheckSum); err != nil { | ||
66 | return err | ||
67 | } | ||
68 | return nil | ||
69 | } | ||
70 | |||
71 | // filters creates the filter list for the given parameters. | ||
72 | func (c *WriterConfig) filters() []filter { | ||
73 | return []filter{&lzmaFilter{int64(c.DictCap)}} | ||
74 | } | ||
75 | |||
76 | // maxInt64 defines the maximum 64-bit signed integer. | ||
77 | const maxInt64 = 1<<63 - 1 | ||
78 | |||
79 | // verifyFilters checks the filter list for the length and the right | ||
80 | // sequence of filters. | ||
81 | func verifyFilters(f []filter) error { | ||
82 | if len(f) == 0 { | ||
83 | return errors.New("xz: no filters") | ||
84 | } | ||
85 | if len(f) > 4 { | ||
86 | return errors.New("xz: more than four filters") | ||
87 | } | ||
88 | for _, g := range f[:len(f)-1] { | ||
89 | if g.last() { | ||
90 | return errors.New("xz: last filter is not last") | ||
91 | } | ||
92 | } | ||
93 | if !f[len(f)-1].last() { | ||
94 | return errors.New("xz: wrong last filter") | ||
95 | } | ||
96 | return nil | ||
97 | } | ||
98 | |||
99 | // newFilterWriteCloser converts a filter list into a WriteCloser that | ||
100 | // can be used by a blockWriter. | ||
101 | func (c *WriterConfig) newFilterWriteCloser(w io.Writer, f []filter) (fw io.WriteCloser, err error) { | ||
102 | if err = verifyFilters(f); err != nil { | ||
103 | return nil, err | ||
104 | } | ||
105 | fw = nopWriteCloser(w) | ||
106 | for i := len(f) - 1; i >= 0; i-- { | ||
107 | fw, err = f[i].writeCloser(fw, c) | ||
108 | if err != nil { | ||
109 | return nil, err | ||
110 | } | ||
111 | } | ||
112 | return fw, nil | ||
113 | } | ||
114 | |||
115 | // nopWCloser implements a WriteCloser with a Close method not doing | ||
116 | // anything. | ||
117 | type nopWCloser struct { | ||
118 | io.Writer | ||
119 | } | ||
120 | |||
121 | // Close returns nil and doesn't do anything else. | ||
122 | func (c nopWCloser) Close() error { | ||
123 | return nil | ||
124 | } | ||
125 | |||
126 | // nopWriteCloser converts the Writer into a WriteCloser with a Close | ||
127 | // function that does nothing beside returning nil. | ||
128 | func nopWriteCloser(w io.Writer) io.WriteCloser { | ||
129 | return nopWCloser{w} | ||
130 | } | ||
131 | |||
132 | // Writer compresses data written to it. It is an io.WriteCloser. | ||
133 | type Writer struct { | ||
134 | WriterConfig | ||
135 | |||
136 | xz io.Writer | ||
137 | bw *blockWriter | ||
138 | newHash func() hash.Hash | ||
139 | h header | ||
140 | index []record | ||
141 | closed bool | ||
142 | } | ||
143 | |||
144 | // newBlockWriter creates a new block writer writes the header out. | ||
145 | func (w *Writer) newBlockWriter() error { | ||
146 | var err error | ||
147 | w.bw, err = w.WriterConfig.newBlockWriter(w.xz, w.newHash()) | ||
148 | if err != nil { | ||
149 | return err | ||
150 | } | ||
151 | if err = w.bw.writeHeader(w.xz); err != nil { | ||
152 | return err | ||
153 | } | ||
154 | return nil | ||
155 | } | ||
156 | |||
157 | // closeBlockWriter closes a block writer and records the sizes in the | ||
158 | // index. | ||
159 | func (w *Writer) closeBlockWriter() error { | ||
160 | var err error | ||
161 | if err = w.bw.Close(); err != nil { | ||
162 | return err | ||
163 | } | ||
164 | w.index = append(w.index, w.bw.record()) | ||
165 | return nil | ||
166 | } | ||
167 | |||
168 | // NewWriter creates a new xz writer using default parameters. | ||
169 | func NewWriter(xz io.Writer) (w *Writer, err error) { | ||
170 | return WriterConfig{}.NewWriter(xz) | ||
171 | } | ||
172 | |||
173 | // NewWriter creates a new Writer using the given configuration parameters. | ||
174 | func (c WriterConfig) NewWriter(xz io.Writer) (w *Writer, err error) { | ||
175 | if err = c.Verify(); err != nil { | ||
176 | return nil, err | ||
177 | } | ||
178 | w = &Writer{ | ||
179 | WriterConfig: c, | ||
180 | xz: xz, | ||
181 | h: header{c.CheckSum}, | ||
182 | index: make([]record, 0, 4), | ||
183 | } | ||
184 | if w.newHash, err = newHashFunc(c.CheckSum); err != nil { | ||
185 | return nil, err | ||
186 | } | ||
187 | data, err := w.h.MarshalBinary() | ||
188 | if _, err = xz.Write(data); err != nil { | ||
189 | return nil, err | ||
190 | } | ||
191 | if err = w.newBlockWriter(); err != nil { | ||
192 | return nil, err | ||
193 | } | ||
194 | return w, nil | ||
195 | |||
196 | } | ||
197 | |||
198 | // Write compresses the uncompressed data provided. | ||
199 | func (w *Writer) Write(p []byte) (n int, err error) { | ||
200 | if w.closed { | ||
201 | return 0, errClosed | ||
202 | } | ||
203 | for { | ||
204 | k, err := w.bw.Write(p[n:]) | ||
205 | n += k | ||
206 | if err != errNoSpace { | ||
207 | return n, err | ||
208 | } | ||
209 | if err = w.closeBlockWriter(); err != nil { | ||
210 | return n, err | ||
211 | } | ||
212 | if err = w.newBlockWriter(); err != nil { | ||
213 | return n, err | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | |||
218 | // Close closes the writer and adds the footer to the Writer. Close | ||
219 | // doesn't close the underlying writer. | ||
220 | func (w *Writer) Close() error { | ||
221 | if w.closed { | ||
222 | return errClosed | ||
223 | } | ||
224 | w.closed = true | ||
225 | var err error | ||
226 | if err = w.closeBlockWriter(); err != nil { | ||
227 | return err | ||
228 | } | ||
229 | |||
230 | f := footer{flags: w.h.flags} | ||
231 | if f.indexSize, err = writeIndex(w.xz, w.index); err != nil { | ||
232 | return err | ||
233 | } | ||
234 | data, err := f.MarshalBinary() | ||
235 | if err != nil { | ||
236 | return err | ||
237 | } | ||
238 | if _, err = w.xz.Write(data); err != nil { | ||
239 | return err | ||
240 | } | ||
241 | return nil | ||
242 | } | ||
243 | |||
244 | // countingWriter is a writer that counts all data written to it. | ||
245 | type countingWriter struct { | ||
246 | w io.Writer | ||
247 | n int64 | ||
248 | } | ||
249 | |||
250 | // Write writes data to the countingWriter. | ||
251 | func (cw *countingWriter) Write(p []byte) (n int, err error) { | ||
252 | n, err = cw.w.Write(p) | ||
253 | cw.n += int64(n) | ||
254 | if err == nil && cw.n < 0 { | ||
255 | return n, errors.New("xz: counter overflow") | ||
256 | } | ||
257 | return | ||
258 | } | ||
259 | |||
260 | // blockWriter is writes a single block. | ||
261 | type blockWriter struct { | ||
262 | cxz countingWriter | ||
263 | // mw combines io.WriteCloser w and the hash. | ||
264 | mw io.Writer | ||
265 | w io.WriteCloser | ||
266 | n int64 | ||
267 | blockSize int64 | ||
268 | closed bool | ||
269 | headerLen int | ||
270 | |||
271 | filters []filter | ||
272 | hash hash.Hash | ||
273 | } | ||
274 | |||
275 | // newBlockWriter creates a new block writer. | ||
276 | func (c *WriterConfig) newBlockWriter(xz io.Writer, hash hash.Hash) (bw *blockWriter, err error) { | ||
277 | bw = &blockWriter{ | ||
278 | cxz: countingWriter{w: xz}, | ||
279 | blockSize: c.BlockSize, | ||
280 | filters: c.filters(), | ||
281 | hash: hash, | ||
282 | } | ||
283 | bw.w, err = c.newFilterWriteCloser(&bw.cxz, bw.filters) | ||
284 | if err != nil { | ||
285 | return nil, err | ||
286 | } | ||
287 | bw.mw = io.MultiWriter(bw.w, bw.hash) | ||
288 | return bw, nil | ||
289 | } | ||
290 | |||
291 | // writeHeader writes the header. If the function is called after Close | ||
292 | // the commpressedSize and uncompressedSize fields will be filled. | ||
293 | func (bw *blockWriter) writeHeader(w io.Writer) error { | ||
294 | h := blockHeader{ | ||
295 | compressedSize: -1, | ||
296 | uncompressedSize: -1, | ||
297 | filters: bw.filters, | ||
298 | } | ||
299 | if bw.closed { | ||
300 | h.compressedSize = bw.compressedSize() | ||
301 | h.uncompressedSize = bw.uncompressedSize() | ||
302 | } | ||
303 | data, err := h.MarshalBinary() | ||
304 | if err != nil { | ||
305 | return err | ||
306 | } | ||
307 | if _, err = w.Write(data); err != nil { | ||
308 | return err | ||
309 | } | ||
310 | bw.headerLen = len(data) | ||
311 | return nil | ||
312 | } | ||
313 | |||
314 | // compressed size returns the amount of data written to the underlying | ||
315 | // stream. | ||
316 | func (bw *blockWriter) compressedSize() int64 { | ||
317 | return bw.cxz.n | ||
318 | } | ||
319 | |||
320 | // uncompressedSize returns the number of data written to the | ||
321 | // blockWriter | ||
322 | func (bw *blockWriter) uncompressedSize() int64 { | ||
323 | return bw.n | ||
324 | } | ||
325 | |||
326 | // unpaddedSize returns the sum of the header length, the uncompressed | ||
327 | // size of the block and the hash size. | ||
328 | func (bw *blockWriter) unpaddedSize() int64 { | ||
329 | if bw.headerLen <= 0 { | ||
330 | panic("xz: block header not written") | ||
331 | } | ||
332 | n := int64(bw.headerLen) | ||
333 | n += bw.compressedSize() | ||
334 | n += int64(bw.hash.Size()) | ||
335 | return n | ||
336 | } | ||
337 | |||
338 | // record returns the record for the current stream. Call Close before | ||
339 | // calling this method. | ||
340 | func (bw *blockWriter) record() record { | ||
341 | return record{bw.unpaddedSize(), bw.uncompressedSize()} | ||
342 | } | ||
343 | |||
344 | var errClosed = errors.New("xz: writer already closed") | ||
345 | |||
346 | var errNoSpace = errors.New("xz: no space") | ||
347 | |||
348 | // Write writes uncompressed data to the block writer. | ||
349 | func (bw *blockWriter) Write(p []byte) (n int, err error) { | ||
350 | if bw.closed { | ||
351 | return 0, errClosed | ||
352 | } | ||
353 | |||
354 | t := bw.blockSize - bw.n | ||
355 | if int64(len(p)) > t { | ||
356 | err = errNoSpace | ||
357 | p = p[:t] | ||
358 | } | ||
359 | |||
360 | var werr error | ||
361 | n, werr = bw.mw.Write(p) | ||
362 | bw.n += int64(n) | ||
363 | if werr != nil { | ||
364 | return n, werr | ||
365 | } | ||
366 | return n, err | ||
367 | } | ||
368 | |||
369 | // Close closes the writer. | ||
370 | func (bw *blockWriter) Close() error { | ||
371 | if bw.closed { | ||
372 | return errClosed | ||
373 | } | ||
374 | bw.closed = true | ||
375 | if err := bw.w.Close(); err != nil { | ||
376 | return err | ||
377 | } | ||
378 | s := bw.hash.Size() | ||
379 | k := padLen(bw.cxz.n) | ||
380 | p := make([]byte, k+s) | ||
381 | bw.hash.Sum(p[k:k]) | ||
382 | if _, err := bw.cxz.w.Write(p); err != nil { | ||
383 | return err | ||
384 | } | ||
385 | return nil | ||
386 | } | ||