| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | // 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 ignorepackage 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/internal/gen"	"golang.org/x/text/language"	"golang.org/x/text/unicode/cldr")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() {		// We include all locales unconditionally to be consistent with en_US.		// We want en_US, even though it has no data associated with it.		// TODO: put any of the languages for which no data exists at the end		// of the index. This allows all components based on ICU to use that		// as the cutoff point.		// 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", "-u-va-posix", 1))		m[tag] = true		// }	}	// Include locales for plural rules, which uses a different structure.	for _, plurals := range data.Supplemental().Plurals {		for _, rules := range plurals.PluralRules {			for _, lang := range strings.Split(rules.Locales, " ") {				m[language.Make(lang)] = true			}		}	}	var core, special []language.Tag	for t := range m {		if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" {			log.Fatalf("Unexpected extension %v in %v", x, 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)	// TODO: order by frequency?	sort.Sort(byAlpha(core))	// Size computations are just an estimate.	w.Size += int(reflect.TypeOf(map[uint32]uint16{}).Size())	w.Size += len(core) * 6 // size of uint32 and uint16	fmt.Fprintln(w)	fmt.Fprintln(w, "var coreTags = map[uint32]uint16{")	fmt.Fprintln(w, "0x0: 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()		fmt.Fprintf(w, "0x%s%s%s: %d, // %s\n",			getIndex(b, 3), // 3 is enough as it is guaranteed to be a compact number			getIndex(s, 2),			getIndex(r, 3),			i, t)		i++	}	fmt.Fprintln(w, "}")}// getIndex prints the subtag type and extracts its index of size nibble.// If the index is less than n nibbles, the result is prefixed with 0s.func getIndex(x interface{}, n int) string {	s := fmt.Sprintf("%#v", x) // s is of form Type{typeID: 0x00}	s = s[strings.Index(s, "0x")+2 : len(s)-1]	return strings.Repeat("0", n-len(s)) + s}type byAlpha []language.Tagfunc (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() }
 |