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