summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/currency/gen.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/currency/gen.go')
-rw-r--r--vendor/golang.org/x/text/currency/gen.go400
1 files changed, 400 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/currency/gen.go b/vendor/golang.org/x/text/currency/gen.go
new file mode 100644
index 0000000..0952d41
--- /dev/null
+++ b/vendor/golang.org/x/text/currency/gen.go
@@ -0,0 +1,400 @@
+// 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
+
+// Generator for currency-related data.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/text/internal"
+ "golang.org/x/text/internal/gen"
+ "golang.org/x/text/internal/tag"
+ "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.")
+ outputFile = flag.String("output", "tables.go", "output file")
+
+ draft = flag.String("draft",
+ "contributed",
+ `Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
+)
+
+func main() {
+ gen.Init()
+
+ gen.Repackage("gen_common.go", "common.go", "currency")
+
+ // Read the CLDR zip file.
+ r := gen.OpenCLDRCoreZip()
+ defer r.Close()
+
+ d := &cldr.Decoder{}
+ d.SetDirFilter("supplemental", "main")
+ d.SetSectionFilter("numbers")
+ data, err := d.DecodeZip(r)
+ if err != nil {
+ log.Fatalf("DecodeZip: %v", err)
+ }
+
+ w := gen.NewCodeWriter()
+ defer w.WriteGoFile(*outputFile, "currency")
+
+ fmt.Fprintln(w, `import "golang.org/x/text/internal/tag"`)
+
+ gen.WriteCLDRVersion(w)
+ b := &builder{}
+ b.genCurrencies(w, data.Supplemental())
+ b.genSymbols(w, data)
+}
+
+var constants = []string{
+ // Undefined and testing.
+ "XXX", "XTS",
+ // G11 currencies https://en.wikipedia.org/wiki/G10_currencies.
+ "USD", "EUR", "JPY", "GBP", "CHF", "AUD", "NZD", "CAD", "SEK", "NOK", "DKK",
+ // Precious metals.
+ "XAG", "XAU", "XPT", "XPD",
+
+ // Additional common currencies as defined by CLDR.
+ "BRL", "CNY", "INR", "RUB", "HKD", "IDR", "KRW", "MXN", "PLN", "SAR",
+ "THB", "TRY", "TWD", "ZAR",
+}
+
+type builder struct {
+ currencies tag.Index
+ numCurrencies int
+}
+
+func (b *builder) genCurrencies(w *gen.CodeWriter, data *cldr.SupplementalData) {
+ // 3-letter ISO currency codes
+ // Start with dummy to let index start at 1.
+ currencies := []string{"\x00\x00\x00\x00"}
+
+ // currency codes
+ for _, reg := range data.CurrencyData.Region {
+ for _, cur := range reg.Currency {
+ currencies = append(currencies, cur.Iso4217)
+ }
+ }
+ // Not included in the list for some reasons:
+ currencies = append(currencies, "MVP")
+
+ sort.Strings(currencies)
+ // Unique the elements.
+ k := 0
+ for i := 1; i < len(currencies); i++ {
+ if currencies[k] != currencies[i] {
+ currencies[k+1] = currencies[i]
+ k++
+ }
+ }
+ currencies = currencies[:k+1]
+
+ // Close with dummy for simpler and faster searching.
+ currencies = append(currencies, "\xff\xff\xff\xff")
+
+ // Write currency values.
+ fmt.Fprintln(w, "const (")
+ for _, c := range constants {
+ index := sort.SearchStrings(currencies, c)
+ fmt.Fprintf(w, "\t%s = %d\n", strings.ToLower(c), index)
+ }
+ fmt.Fprint(w, ")")
+
+ // Compute currency-related data that we merge into the table.
+ for _, info := range data.CurrencyData.Fractions[0].Info {
+ if info.Iso4217 == "DEFAULT" {
+ continue
+ }
+ standard := getRoundingIndex(info.Digits, info.Rounding, 0)
+ cash := getRoundingIndex(info.CashDigits, info.CashRounding, standard)
+
+ index := sort.SearchStrings(currencies, info.Iso4217)
+ currencies[index] += mkCurrencyInfo(standard, cash)
+ }
+
+ // Set default values for entries that weren't touched.
+ for i, c := range currencies {
+ if len(c) == 3 {
+ currencies[i] += mkCurrencyInfo(0, 0)
+ }
+ }
+
+ b.currencies = tag.Index(strings.Join(currencies, ""))
+ w.WriteComment(`
+ currency holds an alphabetically sorted list of canonical 3-letter currency
+ identifiers. Each identifier is followed by a byte of type currencyInfo,
+ defined in gen_common.go.`)
+ w.WriteConst("currency", b.currencies)
+
+ // Hack alert: gofmt indents a trailing comment after an indented string.
+ // Ensure that the next thing written is not a comment.
+ b.numCurrencies = (len(b.currencies) / 4) - 2
+ w.WriteConst("numCurrencies", b.numCurrencies)
+
+ // Create a table that maps regions to currencies.
+ regionToCurrency := []toCurrency{}
+
+ for _, reg := range data.CurrencyData.Region {
+ if len(reg.Iso3166) != 2 {
+ log.Fatalf("Unexpected group %q in region data", reg.Iso3166)
+ }
+ if len(reg.Currency) == 0 {
+ continue
+ }
+ cur := reg.Currency[0]
+ if cur.To != "" || cur.Tender == "false" {
+ continue
+ }
+ regionToCurrency = append(regionToCurrency, toCurrency{
+ region: regionToCode(language.MustParseRegion(reg.Iso3166)),
+ code: uint16(b.currencies.Index([]byte(cur.Iso4217))),
+ })
+ }
+ sort.Sort(byRegion(regionToCurrency))
+
+ w.WriteType(toCurrency{})
+ w.WriteVar("regionToCurrency", regionToCurrency)
+
+ // Create a table that maps regions to currencies.
+ regionData := []regionInfo{}
+
+ for _, reg := range data.CurrencyData.Region {
+ if len(reg.Iso3166) != 2 {
+ log.Fatalf("Unexpected group %q in region data", reg.Iso3166)
+ }
+ for _, cur := range reg.Currency {
+ from, _ := time.Parse("2006-01-02", cur.From)
+ to, _ := time.Parse("2006-01-02", cur.To)
+ code := uint16(b.currencies.Index([]byte(cur.Iso4217)))
+ if cur.Tender == "false" {
+ code |= nonTenderBit
+ }
+ regionData = append(regionData, regionInfo{
+ region: regionToCode(language.MustParseRegion(reg.Iso3166)),
+ code: code,
+ from: toDate(from),
+ to: toDate(to),
+ })
+ }
+ }
+ sort.Stable(byRegionCode(regionData))
+
+ w.WriteType(regionInfo{})
+ w.WriteVar("regionData", regionData)
+}
+
+type regionInfo struct {
+ region uint16
+ code uint16 // 0x8000 not legal tender
+ from uint32
+ to uint32
+}
+
+type byRegionCode []regionInfo
+
+func (a byRegionCode) Len() int { return len(a) }
+func (a byRegionCode) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byRegionCode) Less(i, j int) bool { return a[i].region < a[j].region }
+
+type toCurrency struct {
+ region uint16
+ code uint16
+}
+
+type byRegion []toCurrency
+
+func (a byRegion) Len() int { return len(a) }
+func (a byRegion) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byRegion) Less(i, j int) bool { return a[i].region < a[j].region }
+
+func mkCurrencyInfo(standard, cash int) string {
+ return string([]byte{byte(cash<<cashShift | standard)})
+}
+
+func getRoundingIndex(digits, rounding string, defIndex int) int {
+ round := roundings[defIndex] // default
+
+ if digits != "" {
+ round.scale = parseUint8(digits)
+ }
+ if rounding != "" && rounding != "0" { // 0 means 1 here in CLDR
+ round.increment = parseUint8(rounding)
+ }
+
+ // Will panic if the entry doesn't exist:
+ for i, r := range roundings {
+ if r == round {
+ return i
+ }
+ }
+ log.Fatalf("Rounding entry %#v does not exist.", round)
+ panic("unreachable")
+}
+
+// genSymbols generates the symbols used for currencies. Most symbols are
+// defined in root and there is only very small variation per language.
+// The following rules apply:
+// - A symbol can be requested as normal or narrow.
+// - If a symbol is not defined for a currency, it defaults to its ISO code.
+func (b *builder) genSymbols(w *gen.CodeWriter, data *cldr.CLDR) {
+ d, err := cldr.ParseDraft(*draft)
+ if err != nil {
+ log.Fatalf("filter: %v", err)
+ }
+
+ const (
+ normal = iota
+ narrow
+ numTypes
+ )
+ // language -> currency -> type -> symbol
+ var symbols [language.NumCompactTags][][numTypes]*string
+
+ // Collect symbol information per language.
+ for _, lang := range data.Locales() {
+ ldml := data.RawLDML(lang)
+ if ldml.Numbers == nil || ldml.Numbers.Currencies == nil {
+ continue
+ }
+
+ langIndex, ok := language.CompactIndex(language.MustParse(lang))
+ if !ok {
+ log.Fatalf("No compact index for language %s", lang)
+ }
+
+ symbols[langIndex] = make([][numTypes]*string, b.numCurrencies+1)
+
+ for _, c := range ldml.Numbers.Currencies.Currency {
+ syms := cldr.MakeSlice(&c.Symbol)
+ syms.SelectDraft(d)
+
+ for _, sym := range c.Symbol {
+ v := sym.Data()
+ if v == c.Type {
+ // We define "" to mean the ISO symbol.
+ v = ""
+ }
+ cur := b.currencies.Index([]byte(c.Type))
+ // XXX gets reassigned to 0 in the package's code.
+ if c.Type == "XXX" {
+ cur = 0
+ }
+ if cur == -1 {
+ fmt.Println("Unsupported:", c.Type)
+ continue
+ }
+
+ switch sym.Alt {
+ case "":
+ symbols[langIndex][cur][normal] = &v
+ case "narrow":
+ symbols[langIndex][cur][narrow] = &v
+ }
+ }
+ }
+ }
+
+ // Remove values identical to the parent.
+ for langIndex, data := range symbols {
+ for curIndex, curs := range data {
+ for typ, sym := range curs {
+ if sym == nil {
+ continue
+ }
+ for p := uint16(langIndex); p != 0; {
+ p = internal.Parent[p]
+ x := symbols[p]
+ if x == nil {
+ continue
+ }
+ if v := x[curIndex][typ]; v != nil || p == 0 {
+ // Value is equal to the default value root value is undefined.
+ parentSym := ""
+ if v != nil {
+ parentSym = *v
+ }
+ if parentSym == *sym {
+ // Value is the same as parent.
+ data[curIndex][typ] = nil
+ }
+ break
+ }
+ }
+ }
+ }
+ }
+
+ // Create symbol index.
+ symbolData := []byte{0}
+ symbolLookup := map[string]uint16{"": 0} // 0 means default, so block that value.
+ for _, data := range symbols {
+ for _, curs := range data {
+ for _, sym := range curs {
+ if sym == nil {
+ continue
+ }
+ if _, ok := symbolLookup[*sym]; !ok {
+ symbolLookup[*sym] = uint16(len(symbolData))
+ symbolData = append(symbolData, byte(len(*sym)))
+ symbolData = append(symbolData, *sym...)
+ }
+ }
+ }
+ }
+ w.WriteComment(`
+ symbols holds symbol data of the form <n> <str>, where n is the length of
+ the symbol string str.`)
+ w.WriteConst("symbols", string(symbolData))
+
+ // Create index from language to currency lookup to symbol.
+ type curToIndex struct{ cur, idx uint16 }
+ w.WriteType(curToIndex{})
+
+ prefix := []string{"normal", "narrow"}
+ // Create data for regular and narrow symbol data.
+ for typ := normal; typ <= narrow; typ++ {
+
+ indexes := []curToIndex{} // maps currency to symbol index
+ languages := []uint16{}
+
+ for _, data := range symbols {
+ languages = append(languages, uint16(len(indexes)))
+ for curIndex, curs := range data {
+
+ if sym := curs[typ]; sym != nil {
+ indexes = append(indexes, curToIndex{uint16(curIndex), symbolLookup[*sym]})
+ }
+ }
+ }
+ languages = append(languages, uint16(len(indexes)))
+
+ w.WriteVar(prefix[typ]+"LangIndex", languages)
+ w.WriteVar(prefix[typ]+"SymIndex", indexes)
+ }
+}
+func parseUint8(str string) uint8 {
+ x, err := strconv.ParseUint(str, 10, 8)
+ if err != nil {
+ // Show line number of where this function was called.
+ log.New(os.Stderr, "", log.Lshortfile).Output(2, err.Error())
+ os.Exit(1)
+ }
+ return uint8(x)
+}