aboutsummaryrefslogblamecommitdiffstats
path: root/Godeps/_workspace/src/golang.org/x/text/language/gen_index.go
blob: eef555cd3a640e39e4d99fe4a32347761846f53b (plain) (tree)

































































































































































                                                                                                 
// 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/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.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() }