aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/ulikunitz/xz/lzma/writer2.go
diff options
context:
space:
mode:
authorAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
committerAlex Pilon <apilon@hashicorp.com>2019-02-22 18:24:37 -0500
commit15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch)
tree255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/ulikunitz/xz/lzma/writer2.go
parent07971ca38143c5faf951d152fba370ddcbe26ad5 (diff)
downloadterraform-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/lzma/writer2.go')
-rw-r--r--vendor/github.com/ulikunitz/xz/lzma/writer2.go305
1 files changed, 305 insertions, 0 deletions
diff --git a/vendor/github.com/ulikunitz/xz/lzma/writer2.go b/vendor/github.com/ulikunitz/xz/lzma/writer2.go
new file mode 100644
index 0000000..7c1afe1
--- /dev/null
+++ b/vendor/github.com/ulikunitz/xz/lzma/writer2.go
@@ -0,0 +1,305 @@
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
5package lzma
6
7import (
8 "bytes"
9 "errors"
10 "io"
11)
12
13// Writer2Config is used to create a Writer2 using parameters.
14type Writer2Config struct {
15 // The properties for the encoding. If the it is nil the value
16 // {LC: 3, LP: 0, PB: 2} will be chosen.
17 Properties *Properties
18 // The capacity of the dictionary. If DictCap is zero, the value
19 // 8 MiB will be chosen.
20 DictCap int
21 // Size of the lookahead buffer; value 0 indicates default size
22 // 4096
23 BufSize int
24 // Match algorithm
25 Matcher MatchAlgorithm
26}
27
28// fill replaces zero values with default values.
29func (c *Writer2Config) fill() {
30 if c.Properties == nil {
31 c.Properties = &Properties{LC: 3, LP: 0, PB: 2}
32 }
33 if c.DictCap == 0 {
34 c.DictCap = 8 * 1024 * 1024
35 }
36 if c.BufSize == 0 {
37 c.BufSize = 4096
38 }
39}
40
41// Verify checks the Writer2Config for correctness. Zero values will be
42// replaced by default values.
43func (c *Writer2Config) Verify() error {
44 c.fill()
45 var err error
46 if c == nil {
47 return errors.New("lzma: WriterConfig is nil")
48 }
49 if c.Properties == nil {
50 return errors.New("lzma: WriterConfig has no Properties set")
51 }
52 if err = c.Properties.verify(); err != nil {
53 return err
54 }
55 if !(MinDictCap <= c.DictCap && int64(c.DictCap) <= MaxDictCap) {
56 return errors.New("lzma: dictionary capacity is out of range")
57 }
58 if !(maxMatchLen <= c.BufSize) {
59 return errors.New("lzma: lookahead buffer size too small")
60 }
61 if c.Properties.LC+c.Properties.LP > 4 {
62 return errors.New("lzma: sum of lc and lp exceeds 4")
63 }
64 if err = c.Matcher.verify(); err != nil {
65 return err
66 }
67 return nil
68}
69
70// Writer2 supports the creation of an LZMA2 stream. But note that
71// written data is buffered, so call Flush or Close to write data to the
72// underlying writer. The Close method writes the end-of-stream marker
73// to the stream. So you may be able to concatenate the output of two
74// writers as long the output of the first writer has only been flushed
75// but not closed.
76//
77// Any change to the fields Properties, DictCap must be done before the
78// first call to Write, Flush or Close.
79type Writer2 struct {
80 w io.Writer
81
82 start *state
83 encoder *encoder
84
85 cstate chunkState
86 ctype chunkType
87
88 buf bytes.Buffer
89 lbw LimitedByteWriter
90}
91
92// NewWriter2 creates an LZMA2 chunk sequence writer with the default
93// parameters and options.
94func NewWriter2(lzma2 io.Writer) (w *Writer2, err error) {
95 return Writer2Config{}.NewWriter2(lzma2)
96}
97
98// NewWriter2 creates a new LZMA2 writer using the given configuration.
99func (c Writer2Config) NewWriter2(lzma2 io.Writer) (w *Writer2, err error) {
100 if err = c.Verify(); err != nil {
101 return nil, err
102 }
103 w = &Writer2{
104 w: lzma2,
105 start: newState(*c.Properties),
106 cstate: start,
107 ctype: start.defaultChunkType(),
108 }
109 w.buf.Grow(maxCompressed)
110 w.lbw = LimitedByteWriter{BW: &w.buf, N: maxCompressed}
111 m, err := c.Matcher.new(c.DictCap)
112 if err != nil {
113 return nil, err
114 }
115 d, err := newEncoderDict(c.DictCap, c.BufSize, m)
116 if err != nil {
117 return nil, err
118 }
119 w.encoder, err = newEncoder(&w.lbw, cloneState(w.start), d, 0)
120 if err != nil {
121 return nil, err
122 }
123 return w, nil
124}
125
126// written returns the number of bytes written to the current chunk
127func (w *Writer2) written() int {
128 if w.encoder == nil {
129 return 0
130 }
131 return int(w.encoder.Compressed()) + w.encoder.dict.Buffered()
132}
133
134// errClosed indicates that the writer is closed.
135var errClosed = errors.New("lzma: writer closed")
136
137// Writes data to LZMA2 stream. Note that written data will be buffered.
138// Use Flush or Close to ensure that data is written to the underlying
139// writer.
140func (w *Writer2) Write(p []byte) (n int, err error) {
141 if w.cstate == stop {
142 return 0, errClosed
143 }
144 for n < len(p) {
145 m := maxUncompressed - w.written()
146 if m <= 0 {
147 panic("lzma: maxUncompressed reached")
148 }
149 var q []byte
150 if n+m < len(p) {
151 q = p[n : n+m]
152 } else {
153 q = p[n:]
154 }
155 k, err := w.encoder.Write(q)
156 n += k
157 if err != nil && err != ErrLimit {
158 return n, err
159 }
160 if err == ErrLimit || k == m {
161 if err = w.flushChunk(); err != nil {
162 return n, err
163 }
164 }
165 }
166 return n, nil
167}
168
169// writeUncompressedChunk writes an uncompressed chunk to the LZMA2
170// stream.
171func (w *Writer2) writeUncompressedChunk() error {
172 u := w.encoder.Compressed()
173 if u <= 0 {
174 return errors.New("lzma: can't write empty uncompressed chunk")
175 }
176 if u > maxUncompressed {
177 panic("overrun of uncompressed data limit")
178 }
179 switch w.ctype {
180 case cLRND:
181 w.ctype = cUD
182 default:
183 w.ctype = cU
184 }
185 w.encoder.state = w.start
186
187 header := chunkHeader{
188 ctype: w.ctype,
189 uncompressed: uint32(u - 1),
190 }
191 hdata, err := header.MarshalBinary()
192 if err != nil {
193 return err
194 }
195 if _, err = w.w.Write(hdata); err != nil {
196 return err
197 }
198 _, err = w.encoder.dict.CopyN(w.w, int(u))
199 return err
200}
201
202// writeCompressedChunk writes a compressed chunk to the underlying
203// writer.
204func (w *Writer2) writeCompressedChunk() error {
205 if w.ctype == cU || w.ctype == cUD {
206 panic("chunk type uncompressed")
207 }
208
209 u := w.encoder.Compressed()
210 if u <= 0 {
211 return errors.New("writeCompressedChunk: empty chunk")
212 }
213 if u > maxUncompressed {
214 panic("overrun of uncompressed data limit")
215 }
216 c := w.buf.Len()
217 if c <= 0 {
218 panic("no compressed data")
219 }
220 if c > maxCompressed {
221 panic("overrun of compressed data limit")
222 }
223 header := chunkHeader{
224 ctype: w.ctype,
225 uncompressed: uint32(u - 1),
226 compressed: uint16(c - 1),
227 props: w.encoder.state.Properties,
228 }
229 hdata, err := header.MarshalBinary()
230 if err != nil {
231 return err
232 }
233 if _, err = w.w.Write(hdata); err != nil {
234 return err
235 }
236 _, err = io.Copy(w.w, &w.buf)
237 return err
238}
239
240// writes a single chunk to the underlying writer.
241func (w *Writer2) writeChunk() error {
242 u := int(uncompressedHeaderLen + w.encoder.Compressed())
243 c := headerLen(w.ctype) + w.buf.Len()
244 if u < c {
245 return w.writeUncompressedChunk()
246 }
247 return w.writeCompressedChunk()
248}
249
250// flushChunk terminates the current chunk. The encoder will be reset
251// to support the next chunk.
252func (w *Writer2) flushChunk() error {
253 if w.written() == 0 {
254 return nil
255 }
256 var err error
257 if err = w.encoder.Close(); err != nil {
258 return err
259 }
260 if err = w.writeChunk(); err != nil {
261 return err
262 }
263 w.buf.Reset()
264 w.lbw.N = maxCompressed
265 if err = w.encoder.Reopen(&w.lbw); err != nil {
266 return err
267 }
268 if err = w.cstate.next(w.ctype); err != nil {
269 return err
270 }
271 w.ctype = w.cstate.defaultChunkType()
272 w.start = cloneState(w.encoder.state)
273 return nil
274}
275
276// Flush writes all buffered data out to the underlying stream. This
277// could result in multiple chunks to be created.
278func (w *Writer2) Flush() error {
279 if w.cstate == stop {
280 return errClosed
281 }
282 for w.written() > 0 {
283 if err := w.flushChunk(); err != nil {
284 return err
285 }
286 }
287 return nil
288}
289
290// Close terminates the LZMA2 stream with an EOS chunk.
291func (w *Writer2) Close() error {
292 if w.cstate == stop {
293 return errClosed
294 }
295 if err := w.Flush(); err != nil {
296 return nil
297 }
298 // write zero byte EOS chunk
299 _, err := w.w.Write([]byte{0})
300 if err != nil {
301 return err
302 }
303 w.cstate = stop
304 return nil
305}