blob: 4f4a0201aa0030835fd19361c227a27fa3edd477 [file] [log] [blame] [edit]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
import (
"bytes"
"log"
"sort"
"strings"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/gen/bitfield"
"golang.org/x/text/internal/ucd"
)
var (
// computed by computeDirectOffsets
directOffsets = map[string]int{}
directData bytes.Buffer
// computed by computeEntries
entries []entry
singleData bytes.Buffer
index []uint16
)
type entry struct {
start rune `bitfield:"21,startRune"`
numRunes int `bitfield:"16"`
end rune
index int `bitfield:"16"`
base int `bitfield:"6"`
direct bool `bitfield:""`
name string
}
func main() {
gen.Init()
w := gen.NewCodeWriter()
defer w.WriteVersionedGoFile("tables.go", "runenames")
gen.WriteUnicodeVersion(w)
computeDirectOffsets()
computeEntries()
if err := bitfield.Gen(w, entry{}, nil); err != nil {
log.Fatal(err)
}
type entry uint64 // trick the generation code to use the entry type
packed := []entry{}
for _, e := range entries {
e.numRunes = int(e.end - e.start + 1)
v, err := bitfield.Pack(e, nil)
if err != nil {
log.Fatal(err)
}
packed = append(packed, entry(v))
}
index = append(index, uint16(singleData.Len()))
w.WriteVar("entries", packed)
w.WriteVar("index", index)
w.WriteConst("directData", directData.String())
w.WriteConst("singleData", singleData.String())
}
func computeDirectOffsets() {
counts := map[string]int{}
p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
for p.Next() {
start, end := p.Range(0)
counts[getName(p)] += int(end-start) + 1
}
direct := []string{}
for k, v := range counts {
if v > 1 {
direct = append(direct, k)
}
}
sort.Strings(direct)
for _, s := range direct {
directOffsets[s] = directData.Len()
directData.WriteString(s)
}
}
func computeEntries() {
p := ucd.New(gen.OpenUCDFile("UnicodeData.txt"), ucd.KeepRanges)
for p.Next() {
start, end := p.Range(0)
last := entry{}
if len(entries) > 0 {
last = entries[len(entries)-1]
}
name := getName(p)
if index, ok := directOffsets[name]; ok {
if last.name == name && last.end+1 == start {
entries[len(entries)-1].end = end
continue
}
entries = append(entries, entry{
start: start,
end: end,
index: index,
base: len(name),
direct: true,
name: name,
})
continue
}
if start != end {
log.Fatalf("Expected start == end, found %x != %x", start, end)
}
offset := singleData.Len()
base := offset >> 16
index = append(index, uint16(offset))
singleData.WriteString(name)
if last.base == base && last.end+1 == start {
entries[len(entries)-1].end = start
continue
}
entries = append(entries, entry{
start: start,
end: end,
index: len(index) - 1,
base: base,
name: name,
})
}
}
func getName(p *ucd.Parser) string {
s := p.String(ucd.Name)
if s == "" {
return ""
}
if s[0] == '<' {
const first = ", First>"
if i := strings.Index(s, first); i >= 0 {
s = s[:i] + ">"
}
}
return s
}