...
Source file src/pkg/compress/flate/deflatefast.go
1
2
3
4
5 package flate
6
7
8
9
10 const (
11 tableBits = 14
12 tableSize = 1 << tableBits
13 tableMask = tableSize - 1
14 tableShift = 32 - tableBits
15 )
16
17 func load32(b []byte, i int32) uint32 {
18 b = b[i : i+4 : len(b)]
19 return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
20 }
21
22 func load64(b []byte, i int32) uint64 {
23 b = b[i : i+8 : len(b)]
24 return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
25 uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
26 }
27
28 func hash(u uint32) uint32 {
29 return (u * 0x1e35a7bd) >> tableShift
30 }
31
32
33
34
35
36 const (
37 inputMargin = 16 - 1
38 minNonLiteralBlockSize = 1 + 1 + inputMargin
39 )
40
41 type tableEntry struct {
42 val uint32
43 offset int32
44 }
45
46
47
48 type deflateFast struct {
49 table [tableSize]tableEntry
50 prev []byte
51 cur int32
52 }
53
54 func newDeflateFast() *deflateFast {
55 return &deflateFast{cur: maxStoreBlockSize, prev: make([]byte, 0, maxStoreBlockSize)}
56 }
57
58
59
60 func (e *deflateFast) encode(dst []token, src []byte) []token {
61
62 if e.cur > 1<<30 {
63 e.resetAll()
64 }
65
66
67
68 if len(src) < minNonLiteralBlockSize {
69 e.cur += maxStoreBlockSize
70 e.prev = e.prev[:0]
71 return emitLiteral(dst, src)
72 }
73
74
75
76
77 sLimit := int32(len(src) - inputMargin)
78
79
80 nextEmit := int32(0)
81 s := int32(0)
82 cv := load32(src, s)
83 nextHash := hash(cv)
84
85 for {
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 skip := int32(32)
102
103 nextS := s
104 var candidate tableEntry
105 for {
106 s = nextS
107 bytesBetweenHashLookups := skip >> 5
108 nextS = s + bytesBetweenHashLookups
109 skip += bytesBetweenHashLookups
110 if nextS > sLimit {
111 goto emitRemainder
112 }
113 candidate = e.table[nextHash&tableMask]
114 now := load32(src, nextS)
115 e.table[nextHash&tableMask] = tableEntry{offset: s + e.cur, val: cv}
116 nextHash = hash(now)
117
118 offset := s - (candidate.offset - e.cur)
119 if offset > maxMatchOffset || cv != candidate.val {
120
121 cv = now
122 continue
123 }
124 break
125 }
126
127
128
129
130 dst = emitLiteral(dst, src[nextEmit:s])
131
132
133
134
135
136
137
138
139
140 for {
141
142
143
144
145
146 s += 4
147 t := candidate.offset - e.cur + 4
148 l := e.matchLen(s, t, src)
149
150
151 dst = append(dst, matchToken(uint32(l+4-baseMatchLength), uint32(s-t-baseMatchOffset)))
152 s += l
153 nextEmit = s
154 if s >= sLimit {
155 goto emitRemainder
156 }
157
158
159
160
161
162
163
164 x := load64(src, s-1)
165 prevHash := hash(uint32(x))
166 e.table[prevHash&tableMask] = tableEntry{offset: e.cur + s - 1, val: uint32(x)}
167 x >>= 8
168 currHash := hash(uint32(x))
169 candidate = e.table[currHash&tableMask]
170 e.table[currHash&tableMask] = tableEntry{offset: e.cur + s, val: uint32(x)}
171
172 offset := s - (candidate.offset - e.cur)
173 if offset > maxMatchOffset || uint32(x) != candidate.val {
174 cv = uint32(x >> 8)
175 nextHash = hash(cv)
176 s++
177 break
178 }
179 }
180 }
181
182 emitRemainder:
183 if int(nextEmit) < len(src) {
184 dst = emitLiteral(dst, src[nextEmit:])
185 }
186 e.cur += int32(len(src))
187 e.prev = e.prev[:len(src)]
188 copy(e.prev, src)
189 return dst
190 }
191
192 func emitLiteral(dst []token, lit []byte) []token {
193 for _, v := range lit {
194 dst = append(dst, literalToken(uint32(v)))
195 }
196 return dst
197 }
198
199
200
201
202 func (e *deflateFast) matchLen(s, t int32, src []byte) int32 {
203 s1 := int(s) + maxMatchLength - 4
204 if s1 > len(src) {
205 s1 = len(src)
206 }
207
208
209 if t >= 0 {
210 b := src[t:]
211 a := src[s:s1]
212 b = b[:len(a)]
213
214 for i := range a {
215 if a[i] != b[i] {
216 return int32(i)
217 }
218 }
219 return int32(len(a))
220 }
221
222
223 tp := int32(len(e.prev)) + t
224 if tp < 0 {
225 return 0
226 }
227
228
229 a := src[s:s1]
230 b := e.prev[tp:]
231 if len(b) > len(a) {
232 b = b[:len(a)]
233 }
234 a = a[:len(b)]
235 for i := range b {
236 if a[i] != b[i] {
237 return int32(i)
238 }
239 }
240
241
242
243 n := int32(len(b))
244 if int(s+n) == s1 {
245 return n
246 }
247
248
249 a = src[s+n : s1]
250 b = src[:len(a)]
251 for i := range a {
252 if a[i] != b[i] {
253 return int32(i) + n
254 }
255 }
256 return int32(len(a)) + n
257 }
258
259
260
261 func (e *deflateFast) reset() {
262 e.prev = e.prev[:0]
263
264 e.cur += maxMatchOffset
265
266
267 if e.cur > 1<<30 {
268 e.resetAll()
269 }
270 }
271
272
273
274
275
276
277 func (e *deflateFast) resetAll() {
278
279
280 e.cur = maxStoreBlockSize
281 e.prev = e.prev[:0]
282 for i := range e.table {
283 e.table[i] = tableEntry{}
284 }
285 }
286
View as plain text