1
2
3
4
5
6
7 package main
8
9 import (
10 "os"
11 "strings"
12 )
13
14 func main() {
15 f, err := os.Create("../inflate_gen.go")
16 if err != nil {
17 panic(err)
18 }
19 defer f.Close()
20 types := []string{"*bytes.Buffer", "*bytes.Reader", "*bufio.Reader", "*strings.Reader", "Reader"}
21 names := []string{"BytesBuffer", "BytesReader", "BufioReader", "StringsReader", "GenericReader"}
22 imports := []string{"bytes", "bufio", "fmt", "strings", "math/bits"}
23 f.WriteString(`// Code generated by go generate gen_inflate.go. DO NOT EDIT.
24
25 package flate
26
27 import (
28 `)
29
30 for _, imp := range imports {
31 f.WriteString("\t\"" + imp + "\"\n")
32 }
33 f.WriteString(")\n\n")
34
35 template := `
36
37 // Decode a single Huffman block from f.
38 // hl and hd are the Huffman states for the lit/length values
39 // and the distance values, respectively. If hd == nil, using the
40 // fixed distance encoding associated with fixed Huffman blocks.
41 func (f *decompressor) $FUNCNAME$() {
42 const (
43 stateInit = iota // Zero value must be stateInit
44 stateDict
45 )
46 fr := f.r.($TYPE$)
47
48 // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
49 // but is smart enough to keep local variables in registers, so use nb and b,
50 // inline call to moreBits and reassign b,nb back to f on return.
51 fnb, fb, dict := f.nb, f.b, &f.dict
52
53 switch f.stepState {
54 case stateInit:
55 goto readLiteral
56 case stateDict:
57 goto copyHistory
58 }
59
60 readLiteral:
61 // Read literal and/or (length, distance) according to RFC section 3.2.3.
62 {
63 var v int
64 {
65 // Inlined v, err := f.huffSym(f.hl)
66 // Since a huffmanDecoder can be empty or be composed of a degenerate tree
67 // with single element, huffSym must error on these two edge cases. In both
68 // cases, the chunks slice will be 0 for the invalid sequence, leading it
69 // satisfy the n == 0 check below.
70 n := uint(f.hl.maxRead)
71 for {
72 for fnb < n {
73 c, err := fr.ReadByte()
74 if err != nil {
75 f.b, f.nb = fb, fnb
76 f.err = noEOF(err)
77 return
78 }
79 f.roffset++
80 fb |= uint32(c) << (fnb & regSizeMaskUint32)
81 fnb += 8
82 }
83 chunk := f.hl.chunks[fb&(huffmanNumChunks-1)]
84 n = uint(chunk & huffmanCountMask)
85 if n > huffmanChunkBits {
86 chunk = f.hl.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hl.linkMask]
87 n = uint(chunk & huffmanCountMask)
88 }
89 if n <= fnb {
90 if n == 0 {
91 f.b, f.nb = fb, fnb
92 if debugDecode {
93 fmt.Println("huffsym: n==0")
94 }
95 f.err = CorruptInputError(f.roffset)
96 return
97 }
98 fb = fb >> (n & regSizeMaskUint32)
99 fnb = fnb - n
100 v = int(chunk >> huffmanValueShift)
101 break
102 }
103 }
104 }
105
106 var length int
107 switch {
108 case v < 256:
109 dict.writeByte(byte(v))
110 if dict.availWrite() == 0 {
111 f.toRead = dict.readFlush()
112 f.step = $FUNCNAME$
113 f.stepState = stateInit
114 f.b, f.nb = fb, fnb
115 return
116 }
117 goto readLiteral
118 case v == 256:
119 f.b, f.nb = fb, fnb
120 f.finishBlock()
121 return
122 // otherwise, reference to older data
123 case v < 265:
124 length = v - (257 - 3)
125 case v < maxNumLit:
126 val := decCodeToLen[(v - 257)]
127 length = int(val.length) + 3
128 n := uint(val.extra)
129 for fnb < n {
130 c, err := fr.ReadByte()
131 if err != nil {
132 f.b, f.nb = fb, fnb
133 if debugDecode {
134 fmt.Println("morebits n>0:", err)
135 }
136 f.err = err
137 return
138 }
139 f.roffset++
140 fb |= uint32(c) << (fnb®SizeMaskUint32)
141 fnb += 8
142 }
143 length += int(fb & bitMask32[n])
144 fb >>= n & regSizeMaskUint32
145 fnb -= n
146 default:
147 if debugDecode {
148 fmt.Println(v, ">= maxNumLit")
149 }
150 f.err = CorruptInputError(f.roffset)
151 f.b, f.nb = fb, fnb
152 return
153 }
154
155 var dist uint32
156 if f.hd == nil {
157 for fnb < 5 {
158 c, err := fr.ReadByte()
159 if err != nil {
160 f.b, f.nb = fb, fnb
161 if debugDecode {
162 fmt.Println("morebits f.nb<5:", err)
163 }
164 f.err = err
165 return
166 }
167 f.roffset++
168 fb |= uint32(c) << (fnb®SizeMaskUint32)
169 fnb += 8
170 }
171 dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3)))
172 fb >>= 5
173 fnb -= 5
174 } else {
175 // Since a huffmanDecoder can be empty or be composed of a degenerate tree
176 // with single element, huffSym must error on these two edge cases. In both
177 // cases, the chunks slice will be 0 for the invalid sequence, leading it
178 // satisfy the n == 0 check below.
179 n := uint(f.hd.maxRead)
180 // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
181 // but is smart enough to keep local variables in registers, so use nb and b,
182 // inline call to moreBits and reassign b,nb back to f on return.
183 for {
184 for fnb < n {
185 c, err := fr.ReadByte()
186 if err != nil {
187 f.b, f.nb = fb, fnb
188 f.err = noEOF(err)
189 return
190 }
191 f.roffset++
192 fb |= uint32(c) << (fnb & regSizeMaskUint32)
193 fnb += 8
194 }
195 chunk := f.hd.chunks[fb&(huffmanNumChunks-1)]
196 n = uint(chunk & huffmanCountMask)
197 if n > huffmanChunkBits {
198 chunk = f.hd.links[chunk>>huffmanValueShift][(fb>>huffmanChunkBits)&f.hd.linkMask]
199 n = uint(chunk & huffmanCountMask)
200 }
201 if n <= fnb {
202 if n == 0 {
203 f.b, f.nb = fb, fnb
204 if debugDecode {
205 fmt.Println("huffsym: n==0")
206 }
207 f.err = CorruptInputError(f.roffset)
208 return
209 }
210 fb = fb >> (n & regSizeMaskUint32)
211 fnb = fnb - n
212 dist = uint32(chunk >> huffmanValueShift)
213 break
214 }
215 }
216 }
217
218 switch {
219 case dist < 4:
220 dist++
221 case dist < maxNumDist:
222 nb := uint(dist-2) >> 1
223 // have 1 bit in bottom of dist, need nb more.
224 extra := (dist & 1) << (nb & regSizeMaskUint32)
225 for fnb < nb {
226 c, err := fr.ReadByte()
227 if err != nil {
228 f.b, f.nb = fb, fnb
229 if debugDecode {
230 fmt.Println("morebits f.nb<nb:", err)
231 }
232 f.err = err
233 return
234 }
235 f.roffset++
236 fb |= uint32(c) << (fnb®SizeMaskUint32)
237 fnb += 8
238 }
239 extra |= fb & bitMask32[nb]
240 fb >>= nb & regSizeMaskUint32
241 fnb -= nb
242 dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra
243 // slower: dist = bitMask32[nb+1] + 2 + extra
244 default:
245 f.b, f.nb = fb, fnb
246 if debugDecode {
247 fmt.Println("dist too big:", dist, maxNumDist)
248 }
249 f.err = CorruptInputError(f.roffset)
250 return
251 }
252
253 // No check on length; encoding can be prescient.
254 if dist > uint32(dict.histSize()) {
255 f.b, f.nb = fb, fnb
256 if debugDecode {
257 fmt.Println("dist > dict.histSize():", dist, dict.histSize())
258 }
259 f.err = CorruptInputError(f.roffset)
260 return
261 }
262
263 f.copyLen, f.copyDist = length, int(dist)
264 goto copyHistory
265 }
266
267 copyHistory:
268 // Perform a backwards copy according to RFC section 3.2.3.
269 {
270 cnt := dict.tryWriteCopy(f.copyDist, f.copyLen)
271 if cnt == 0 {
272 cnt = dict.writeCopy(f.copyDist, f.copyLen)
273 }
274 f.copyLen -= cnt
275
276 if dict.availWrite() == 0 || f.copyLen > 0 {
277 f.toRead = dict.readFlush()
278 f.step = $FUNCNAME$ // We need to continue this work
279 f.stepState = stateDict
280 f.b, f.nb = fb, fnb
281 return
282 }
283 goto readLiteral
284 }
285 // Not reached
286 }
287
288 `
289 for i, t := range types {
290 s := strings.Replace(template, "$FUNCNAME$", "huffman"+names[i], -1)
291 s = strings.Replace(s, "$TYPE$", t, -1)
292 f.WriteString(s)
293 }
294 f.WriteString("func (f *decompressor) huffmanBlockDecoder() {\n")
295 f.WriteString("\tswitch f.r.(type) {\n")
296 for i, t := range types {
297 f.WriteString("\t\tcase " + t + ":\n")
298 f.WriteString("\t\t\tf.huffman" + names[i] + "()\n")
299 }
300 f.WriteString("\t\tdefault:\n")
301 f.WriteString("\t\t\tf.huffmanGenericReader()\n")
302 f.WriteString("\t}\n}\n")
303 }
304
View as plain text