...
1 package flate
2
3 import "fmt"
4
5
6
7
8 type fastEncL2 struct {
9 fastGen
10 table [bTableSize]tableEntry
11 }
12
13
14
15 func (e *fastEncL2) Encode(dst *tokens, src []byte) {
16 const (
17 inputMargin = 12 - 1
18 minNonLiteralBlockSize = 1 + 1 + inputMargin
19 hashBytes = 5
20 )
21
22 if debugDeflate && e.cur < 0 {
23 panic(fmt.Sprint("e.cur < 0: ", e.cur))
24 }
25
26
27 for e.cur >= bufferReset {
28 if len(e.hist) == 0 {
29 for i := range e.table[:] {
30 e.table[i] = tableEntry{}
31 }
32 e.cur = maxMatchOffset
33 break
34 }
35
36 minOff := e.cur + int32(len(e.hist)) - maxMatchOffset
37 for i := range e.table[:] {
38 v := e.table[i].offset
39 if v <= minOff {
40 v = 0
41 } else {
42 v = v - e.cur + maxMatchOffset
43 }
44 e.table[i].offset = v
45 }
46 e.cur = maxMatchOffset
47 }
48
49 s := e.addBlock(src)
50
51
52
53 if len(src) < minNonLiteralBlockSize {
54
55
56 dst.n = uint16(len(src))
57 return
58 }
59
60
61 src = e.hist
62 nextEmit := s
63
64
65
66
67 sLimit := int32(len(src) - inputMargin)
68
69
70 cv := load6432(src, s)
71 for {
72
73 const skipLog = 5
74 const doEvery = 2
75
76 nextS := s
77 var candidate tableEntry
78 for {
79 nextHash := hashLen(cv, bTableBits, hashBytes)
80 s = nextS
81 nextS = s + doEvery + (s-nextEmit)>>skipLog
82 if nextS > sLimit {
83 goto emitRemainder
84 }
85 candidate = e.table[nextHash]
86 now := load6432(src, nextS)
87 e.table[nextHash] = tableEntry{offset: s + e.cur}
88 nextHash = hashLen(now, bTableBits, hashBytes)
89
90 offset := s - (candidate.offset - e.cur)
91 if offset < maxMatchOffset && uint32(cv) == load3232(src, candidate.offset-e.cur) {
92 e.table[nextHash] = tableEntry{offset: nextS + e.cur}
93 break
94 }
95
96
97 cv = now
98 s = nextS
99 nextS++
100 candidate = e.table[nextHash]
101 now >>= 8
102 e.table[nextHash] = tableEntry{offset: s + e.cur}
103
104 offset = s - (candidate.offset - e.cur)
105 if offset < maxMatchOffset && uint32(cv) == load3232(src, candidate.offset-e.cur) {
106 break
107 }
108 cv = now
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123 for {
124
125
126
127
128 t := candidate.offset - e.cur
129 l := e.matchlenLong(s+4, t+4, src) + 4
130
131
132 for t > 0 && s > nextEmit && src[t-1] == src[s-1] {
133 s--
134 t--
135 l++
136 }
137 if nextEmit < s {
138 if false {
139 emitLiteral(dst, src[nextEmit:s])
140 } else {
141 for _, v := range src[nextEmit:s] {
142 dst.tokens[dst.n] = token(v)
143 dst.litHist[v]++
144 dst.n++
145 }
146 }
147 }
148
149 dst.AddMatchLong(l, uint32(s-t-baseMatchOffset))
150 s += l
151 nextEmit = s
152 if nextS >= s {
153 s = nextS + 1
154 }
155
156 if s >= sLimit {
157
158 if int(s+l+8) < len(src) {
159 cv := load6432(src, s)
160 e.table[hashLen(cv, bTableBits, hashBytes)] = tableEntry{offset: s + e.cur}
161 }
162 goto emitRemainder
163 }
164
165
166 for i := s - l + 2; i < s-5; i += 7 {
167 x := load6432(src, i)
168 nextHash := hashLen(x, bTableBits, hashBytes)
169 e.table[nextHash] = tableEntry{offset: e.cur + i}
170
171 x >>= 16
172 nextHash = hashLen(x, bTableBits, hashBytes)
173 e.table[nextHash] = tableEntry{offset: e.cur + i + 2}
174
175 x >>= 16
176 nextHash = hashLen(x, bTableBits, hashBytes)
177 e.table[nextHash] = tableEntry{offset: e.cur + i + 4}
178 }
179
180
181
182
183
184
185
186 x := load6432(src, s-2)
187 o := e.cur + s - 2
188 prevHash := hashLen(x, bTableBits, hashBytes)
189 prevHash2 := hashLen(x>>8, bTableBits, hashBytes)
190 e.table[prevHash] = tableEntry{offset: o}
191 e.table[prevHash2] = tableEntry{offset: o + 1}
192 currHash := hashLen(x>>16, bTableBits, hashBytes)
193 candidate = e.table[currHash]
194 e.table[currHash] = tableEntry{offset: o + 2}
195
196 offset := s - (candidate.offset - e.cur)
197 if offset > maxMatchOffset || uint32(x>>16) != load3232(src, candidate.offset-e.cur) {
198 cv = x >> 24
199 s++
200 break
201 }
202 }
203 }
204
205 emitRemainder:
206 if int(nextEmit) < len(src) {
207
208 if dst.n == 0 {
209 return
210 }
211
212 emitLiteral(dst, src[nextEmit:])
213 }
214 }
215
View as plain text