golang.org/x/text@v0.14.0/unicode/runenames/gen.go (about) 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. 4 5 //go:build ignore 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 // computed by computeDirectOffsets 22 directOffsets = map[string]int{} 23 directData bytes.Buffer 24 25 // computed by computeEntries 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 // trick the generation code to use the entry type 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 }