github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/text/language/gen_index.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build ignore 6 7 package main 8 9 // This file generates derivative tables based on the language package itself. 10 11 import ( 12 "bytes" 13 "flag" 14 "fmt" 15 "io/ioutil" 16 "log" 17 "reflect" 18 "sort" 19 "strings" 20 21 "golang.org/x/text/internal/gen" 22 "golang.org/x/text/language" 23 "golang.org/x/text/unicode/cldr" 24 ) 25 26 var ( 27 test = flag.Bool("test", false, 28 "test existing tables; can be used to compare web data with package data.") 29 30 draft = flag.String("draft", 31 "contributed", 32 `Minimal draft requirements (approved, contributed, provisional, unconfirmed).`) 33 ) 34 35 func main() { 36 gen.Init() 37 38 // Read the CLDR zip file. 39 r := gen.OpenCLDRCoreZip() 40 defer r.Close() 41 42 d := &cldr.Decoder{} 43 data, err := d.DecodeZip(r) 44 if err != nil { 45 log.Fatalf("DecodeZip: %v", err) 46 } 47 48 w := gen.NewCodeWriter() 49 defer func() { 50 buf := &bytes.Buffer{} 51 52 if _, err = w.WriteGo(buf, "language"); err != nil { 53 log.Fatalf("Error formatting file index.go: %v", err) 54 } 55 56 // Since we're generating a table for our own package we need to rewrite 57 // doing the equivalent of go fmt -r 'language.b -> b'. Using 58 // bytes.Replace will do. 59 out := bytes.Replace(buf.Bytes(), []byte("language."), nil, -1) 60 if err := ioutil.WriteFile("index.go", out, 0600); err != nil { 61 log.Fatalf("Could not create file index.go: %v", err) 62 } 63 }() 64 65 m := map[language.Tag]bool{} 66 for _, lang := range data.Locales() { 67 // We include all locales unconditionally to be consistent with en_US. 68 // We want en_US, even though it has no data associated with it. 69 70 // TODO: put any of the languages for which no data exists at the end 71 // of the index. This allows all components based on ICU to use that 72 // as the cutoff point. 73 // if x := data.RawLDML(lang); false || 74 // x.LocaleDisplayNames != nil || 75 // x.Characters != nil || 76 // x.Delimiters != nil || 77 // x.Measurement != nil || 78 // x.Dates != nil || 79 // x.Numbers != nil || 80 // x.Units != nil || 81 // x.ListPatterns != nil || 82 // x.Collations != nil || 83 // x.Segmentations != nil || 84 // x.Rbnf != nil || 85 // x.Annotations != nil || 86 // x.Metadata != nil { 87 88 // TODO: support POSIX natively, albeit non-standard. 89 tag := language.Make(strings.Replace(lang, "_POSIX", "-u-va-posix", 1)) 90 m[tag] = true 91 // } 92 } 93 var core, special []language.Tag 94 95 for t := range m { 96 if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" { 97 log.Fatalf("Unexpected extension %v in %v", x, t) 98 } 99 if len(t.Variants()) == 0 && len(t.Extensions()) == 0 { 100 core = append(core, t) 101 } else { 102 special = append(special, t) 103 } 104 } 105 106 w.WriteComment(` 107 NumCompactTags is the number of common tags. The maximum tag is 108 NumCompactTags-1.`) 109 w.WriteConst("NumCompactTags", len(core)+len(special)) 110 111 sort.Sort(byAlpha(special)) 112 w.WriteVar("specialTags", special) 113 114 // TODO: order by frequency? 115 sort.Sort(byAlpha(core)) 116 117 // Size computations are just an estimate. 118 w.Size += int(reflect.TypeOf(map[uint32]uint16{}).Size()) 119 w.Size += len(core) * 6 // size of uint32 and uint16 120 121 fmt.Fprintln(w) 122 fmt.Fprintln(w, "var coreTags = map[uint32]uint16{") 123 fmt.Fprintln(w, "0x0: 0, // und") 124 i := len(special) + 1 // Und and special tags already written. 125 for _, t := range core { 126 if t == language.Und { 127 continue 128 } 129 fmt.Fprint(w.Hash, t, i) 130 b, s, r := t.Raw() 131 fmt.Fprintf(w, "0x%s%s%s: %d, // %s\n", 132 getIndex(b, 3), // 3 is enough as it is guaranteed to be a compact number 133 getIndex(s, 2), 134 getIndex(r, 3), 135 i, t) 136 i++ 137 } 138 fmt.Fprintln(w, "}") 139 } 140 141 // getIndex prints the subtag type and extracts its index of size nibble. 142 // If the index is less than n nibbles, the result is prefixed with 0s. 143 func getIndex(x interface{}, n int) string { 144 s := fmt.Sprintf("%#v", x) // s is of form Type{typeID: 0x00} 145 s = s[strings.Index(s, "0x")+2 : len(s)-1] 146 return strings.Repeat("0", n-len(s)) + s 147 } 148 149 type byAlpha []language.Tag 150 151 func (a byAlpha) Len() int { return len(a) } 152 func (a byAlpha) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 153 func (a byAlpha) Less(i, j int) bool { return a[i].String() < a[j].String() }