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