...
1
2
3
4
5
6
7 package main
8
9 import (
10 "bytes"
11 "log"
12 "sort"
13 "strings"
14
15 "golang.org/x/text/internal/gen"
16 "golang.org/x/text/internal/gen/bitfield"
17 "golang.org/x/text/internal/ucd"
18 )
19
20 var (
21
22 directOffsets = map[string]int{}
23 directData bytes.Buffer
24
25
26 entries []entry
27 singleData bytes.Buffer
28 index []uint16
29 )
30
31 type entry struct {
32 start rune `bitfield:"21,startRune"`
33 numRunes int `bitfield:"16"`
34 end rune
35 index int `bitfield:"16"`
36 base int `bitfield:"6"`
37 direct bool `bitfield:""`
38 name string
39 }
40
41 func main() {
42 gen.Init()
43
44 w := gen.NewCodeWriter()
45 defer w.WriteVersionedGoFile("tables.go", "runenames")
46
47 gen.WriteUnicodeVersion(w)
48
49 computeDirectOffsets()
50 computeEntries()
51
52 if err := bitfield.Gen(w, entry{}, nil); err != nil {
53 log.Fatal(err)
54 }
55
56 type entry uint64
57 packed := []entry{}
58 for _, e := range entries {
59 e.numRunes = int(e.end - e.start + 1)
60 v, err := bitfield.Pack(e, nil)
61 if err != nil {
62 log.Fatal(err)
63 }
64 packed = append(packed, entry(v))
65 }
66
67 index = append(index, uint16(singleData.Len()))
68
69 w.WriteVar("entries", packed)
70 w.WriteVar("index", index)
71 w.WriteConst("directData", directData.String())
72 w.WriteConst("singleData", singleData.String())
73 }
74
75 func computeDirectOffsets() {
76 counts := map[string]int{}
77
78 p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
79 for p.Next() {
80 start, end := p.Range(0)
81 counts[getName(p)] += int(end-start) + 1
82 }
83
84 direct := []string{}
85 for k, v := range counts {
86 if v > 1 {
87 direct = append(direct, k)
88 }
89 }
90 sort.Strings(direct)
91
92 for _, s := range direct {
93 directOffsets[s] = directData.Len()
94 directData.WriteString(s)
95 }
96 }
97
98 func computeEntries() {
99 p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
100 for p.Next() {
101 start, end := p.Range(0)
102
103 last := entry{}
104 if len(entries) > 0 {
105 last = entries[len(entries)-1]
106 }
107
108 name := getName(p)
109 if index, ok := directOffsets[name]; ok {
110 if last.name == name && last.end+1 == start {
111 entries[len(entries)-1].end = end
112 continue
113 }
114 entries = append(entries, entry{
115 start: start,
116 end: end,
117 index: index,
118 base: len(name),
119 direct: true,
120 name: name,
121 })
122 continue
123 }
124
125 if start != end {
126 log.Fatalf("Expected start == end, found %x != %x", start, end)
127 }
128
129 offset := singleData.Len()
130 base := offset >> 16
131 index = append(index, uint16(offset))
132 singleData.WriteString(name)
133
134 if last.base == base && last.end+1 == start {
135 entries[len(entries)-1].end = start
136 continue
137 }
138
139 entries = append(entries, entry{
140 start: start,
141 end: end,
142 index: len(index) - 1,
143 base: base,
144 name: name,
145 })
146 }
147 }
148
149 func getName(p *ucd.Parser) string {
150 s := p.String(ucd.Name)
151 if s == "" {
152 return ""
153 }
154 if s[0] == '<' {
155 const first = ", First>"
156 if i := strings.Index(s, first); i >= 0 {
157 s = s[:i] + ">"
158 }
159
160 }
161 return s
162 }
163
View as plain text