diff options
Diffstat (limited to 'vendor/github.com/ulikunitz/xz/lzma/encoderdict.go')
-rw-r--r-- | vendor/github.com/ulikunitz/xz/lzma/encoderdict.go | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/vendor/github.com/ulikunitz/xz/lzma/encoderdict.go b/vendor/github.com/ulikunitz/xz/lzma/encoderdict.go new file mode 100644 index 0000000..9d0fbc7 --- /dev/null +++ b/vendor/github.com/ulikunitz/xz/lzma/encoderdict.go | |||
@@ -0,0 +1,149 @@ | |||
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 lzma | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "fmt" | ||
10 | "io" | ||
11 | ) | ||
12 | |||
13 | // matcher is an interface that supports the identification of the next | ||
14 | // operation. | ||
15 | type matcher interface { | ||
16 | io.Writer | ||
17 | SetDict(d *encoderDict) | ||
18 | NextOp(rep [4]uint32) operation | ||
19 | } | ||
20 | |||
21 | // encoderDict provides the dictionary of the encoder. It includes an | ||
22 | // addtional buffer atop of the actual dictionary. | ||
23 | type encoderDict struct { | ||
24 | buf buffer | ||
25 | m matcher | ||
26 | head int64 | ||
27 | capacity int | ||
28 | // preallocated array | ||
29 | data [maxMatchLen]byte | ||
30 | } | ||
31 | |||
32 | // newEncoderDict creates the encoder dictionary. The argument bufSize | ||
33 | // defines the size of the additional buffer. | ||
34 | func newEncoderDict(dictCap, bufSize int, m matcher) (d *encoderDict, err error) { | ||
35 | if !(1 <= dictCap && int64(dictCap) <= MaxDictCap) { | ||
36 | return nil, errors.New( | ||
37 | "lzma: dictionary capacity out of range") | ||
38 | } | ||
39 | if bufSize < 1 { | ||
40 | return nil, errors.New( | ||
41 | "lzma: buffer size must be larger than zero") | ||
42 | } | ||
43 | d = &encoderDict{ | ||
44 | buf: *newBuffer(dictCap + bufSize), | ||
45 | capacity: dictCap, | ||
46 | m: m, | ||
47 | } | ||
48 | m.SetDict(d) | ||
49 | return d, nil | ||
50 | } | ||
51 | |||
52 | // Discard discards n bytes. Note that n must not be larger than | ||
53 | // MaxMatchLen. | ||
54 | func (d *encoderDict) Discard(n int) { | ||
55 | p := d.data[:n] | ||
56 | k, _ := d.buf.Read(p) | ||
57 | if k < n { | ||
58 | panic(fmt.Errorf("lzma: can't discard %d bytes", n)) | ||
59 | } | ||
60 | d.head += int64(n) | ||
61 | d.m.Write(p) | ||
62 | } | ||
63 | |||
64 | // Len returns the data available in the encoder dictionary. | ||
65 | func (d *encoderDict) Len() int { | ||
66 | n := d.buf.Available() | ||
67 | if int64(n) > d.head { | ||
68 | return int(d.head) | ||
69 | } | ||
70 | return n | ||
71 | } | ||
72 | |||
73 | // DictLen returns the actual length of data in the dictionary. | ||
74 | func (d *encoderDict) DictLen() int { | ||
75 | if d.head < int64(d.capacity) { | ||
76 | return int(d.head) | ||
77 | } | ||
78 | return d.capacity | ||
79 | } | ||
80 | |||
81 | // Available returns the number of bytes that can be written by a | ||
82 | // following Write call. | ||
83 | func (d *encoderDict) Available() int { | ||
84 | return d.buf.Available() - d.DictLen() | ||
85 | } | ||
86 | |||
87 | // Write writes data into the dictionary buffer. Note that the position | ||
88 | // of the dictionary head will not be moved. If there is not enough | ||
89 | // space in the buffer ErrNoSpace will be returned. | ||
90 | func (d *encoderDict) Write(p []byte) (n int, err error) { | ||
91 | m := d.Available() | ||
92 | if len(p) > m { | ||
93 | p = p[:m] | ||
94 | err = ErrNoSpace | ||
95 | } | ||
96 | var e error | ||
97 | if n, e = d.buf.Write(p); e != nil { | ||
98 | err = e | ||
99 | } | ||
100 | return n, err | ||
101 | } | ||
102 | |||
103 | // Pos returns the position of the head. | ||
104 | func (d *encoderDict) Pos() int64 { return d.head } | ||
105 | |||
106 | // ByteAt returns the byte at the given distance. | ||
107 | func (d *encoderDict) ByteAt(distance int) byte { | ||
108 | if !(0 < distance && distance <= d.Len()) { | ||
109 | return 0 | ||
110 | } | ||
111 | i := d.buf.rear - distance | ||
112 | if i < 0 { | ||
113 | i += len(d.buf.data) | ||
114 | } | ||
115 | return d.buf.data[i] | ||
116 | } | ||
117 | |||
118 | // CopyN copies the last n bytes from the dictionary into the provided | ||
119 | // writer. This is used for copying uncompressed data into an | ||
120 | // uncompressed segment. | ||
121 | func (d *encoderDict) CopyN(w io.Writer, n int) (written int, err error) { | ||
122 | if n <= 0 { | ||
123 | return 0, nil | ||
124 | } | ||
125 | m := d.Len() | ||
126 | if n > m { | ||
127 | n = m | ||
128 | err = ErrNoSpace | ||
129 | } | ||
130 | i := d.buf.rear - n | ||
131 | var e error | ||
132 | if i < 0 { | ||
133 | i += len(d.buf.data) | ||
134 | if written, e = w.Write(d.buf.data[i:]); e != nil { | ||
135 | return written, e | ||
136 | } | ||
137 | i = 0 | ||
138 | } | ||
139 | var k int | ||
140 | k, e = w.Write(d.buf.data[i:d.buf.rear]) | ||
141 | written += k | ||
142 | if e != nil { | ||
143 | err = e | ||
144 | } | ||
145 | return written, err | ||
146 | } | ||
147 | |||
148 | // Buffered returns the number of bytes in the buffer. | ||
149 | func (d *encoderDict) Buffered() int { return d.buf.Buffered() } | ||