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