1
2
3
4
5 package build
6
7 import (
8 "fmt"
9 "io"
10 "reflect"
11 "sort"
12 "strings"
13
14 "golang.org/x/text/internal/colltab"
15 )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 const (
47 final = 0
48 noIndex = 0xFF
49 )
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 type ctEntry struct {
77 L uint8
78 H uint8
79 N uint8
80 I uint8
81 }
82
83
84
85 type contractTrieSet []struct{ l, h, n, i uint8 }
86
87
88
89 type ctHandle struct {
90 index, n int
91 }
92
93
94
95 func appendTrie(ct *colltab.ContractTrieSet, suffixes []string) (ctHandle, error) {
96 es := make([]stridx, len(suffixes))
97 for i, s := range suffixes {
98 es[i].str = s
99 }
100 sort.Sort(offsetSort(es))
101 for i := range es {
102 es[i].index = i + 1
103 }
104 sort.Sort(genidxSort(es))
105 i := len(*ct)
106 n, err := genStates(ct, es)
107 if err != nil {
108 *ct = (*ct)[:i]
109 return ctHandle{}, err
110 }
111 return ctHandle{i, n}, nil
112 }
113
114
115
116 func genStates(ct *colltab.ContractTrieSet, sis []stridx) (int, error) {
117 if len(sis) == 0 {
118 return 0, fmt.Errorf("genStates: list of suffices must be non-empty")
119 }
120 start := len(*ct)
121
122 for _, si := range sis {
123 s := si.str
124 if len(s) == 0 {
125 continue
126 }
127 added := false
128 c := s[0]
129 if len(s) > 1 {
130 for j := len(*ct) - 1; j >= start; j-- {
131 if (*ct)[j].L == c {
132 added = true
133 break
134 }
135 }
136 if !added {
137 *ct = append(*ct, ctEntry{L: c, I: noIndex})
138 }
139 } else {
140 for j := len(*ct) - 1; j >= start; j-- {
141
142 if (*ct)[j].L == c {
143 (*ct)[j].I = uint8(si.index)
144 added = true
145 }
146
147 if (*ct)[j].H+1 == c {
148 (*ct)[j].H = c
149 added = true
150 }
151 }
152 if !added {
153 *ct = append(*ct, ctEntry{L: c, H: c, N: final, I: uint8(si.index)})
154 }
155 }
156 }
157 n := len(*ct) - start
158
159 sp := 0
160 for i, end := start, len(*ct); i < end; i++ {
161 fe := (*ct)[i]
162 if fe.H == 0 {
163 ln := len(*ct) - start - n
164 if ln > 0xFF {
165 return 0, fmt.Errorf("genStates: relative block offset too large: %d > 255", ln)
166 }
167 fe.H = uint8(ln)
168
169 for ; sis[sp].str[0] != fe.L; sp++ {
170 }
171 se := sp + 1
172 for ; se < len(sis) && len(sis[se].str) > 1 && sis[se].str[0] == fe.L; se++ {
173 }
174 sl := sis[sp:se]
175 sp = se
176 for i, si := range sl {
177 sl[i].str = si.str[1:]
178 }
179 nn, err := genStates(ct, sl)
180 if err != nil {
181 return 0, err
182 }
183 fe.N = uint8(nn)
184 (*ct)[i] = fe
185 }
186 }
187 sort.Sort(entrySort((*ct)[start : start+n]))
188 return n, nil
189 }
190
191
192
193
194 type entrySort colltab.ContractTrieSet
195
196 func (fe entrySort) Len() int { return len(fe) }
197 func (fe entrySort) Swap(i, j int) { fe[i], fe[j] = fe[j], fe[i] }
198 func (fe entrySort) Less(i, j int) bool {
199 return fe[i].L > fe[j].L
200 }
201
202
203 type stridx struct {
204 str string
205 index int
206 }
207
208
209
210
211
212 type offsetSort []stridx
213
214 func (si offsetSort) Len() int { return len(si) }
215 func (si offsetSort) Swap(i, j int) { si[i], si[j] = si[j], si[i] }
216 func (si offsetSort) Less(i, j int) bool {
217 if len(si[i].str) != len(si[j].str) {
218 return len(si[i].str) > len(si[j].str)
219 }
220 return si[i].str < si[j].str
221 }
222
223
224
225 type genidxSort []stridx
226
227 func (si genidxSort) Len() int { return len(si) }
228 func (si genidxSort) Swap(i, j int) { si[i], si[j] = si[j], si[i] }
229 func (si genidxSort) Less(i, j int) bool {
230 if strings.HasPrefix(si[j].str, si[i].str) {
231 return false
232 }
233 if strings.HasPrefix(si[i].str, si[j].str) {
234 return true
235 }
236 return si[i].str < si[j].str
237 }
238
239
240
241 func lookup(ct *colltab.ContractTrieSet, h ctHandle, str []byte) (index, ns int) {
242 states := (*ct)[h.index:]
243 p := 0
244 n := h.n
245 for i := 0; i < n && p < len(str); {
246 e := states[i]
247 c := str[p]
248 if c >= e.L {
249 if e.L == c {
250 p++
251 if e.I != noIndex {
252 index, ns = int(e.I), p
253 }
254 if e.N != final {
255
256 i, states, n = 0, states[int(e.H)+n:], int(e.N)
257 } else {
258 return
259 }
260 continue
261 } else if e.N == final && c <= e.H {
262 p++
263 return int(c-e.L) + int(e.I), p
264 }
265 }
266 i++
267 }
268 return
269 }
270
271
272
273 func print(t *colltab.ContractTrieSet, w io.Writer, name string) (n, size int, err error) {
274 update3 := func(nn, sz int, e error) {
275 n += nn
276 if err == nil {
277 err = e
278 }
279 size += sz
280 }
281 update2 := func(nn int, e error) { update3(nn, 0, e) }
282
283 update3(printArray(*t, w, name))
284 update2(fmt.Fprintf(w, "var %sContractTrieSet = ", name))
285 update3(printStruct(*t, w, name))
286 update2(fmt.Fprintln(w))
287 return
288 }
289
290 func printArray(ct colltab.ContractTrieSet, w io.Writer, name string) (n, size int, err error) {
291 p := func(f string, a ...interface{}) {
292 nn, e := fmt.Fprintf(w, f, a...)
293 n += nn
294 if err == nil {
295 err = e
296 }
297 }
298 size = len(ct) * 4
299 p("// %sCTEntries: %d entries, %d bytes\n", name, len(ct), size)
300 p("var %sCTEntries = [%d]struct{L,H,N,I uint8}{\n", name, len(ct))
301 for _, fe := range ct {
302 p("\t{0x%X, 0x%X, %d, %d},\n", fe.L, fe.H, fe.N, fe.I)
303 }
304 p("}\n")
305 return
306 }
307
308 func printStruct(ct colltab.ContractTrieSet, w io.Writer, name string) (n, size int, err error) {
309 n, err = fmt.Fprintf(w, "colltab.ContractTrieSet( %sCTEntries[:] )", name)
310 size = int(reflect.TypeOf(ct).Size())
311 return
312 }
313
View as plain text