summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/internal/cldrtree/generate.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/internal/cldrtree/generate.go')
-rw-r--r--vendor/golang.org/x/text/internal/cldrtree/generate.go208
1 files changed, 208 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/internal/cldrtree/generate.go b/vendor/golang.org/x/text/internal/cldrtree/generate.go
new file mode 100644
index 0000000..0f0b5f3
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/cldrtree/generate.go
@@ -0,0 +1,208 @@
+// Copyright 2017 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.
+
+package cldrtree
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "golang.org/x/text/internal/gen"
+)
+
+func generate(b *Builder, t *Tree, w *gen.CodeWriter) error {
+ fmt.Fprintln(w, `import "golang.org/x/text/internal/cldrtree"`)
+ fmt.Fprintln(w)
+
+ fmt.Fprintf(w, "var tree = &cldrtree.Tree{locales, indices, buckets}\n\n")
+
+ w.WriteComment("Path values:\n" + b.stats())
+ fmt.Fprintln(w)
+
+ // Generate enum types.
+ for _, e := range b.enums {
+ // Build enum types.
+ w.WriteComment("%s specifies a property of a CLDR field.", e.name)
+ fmt.Fprintf(w, "type %s uint16\n", e.name)
+ }
+
+ d, err := getEnumData(b)
+ if err != nil {
+ return err
+ }
+ fmt.Fprintln(w, "const (")
+ for i, k := range d.keys {
+ fmt.Fprintf(w, "%s %s = %d // %s\n", toCamel(k), d.enums[i], d.m[k], k)
+ }
+ fmt.Fprintln(w, ")")
+
+ w.WriteVar("locales", t.Locales)
+ w.WriteVar("indices", t.Indices)
+
+ // Generate string buckets.
+ fmt.Fprintln(w, "var buckets = []string{")
+ for i := range t.Buckets {
+ fmt.Fprintf(w, "bucket%d,\n", i)
+ }
+ fmt.Fprint(w, "}\n\n")
+ w.Size += int(reflect.TypeOf("").Size()) * len(t.Buckets)
+
+ // Generate string buckets.
+ for i, bucket := range t.Buckets {
+ w.WriteVar(fmt.Sprint("bucket", i), bucket)
+ }
+ return nil
+}
+
+func generateTestData(b *Builder, w *gen.CodeWriter) error {
+ d, err := getEnumData(b)
+ if err != nil {
+ return err
+ }
+
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "var enumMap = map[string]uint16{")
+ fmt.Fprintln(w, `"": 0,`)
+ for _, k := range d.keys {
+ fmt.Fprintf(w, "%q: %d,\n", k, d.m[k])
+ }
+ fmt.Fprintln(w, "}")
+ return nil
+}
+
+func toCamel(s string) string {
+ p := strings.Split(s, "-")
+ for i, s := range p[1:] {
+ p[i+1] = strings.Title(s)
+ }
+ return strings.Replace(strings.Join(p, ""), "/", "", -1)
+}
+
+func (b *Builder) stats() string {
+ w := &bytes.Buffer{}
+
+ b.rootMeta.validate()
+ for _, es := range b.enums {
+ fmt.Fprintf(w, "<%s>\n", es.name)
+ printEnumValues(w, es, 1, nil)
+ }
+ fmt.Fprintln(w)
+ printEnums(w, b.rootMeta.typeInfo, 0)
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "Nr elem: ", len(b.strToBucket))
+ fmt.Fprintln(w, "uniqued size: ", b.size)
+ fmt.Fprintln(w, "total string size: ", b.sizeAll)
+ fmt.Fprintln(w, "bucket waste: ", b.bucketWaste)
+
+ return w.String()
+}
+
+func printEnums(w io.Writer, s *typeInfo, indent int) {
+ idStr := strings.Repeat(" ", indent) + "- "
+ e := s.enum
+ if e == nil {
+ if len(s.entries) > 0 {
+ panic(fmt.Errorf("has entries but no enum values: %#v", s.entries))
+ }
+ return
+ }
+ if e.name != "" {
+ fmt.Fprintf(w, "%s<%s>\n", idStr, e.name)
+ } else {
+ printEnumValues(w, e, indent, s)
+ }
+ if s.sharedKeys() {
+ for _, v := range s.entries {
+ printEnums(w, v, indent+1)
+ break
+ }
+ }
+}
+
+func printEnumValues(w io.Writer, e *enum, indent int, info *typeInfo) {
+ idStr := strings.Repeat(" ", indent) + "- "
+ for i := 0; i < len(e.keys); i++ {
+ fmt.Fprint(w, idStr)
+ k := e.keys[i]
+ if u, err := strconv.ParseUint(k, 10, 16); err == nil {
+ fmt.Fprintf(w, "%s", k)
+ // Skip contiguous integers
+ var v, last uint64
+ for i++; i < len(e.keys); i++ {
+ k = e.keys[i]
+ if v, err = strconv.ParseUint(k, 10, 16); err != nil {
+ break
+ }
+ last = v
+ }
+ if u < last {
+ fmt.Fprintf(w, `..%d`, last)
+ }
+ fmt.Fprintln(w)
+ if err != nil {
+ fmt.Fprintf(w, "%s%s\n", idStr, k)
+ }
+ } else if k == "" {
+ fmt.Fprintln(w, `""`)
+ } else {
+ fmt.Fprintf(w, "%s\n", k)
+ }
+ if info != nil && !info.sharedKeys() {
+ if e := info.entries[enumIndex(i)]; e != nil {
+ printEnums(w, e, indent+1)
+ }
+ }
+ }
+}
+
+func getEnumData(b *Builder) (*enumData, error) {
+ d := &enumData{m: map[string]int{}}
+ if errStr := d.insert(b.rootMeta.typeInfo); errStr != "" {
+ // TODO: consider returning the error.
+ return nil, fmt.Errorf("cldrtree: %s", errStr)
+ }
+ return d, nil
+}
+
+type enumData struct {
+ m map[string]int
+ keys []string
+ enums []string
+}
+
+func (d *enumData) insert(t *typeInfo) (errStr string) {
+ e := t.enum
+ if e == nil {
+ return ""
+ }
+ for i, k := range e.keys {
+ if _, err := strconv.ParseUint(k, 10, 16); err == nil {
+ // We don't include any enum that has integer values.
+ break
+ }
+ if v, ok := d.m[k]; ok {
+ if v != i {
+ return fmt.Sprintf("%q has value %d and %d", k, i, v)
+ }
+ } else {
+ d.m[k] = i
+ if k != "" {
+ d.keys = append(d.keys, k)
+ d.enums = append(d.enums, e.name)
+ }
+ }
+ }
+ for i := range t.enum.keys {
+ if e := t.entries[enumIndex(i)]; e != nil {
+ if errStr := d.insert(e); errStr != "" {
+ return fmt.Sprintf("%q>%v", t.enum.keys[i], errStr)
+ }
+ }
+ }
+ return ""
+}