]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/ulikunitz/xz/lzma/encoderdict.go
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / ulikunitz / xz / lzma / encoderdict.go
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() }