1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 "golang.org/x/text/internal/gen"
15 "golang.org/x/text/internal/ucd"
18 // snippet is a slice of data; data is the concatenation of all of the names.
25 func makeTable0EntryDirect(rOffset, rLength, dOffset, dLength int) uint64 {
26 if rOffset >= 1<<bitsRuneOffset {
27 log.Fatalf("makeTable0EntryDirect: rOffset %d is too large", rOffset)
29 if rLength >= 1<<bitsRuneLength {
30 log.Fatalf("makeTable0EntryDirect: rLength %d is too large", rLength)
32 if dOffset >= 1<<bitsDataOffset {
33 log.Fatalf("makeTable0EntryDirect: dOffset %d is too large", dOffset)
35 if dLength >= 1<<bitsRuneLength {
36 log.Fatalf("makeTable0EntryDirect: dLength %d is too large", dLength)
38 return uint64(rOffset)<<shiftRuneOffset |
39 uint64(rLength)<<shiftRuneLength |
40 uint64(dOffset)<<shiftDataOffset |
41 uint64(dLength)<<shiftDataLength |
45 func makeTable0EntryIndirect(rOffset, rLength, dBase, t1Offset int) uint64 {
46 if rOffset >= 1<<bitsRuneOffset {
47 log.Fatalf("makeTable0EntryIndirect: rOffset %d is too large", rOffset)
49 if rLength >= 1<<bitsRuneLength {
50 log.Fatalf("makeTable0EntryIndirect: rLength %d is too large", rLength)
52 if dBase >= 1<<bitsDataBase {
53 log.Fatalf("makeTable0EntryIndirect: dBase %d is too large", dBase)
55 if t1Offset >= 1<<bitsTable1Offset {
56 log.Fatalf("makeTable0EntryIndirect: t1Offset %d is too large", t1Offset)
58 return uint64(rOffset)<<shiftRuneOffset |
59 uint64(rLength)<<shiftRuneLength |
60 uint64(dBase)<<shiftDataBase |
61 uint64(t1Offset)<<shiftTable1Offset |
65 func makeTable1Entry(x int) uint16 {
66 if x < 0 || 0xffff < x {
67 log.Fatalf("makeTable1Entry: entry %d is out of range", x)
74 snippets = make([]snippet, 1+unicode.MaxRune)
80 names, counts := parse()
81 appendRepeatNames(names, counts)
82 appendUniqueNames(names, counts)
84 table0, table1 := makeTables()
86 gen.Repackage("gen_bits.go", "bits.go", "runenames")
88 w := gen.NewCodeWriter()
89 w.WriteVar("table0", table0)
90 w.WriteVar("table1", table1)
91 w.WriteConst("data", string(data))
92 w.WriteGoFile("tables.go", "runenames")
95 func parse() (names []string, counts map[string]int) {
96 names = make([]string, 1+unicode.MaxRune)
97 counts = map[string]int{}
98 ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
99 r, s := p.Rune(0), p.String(ucd.Name)
104 const first = ", First>"
105 if i := strings.Index(s, first); i >= 0 {
115 func appendRepeatNames(names []string, counts map[string]int) {
116 alreadySeen := map[string]snippet{}
117 for r, s := range names {
118 if s == "" || counts[s] == 1 {
122 log.Fatalf("Repeated name %q does not start with a '<'", s)
125 if z, ok := alreadySeen[s]; ok {
135 data = append(data, s...)
141 func appendUniqueNames(names []string, counts map[string]int) {
142 for r, s := range names {
143 if s == "" || counts[s] != 1 {
147 log.Fatalf("Unique name %q starts with a '<'", s)
155 data = append(data, s...)
160 func makeTables() (table0 []uint64, table1 []uint16) {
161 for i := 0; i < len(snippets); {
163 if zi == (snippet{}) {
168 // Look for repeat names. If we have one, we only need a table0 entry.
170 for ; j < len(snippets) && zi == snippets[j]; j++ {
173 table0 = append(table0, makeTable0EntryDirect(i, j-i, zi.offset, zi.length))
178 // Otherwise, we have a run of unique names. We need one table0 entry
179 // and two or more table1 entries.
180 base := zi.offset &^ (1<<dataBaseUnit - 1)
181 t1Offset := len(table1) + 1
182 table1 = append(table1, makeTable1Entry(zi.offset-base))
183 table1 = append(table1, makeTable1Entry(zi.offset+zi.length-base))
184 for ; j < len(snippets) && snippets[j] != (snippet{}); j++ {
186 if data[zj.offset] == '<' {
189 table1 = append(table1, makeTable1Entry(zj.offset+zj.length-base))
191 table0 = append(table0, makeTable0EntryIndirect(i, j-i, base>>dataBaseUnit, t1Offset))
194 return table0, table1