blob: 43c9b82e911750868cf06b780211c699f87ba19e [file] [log] [blame]
// Copyright 2015 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.
// +build ignore
package main
// This file generates derivative tables based on the language package itself.
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"reflect"
"sort"
"strings"
"golang.org/x/text/cldr"
"golang.org/x/text/internal/gen"
"golang.org/x/text/language"
)
var (
test = flag.Bool("test", false,
"test existing tables; can be used to compare web data with package data.")
draft = flag.String("draft",
"contributed",
`Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
)
func main() {
gen.Init()
// Read the CLDR zip file.
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
data, err := d.DecodeZip(r)
if err != nil {
log.Fatalf("DecodeZip: %v", err)
}
w := gen.NewCodeWriter()
defer func() {
buf := &bytes.Buffer{}
if _, err = w.WriteGo(buf, "language"); err != nil {
log.Fatalf("Error formatting file index.go: %v", err)
}
// Since we're generating a table for our own package we need to rewrite
// doing the equivalent of go fmt -r 'language.b -> b'. Using
// bytes.Replace will do.
out := bytes.Replace(buf.Bytes(), []byte("language."), nil, -1)
if err := ioutil.WriteFile("index.go", out, 0600); err != nil {
log.Fatalf("Could not create file index.go: %v", err)
}
}()
m := map[language.Tag]bool{}
for _, lang := range data.Locales() {
if x := data.RawLDML(lang); false ||
x.LocaleDisplayNames != nil ||
x.Characters != nil ||
x.Delimiters != nil ||
x.Measurement != nil ||
x.Dates != nil ||
x.Numbers != nil ||
x.Units != nil ||
x.ListPatterns != nil ||
x.Collations != nil ||
x.Segmentations != nil ||
x.Rbnf != nil ||
x.Annotations != nil ||
x.Metadata != nil {
// TODO: support POSIX natively, albeit non-standard.
tag := language.Make(strings.Replace(lang, "_POSIX", "-x-posix", 1))
m[tag] = true
}
}
var core, special []language.Tag
for t := range m {
// Check we have no extension except -x.
for _, e := range t.Extensions() {
if e.Type() != 'x' {
log.Fatalf("Unexpected extension %q in %v", e.Type(), t)
}
}
if len(t.Variants()) == 0 && len(t.Extensions()) == 0 {
core = append(core, t)
} else {
special = append(special, t)
}
}
w.WriteComment(`
NumCompactTags is the number of common tags. The maximum tag is
NumCompactTags-1.`)
w.WriteConst("NumCompactTags", len(core)+len(special))
sort.Sort(byAlpha(special))
w.WriteVar("specialTags", special)
type coreKey struct {
base language.Base
script language.Script
region language.Region
}
w.WriteType(coreKey{})
// TODO: order by frequency?
sort.Sort(byAlpha(core))
// Size computations are just an estimate.
w.Size += int(reflect.TypeOf(map[coreKey]uint16{}).Size())
w.Size += len(core) * int(reflect.TypeOf(coreKey{}).Size()+2) // 2 is for uint16
fmt.Fprintln(w, "var coreTags = map[coreKey]uint16{")
fmt.Fprintln(w, "coreKey{}: 0, // und")
i := len(special) + 1 // Und and special tags already written.
for _, t := range core {
if t == language.Und {
continue
}
fmt.Fprint(w.Hash, t, i)
b, s, r := t.Raw()
key := fmt.Sprintf("%#v", coreKey{b, s, r})
key = strings.Replace(key[len("main."):], "language.", "", -1)
fmt.Fprintf(w, "%s: %d, // %s\n", key, i, t)
i++
}
fmt.Fprintln(w, "}")
}
type byAlpha []language.Tag
func (a byAlpha) Len() int { return len(a) }
func (a byAlpha) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byAlpha) Less(i, j int) bool { return a[i].String() < a[j].String() }