github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/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 "github.com/insionng/yougam/libraries/x/text/internal/gen" 22 "github.com/insionng/yougam/libraries/x/text/language" 23 "github.com/insionng/yougam/libraries/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 // Include locales for plural rules, which uses a different structure. 94 for _, plurals := range data.Supplemental().Plurals { 95 for _, rules := range plurals.PluralRules { 96 for _, lang := range strings.Split(rules.Locales, " ") { 97 m[language.Make(lang)] = true 98 } 99 } 100 } 101 102 var core, special []language.Tag 103 104 for t := range m { 105 if x := t.Extensions(); len(x) != 0 && fmt.Sprint(x) != "[u-va-posix]" { 106 log.Fatalf("Unexpected extension %v in %v", x, t) 107 } 108 if len(t.Variants()) == 0 && len(t.Extensions()) == 0 { 109 core = append(core, t) 110 } else { 111 special = append(special, t) 112 } 113 } 114 115 w.WriteComment(` 116 NumCompactTags is the number of common tags. The maximum tag is 117 NumCompactTags-1.`) 118 w.WriteConst("NumCompactTags", len(core)+len(special)) 119 120 sort.Sort(byAlpha(special)) 121 w.WriteVar("specialTags", special) 122 123 // TODO: order by frequency? 124 sort.Sort(byAlpha(core)) 125 126 // Size computations are just an estimate. 127 w.Size += int(reflect.TypeOf(map[uint32]uint16{}).Size()) 128 w.Size += len(core) * 6 // size of uint32 and uint16 129 130 fmt.Fprintln(w) 131 fmt.Fprintln(w, "var coreTags = map[uint32]uint16{") 132 fmt.Fprintln(w, "0x0: 0, // und") 133 i := len(special) + 1 // Und and special tags already written. 134 for _, t := range core { 135 if t == language.Und { 136 continue 137 } 138 fmt.Fprint(w.Hash, t, i) 139 b, s, r := t.Raw() 140 fmt.Fprintf(w, "0x%s%s%s: %d, // %s\n", 141 getIndex(b, 3), // 3 is enough as it is guaranteed to be a compact number 142 getIndex(s, 2), 143 getIndex(r, 3), 144 i, t) 145 i++ 146 } 147 fmt.Fprintln(w, "}") 148 } 149 150 // getIndex prints the subtag type and extracts its index of size nibble. 151 // If the index is less than n nibbles, the result is prefixed with 0s. 152 func getIndex(x interface{}, n int) string { 153 s := fmt.Sprintf("%#v", x) // s is of form Type{typeID: 0x00} 154 s = s[strings.Index(s, "0x")+2 : len(s)-1] 155 return strings.Repeat("0", n-len(s)) + s 156 } 157 158 type byAlpha []language.Tag 159 160 func (a byAlpha) Len() int { return len(a) } 161 func (a byAlpha) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 162 func (a byAlpha) Less(i, j int) bool { return a[i].String() < a[j].String() }