1
2
3
4
5 package flate
6
7 import (
8 "math/bits"
9 )
10
11 const (
12
13 tableBits = 15
14
15
16 tableSize = 1 << tableBits
17
18
19 hashLongBytes = 7
20
21
22 baseMatchOffset = 1
23
24
25 baseMatchLength = 3
26
27
28 maxMatchOffset = 1 << 15
29
30
31 allocHistory = maxStoreBlockSize * 5
32
33
34 bufferReset = (1 << 31) - allocHistory - maxStoreBlockSize - 1
35 )
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 type fastEnc interface {
51
52 encode(dst *tokens, src []byte)
53
54 reset()
55 }
56
57
58 func newFastEnc(level int) fastEnc {
59 switch level {
60 case 1:
61 return &fastEncL1{fastGen: fastGen{cur: maxStoreBlockSize}}
62 case 2:
63 return &fastEncL2{fastGen: fastGen{cur: maxStoreBlockSize}}
64 case 3:
65 return &fastEncL3{fastGen: fastGen{cur: maxStoreBlockSize}}
66 case 4:
67 return &fastEncL4{fastGen: fastGen{cur: maxStoreBlockSize}}
68 case 5:
69 return &fastEncL5{fastGen: fastGen{cur: maxStoreBlockSize}}
70 case 6:
71 return &fastEncL6{fastGen: fastGen{cur: maxStoreBlockSize}}
72 default:
73 panic("invalid level specified")
74 }
75 }
76
77
78
79
80 type fastGen struct {
81 hist []byte
82 cur int32
83 }
84
85
86 func (e *fastGen) addBlock(src []byte) int32 {
87
88 if len(e.hist)+len(src) > cap(e.hist) {
89 if cap(e.hist) == 0 {
90 e.hist = make([]byte, 0, allocHistory)
91 } else {
92 if cap(e.hist) < maxMatchOffset*2 {
93 panic("unexpected buffer size")
94 }
95
96 offset := int32(len(e.hist)) - maxMatchOffset
97 copy(e.hist[0:maxMatchOffset], e.hist[offset:offset+maxMatchOffset])
98 e.cur += offset
99 e.hist = e.hist[:maxMatchOffset]
100 }
101 }
102 s := int32(len(e.hist))
103 e.hist = append(e.hist, src...)
104 return s
105 }
106
107
108
109
110 func (e *fastGen) matchLenLimited(s, t int, src []byte) int32 {
111 a := src[s:min(s+maxMatchLength-4, len(src))]
112 b := src[t:]
113 return int32(matchLen(a, b))
114 }
115
116
117
118 func (e *fastGen) matchLenLong(s, t int, src []byte) int32 {
119 return int32(matchLen(src[s:], src[t:]))
120 }
121
122
123 func (e *fastGen) reset() {
124 if cap(e.hist) < allocHistory {
125 e.hist = make([]byte, 0, allocHistory)
126 }
127
128
129 if e.cur <= bufferReset {
130 e.cur += maxMatchOffset + int32(len(e.hist))
131 }
132 e.hist = e.hist[:0]
133 }
134
135 func (f *fastGen) getFastGen() *fastGen { return f }
136
137
138 type tableEntry struct {
139 offset int32
140 }
141
142
143 type tableEntryPrev struct {
144 cur tableEntry
145 prev tableEntry
146 }
147
148 const (
149 prime3bytes = 506832829
150 prime4bytes = 2654435761
151 prime5bytes = 889523592379
152 prime6bytes = 227718039650203
153 prime7bytes = 58295818150454627
154 prime8bytes = 0xcf1bbcdcb7a56463
155 )
156
157
158
159
160
161 func hashLen(u uint64, b, n uint8) uint32 {
162 switch n {
163 case 3:
164 return (uint32(u<<8) * prime3bytes) >> (32 - b)
165 case 5:
166 return uint32(((u << (64 - 40)) * prime5bytes) >> (64 - b))
167 case 6:
168 return uint32(((u << (64 - 48)) * prime6bytes) >> (64 - b))
169 case 7:
170 return uint32(((u << (64 - 56)) * prime7bytes) >> (64 - b))
171 case 8:
172 return uint32((u * prime8bytes) >> (64 - b))
173 default:
174 return (uint32(u) * prime4bytes) >> (32 - b)
175 }
176 }
177
178
179
180 func matchLen(a, b []byte) (n int) {
181 left := len(a)
182 for left >= 8 {
183 diff := loadLE64(a, n) ^ loadLE64(b, n)
184 if diff != 0 {
185 return n + bits.TrailingZeros64(diff)>>3
186 }
187 n += 8
188 left -= 8
189 }
190
191 a = a[n:]
192 b = b[n:]
193 b = b[:len(a)]
194 for i := range a {
195 if a[i] != b[i] {
196 break
197 }
198 n++
199 }
200 return n
201 }
202
View as plain text