Add vendor folder to git

This commit is contained in:
Lucas Käldström 2017-06-26 19:23:05 +03:00
parent 66cf5eaafb
commit 183585f56f
No known key found for this signature in database
GPG key ID: 600FEFBBD0D40D21
6916 changed files with 2629581 additions and 1 deletions

105
vendor/golang.org/x/text/internal/colltab/colltab.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
// 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.
// Package colltab contains functionality related to collation tables.
// It is only to be used by the collate and search packages.
package colltab // import "golang.org/x/text/internal/colltab"
import (
"sort"
"golang.org/x/text/language"
)
// MatchLang finds the index of t in tags, using a matching algorithm used for
// collation and search. tags[0] must be language.Und, the remaining tags should
// be sorted alphabetically.
//
// Language matching for collation and search is different from the matching
// defined by language.Matcher: the (inferred) base language must be an exact
// match for the relevant fields. For example, "gsw" should not match "de".
// Also the parent relation is different, as a parent may have a different
// script. So usually the parent of zh-Hant is und, whereas for MatchLang it is
// zh.
func MatchLang(t language.Tag, tags []language.Tag) int {
// Canonicalize the values, including collapsing macro languages.
t, _ = language.All.Canonicalize(t)
base, conf := t.Base()
// Estimate the base language, but only use high-confidence values.
if conf < language.High {
// The root locale supports "search" and "standard". We assume that any
// implementation will only use one of both.
return 0
}
// Maximize base and script and normalize the tag.
if _, s, r := t.Raw(); (r != language.Region{}) {
p, _ := language.Raw.Compose(base, s, r)
// Taking the parent forces the script to be maximized.
p = p.Parent()
// Add back region and extensions.
t, _ = language.Raw.Compose(p, r, t.Extensions())
} else {
// Set the maximized base language.
t, _ = language.Raw.Compose(base, s, t.Extensions())
}
// Find start index of the language tag.
start := 1 + sort.Search(len(tags)-1, func(i int) bool {
b, _, _ := tags[i+1].Raw()
return base.String() <= b.String()
})
if start < len(tags) {
if b, _, _ := tags[start].Raw(); b != base {
return 0
}
}
// Besides the base language, script and region, only the collation type and
// the custom variant defined in the 'u' extension are used to distinguish a
// locale.
// Strip all variants and extensions and add back the custom variant.
tdef, _ := language.Raw.Compose(t.Raw())
tdef, _ = tdef.SetTypeForKey("va", t.TypeForKey("va"))
// First search for a specialized collation type, if present.
try := []language.Tag{tdef}
if co := t.TypeForKey("co"); co != "" {
tco, _ := tdef.SetTypeForKey("co", co)
try = []language.Tag{tco, tdef}
}
for _, tx := range try {
for ; tx != language.Und; tx = parent(tx) {
for i, t := range tags[start:] {
if b, _, _ := t.Raw(); b != base {
break
}
if tx == t {
return start + i
}
}
}
}
return 0
}
// parent computes the structural parent. This means inheritance may change
// script. So, unlike the CLDR parent, parent(zh-Hant) == zh.
func parent(t language.Tag) language.Tag {
if t.TypeForKey("va") != "" {
t, _ = t.SetTypeForKey("va", "")
return t
}
result := language.Und
if b, s, r := t.Raw(); (r != language.Region{}) {
result, _ = language.Raw.Compose(b, s, t.Extensions())
} else if (s != language.Script{}) {
result, _ = language.Raw.Compose(b, t.Extensions())
} else if (b != language.Base{}) {
result, _ = language.Raw.Compose(t.Extensions())
}
return result
}

View file

@ -0,0 +1,64 @@
package colltab
import (
"testing"
"golang.org/x/text/language"
)
func TestMatchLang(t *testing.T) {
tags := []language.Tag{
0: language.Und,
1: language.MustParse("bs"),
2: language.German,
3: language.English,
4: language.AmericanEnglish,
5: language.MustParse("en-US-u-va-posix"),
6: language.Portuguese,
7: language.Serbian,
8: language.MustParse("sr-Latn"),
9: language.Chinese,
10: language.MustParse("zh-u-co-stroke"),
11: language.MustParse("zh-Hant-u-co-pinyin"),
12: language.TraditionalChinese,
}
for i, tc := range []struct {
x int
t language.Tag
}{
{0, language.Und},
{0, language.Persian}, // Default to first element when no match.
{3, language.English},
{4, language.AmericanEnglish},
{5, language.MustParse("en-US-u-va-posix")}, // Ext. variant match.
{4, language.MustParse("en-US-u-va-noposix")}, // Ext. variant mismatch.
{3, language.MustParse("en-UK-u-va-noposix")}, // Ext. variant mismatch.
{7, language.Serbian},
{0, language.Croatian}, // Don't match to close language!
{0, language.MustParse("gsw")}, // Don't match to close language!
{1, language.MustParse("bs-Cyrl")}, // Odd, but correct.
{1, language.MustParse("bs-Latn")}, // Estimated script drops.
{8, language.MustParse("sr-Latn")},
{9, language.Chinese},
{9, language.SimplifiedChinese},
{12, language.TraditionalChinese},
{11, language.MustParse("zh-Hant-u-co-pinyin")},
// TODO: should this be 12? Either inherited value (10) or default is
// fine in this case, though. Other locales are not affected.
{10, language.MustParse("zh-Hant-u-co-stroke")},
// There is no "phonebk" sorting order for zh-Hant, so use default.
{12, language.MustParse("zh-Hant-u-co-phonebk")},
{10, language.MustParse("zh-u-co-stroke")},
{12, language.MustParse("und-TW")}, // Infer script and language.
{12, language.MustParse("und-HK")}, // Infer script and language.
{6, language.MustParse("und-BR")}, // Infer script and language.
{6, language.MustParse("und-PT")}, // Infer script and language.
{2, language.MustParse("und-Latn-DE")}, // Infer language.
{0, language.MustParse("und-Jpan-BR")}, // Infers "ja", so no match.
{0, language.MustParse("zu")}, // No match past index.
} {
if x := MatchLang(tc.t, tags); x != tc.x {
t.Errorf("%d: MatchLang(%q, tags) = %d; want %d", i, tc.t, x, tc.x)
}
}
}

145
vendor/golang.org/x/text/internal/colltab/contract.go generated vendored Normal file
View file

@ -0,0 +1,145 @@
// Copyright 2012 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 colltab
import "unicode/utf8"
// For a description of contractTrieSet, see text/collate/build/contract.go.
type contractTrieSet []struct{ l, h, n, i uint8 }
// ctScanner is used to match a trie to an input sequence.
// A contraction may match a non-contiguous sequence of bytes in an input string.
// For example, if there is a contraction for <a, combining_ring>, it should match
// the sequence <a, combining_cedilla, combining_ring>, as combining_cedilla does
// not block combining_ring.
// ctScanner does not automatically skip over non-blocking non-starters, but rather
// retains the state of the last match and leaves it up to the user to continue
// the match at the appropriate points.
type ctScanner struct {
states contractTrieSet
s []byte
n int
index int
pindex int
done bool
}
type ctScannerString struct {
states contractTrieSet
s string
n int
index int
pindex int
done bool
}
func (t contractTrieSet) scanner(index, n int, b []byte) ctScanner {
return ctScanner{s: b, states: t[index:], n: n}
}
func (t contractTrieSet) scannerString(index, n int, str string) ctScannerString {
return ctScannerString{s: str, states: t[index:], n: n}
}
// result returns the offset i and bytes consumed p so far. If no suffix
// matched, i and p will be 0.
func (s *ctScanner) result() (i, p int) {
return s.index, s.pindex
}
func (s *ctScannerString) result() (i, p int) {
return s.index, s.pindex
}
const (
final = 0
noIndex = 0xFF
)
// scan matches the longest suffix at the current location in the input
// and returns the number of bytes consumed.
func (s *ctScanner) scan(p int) int {
pr := p // the p at the rune start
str := s.s
states, n := s.states, s.n
for i := 0; i < n && p < len(str); {
e := states[i]
c := str[p]
// TODO: a significant number of contractions are of a form that
// cannot match discontiguous UTF-8 in a normalized string. We could let
// a negative value of e.n mean that we can set s.done = true and avoid
// the need for additional matches.
if c >= e.l {
if e.l == c {
p++
if e.i != noIndex {
s.index = int(e.i)
s.pindex = p
}
if e.n != final {
i, states, n = 0, states[int(e.h)+n:], int(e.n)
if p >= len(str) || utf8.RuneStart(str[p]) {
s.states, s.n, pr = states, n, p
}
} else {
s.done = true
return p
}
continue
} else if e.n == final && c <= e.h {
p++
s.done = true
s.index = int(c-e.l) + int(e.i)
s.pindex = p
return p
}
}
i++
}
return pr
}
// scan is a verbatim copy of ctScanner.scan.
func (s *ctScannerString) scan(p int) int {
pr := p // the p at the rune start
str := s.s
states, n := s.states, s.n
for i := 0; i < n && p < len(str); {
e := states[i]
c := str[p]
// TODO: a significant number of contractions are of a form that
// cannot match discontiguous UTF-8 in a normalized string. We could let
// a negative value of e.n mean that we can set s.done = true and avoid
// the need for additional matches.
if c >= e.l {
if e.l == c {
p++
if e.i != noIndex {
s.index = int(e.i)
s.pindex = p
}
if e.n != final {
i, states, n = 0, states[int(e.h)+n:], int(e.n)
if p >= len(str) || utf8.RuneStart(str[p]) {
s.states, s.n, pr = states, n, p
}
} else {
s.done = true
return p
}
continue
} else if e.n == final && c <= e.h {
p++
s.done = true
s.index = int(c-e.l) + int(e.i)
s.pindex = p
return p
}
}
i++
}
return pr
}

View file

@ -0,0 +1,135 @@
// Copyright 2012 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 colltab
import (
"testing"
)
type lookupStrings struct {
str string
offset int
n int // bytes consumed from input
}
var lookupTests = []struct {
lookup []lookupStrings
n int
tries contractTrieSet
}{
{
[]lookupStrings{
{"abc", 1, 3},
{"a", 0, 0},
{"b", 0, 0},
{"c", 0, 0},
{"d", 0, 0},
},
1,
contractTrieSet{
{'a', 0, 1, 0xFF},
{'b', 0, 1, 0xFF},
{'c', 'c', 0, 1},
},
},
{
[]lookupStrings{
{"abc", 1, 3},
{"abd", 2, 3},
{"abe", 3, 3},
{"a", 0, 0},
{"ab", 0, 0},
{"d", 0, 0},
{"f", 0, 0},
},
1,
contractTrieSet{
{'a', 0, 1, 0xFF},
{'b', 0, 1, 0xFF},
{'c', 'e', 0, 1},
},
},
{
[]lookupStrings{
{"abc", 1, 3},
{"ab", 2, 2},
{"a", 3, 1},
{"abcd", 1, 3},
{"abe", 2, 2},
},
1,
contractTrieSet{
{'a', 0, 1, 3},
{'b', 0, 1, 2},
{'c', 'c', 0, 1},
},
},
{
[]lookupStrings{
{"abc", 1, 3},
{"abd", 2, 3},
{"ab", 3, 2},
{"ac", 4, 2},
{"a", 5, 1},
{"b", 6, 1},
{"ba", 6, 1},
},
2,
contractTrieSet{
{'b', 'b', 0, 6},
{'a', 0, 2, 5},
{'c', 'c', 0, 4},
{'b', 0, 1, 3},
{'c', 'd', 0, 1},
},
},
{
[]lookupStrings{
{"bcde", 2, 4},
{"bc", 7, 2},
{"ab", 6, 2},
{"bcd", 5, 3},
{"abcd", 1, 4},
{"abc", 4, 3},
{"bcdf", 3, 4},
},
2,
contractTrieSet{
{'b', 3, 1, 0xFF},
{'a', 0, 1, 0xFF},
{'b', 0, 1, 6},
{'c', 0, 1, 4},
{'d', 'd', 0, 1},
{'c', 0, 1, 7},
{'d', 0, 1, 5},
{'e', 'f', 0, 2},
},
},
}
func lookup(c *contractTrieSet, nnode int, s []uint8) (i, n int) {
scan := c.scanner(0, nnode, s)
scan.scan(0)
return scan.result()
}
func TestLookupContraction(t *testing.T) {
for i, tt := range lookupTests {
cts := contractTrieSet(tt.tries)
for j, lu := range tt.lookup {
str := lu.str
for _, s := range []string{str, str + "X"} {
const msg = "%d:%d: %s of %q %v; want %v"
offset, n := lookup(&cts, tt.n, []byte(s))
if offset != lu.offset {
t.Errorf(msg, i, j, "offset", s, offset, lu.offset)
}
if n != lu.n {
t.Errorf(msg, i, j, "bytes consumed", s, n, len(str))
}
}
}
}
}

182
vendor/golang.org/x/text/internal/colltab/iter.go generated vendored Normal file
View file

@ -0,0 +1,182 @@
// 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.
package colltab
import (
"golang.org/x/text/collate/colltab"
)
// An Iter incrementally converts chunks of the input text to collation
// elements, while ensuring that the collation elements are in normalized order
// (that is, they are in the order as if the input text were normalized first).
type Iter struct {
Weighter colltab.Weighter
Elems []colltab.Elem
// N is the number of elements in Elems that will not be reordered on
// subsequent iterations, N <= len(Elems).
N int
bytes []byte
str string
// Because the Elems buffer may contain collation elements that are needed
// for look-ahead, we need two positions in the text (bytes or str): one for
// the end position in the text for the current iteration and one for the
// start of the next call to appendNext.
pEnd int // end position in text corresponding to N.
pNext int // pEnd <= pNext.
}
// Reset sets the position in the current input text to p and discards any
// results obtained so far.
func (i *Iter) Reset(p int) {
i.Elems = i.Elems[:0]
i.N = 0
i.pEnd = p
i.pNext = p
}
// Len returns the length of the input text.
func (i *Iter) Len() int {
if i.bytes != nil {
return len(i.bytes)
}
return len(i.str)
}
// Discard removes the collation elements up to N.
func (i *Iter) Discard() {
// TODO: change this such that only modifiers following starters will have
// to be copied.
i.Elems = i.Elems[:copy(i.Elems, i.Elems[i.N:])]
i.N = 0
}
// End returns the end position of the input text for which Next has returned
// results.
func (i *Iter) End() int {
return i.pEnd
}
// SetInput resets i to input s.
func (i *Iter) SetInput(s []byte) {
i.bytes = s
i.str = ""
i.Reset(0)
}
// SetInputString resets i to input s.
func (i *Iter) SetInputString(s string) {
i.str = s
i.bytes = nil
i.Reset(0)
}
func (i *Iter) done() bool {
return i.pNext >= len(i.str) && i.pNext >= len(i.bytes)
}
func (i *Iter) appendNext() bool {
if i.done() {
return false
}
var sz int
if i.bytes == nil {
i.Elems, sz = i.Weighter.AppendNextString(i.Elems, i.str[i.pNext:])
} else {
i.Elems, sz = i.Weighter.AppendNext(i.Elems, i.bytes[i.pNext:])
}
if sz == 0 {
sz = 1
}
i.pNext += sz
return true
}
// Next appends Elems to the internal array. On each iteration, it will either
// add starters or modifiers. In the majority of cases, an Elem with a primary
// value > 0 will have a CCC of 0. The CCC values of collation elements are also
// used to detect if the input string was not normalized and to adjust the
// result accordingly.
func (i *Iter) Next() bool {
if i.N == len(i.Elems) && !i.appendNext() {
return false
}
// Check if the current segment starts with a starter.
prevCCC := i.Elems[len(i.Elems)-1].CCC()
if prevCCC == 0 {
i.N = len(i.Elems)
i.pEnd = i.pNext
return true
} else if i.Elems[i.N].CCC() == 0 {
// set i.N to only cover part of i.Elems for which prevCCC == 0 and
// use rest for the next call to next.
for i.N++; i.N < len(i.Elems) && i.Elems[i.N].CCC() == 0; i.N++ {
}
i.pEnd = i.pNext
return true
}
// The current (partial) segment starts with modifiers. We need to collect
// all successive modifiers to ensure that they are normalized.
for {
p := len(i.Elems)
i.pEnd = i.pNext
if !i.appendNext() {
break
}
if ccc := i.Elems[p].CCC(); ccc == 0 || len(i.Elems)-i.N > maxCombiningCharacters {
// Leave the starter for the next iteration. This ensures that we
// do not return sequences of collation elements that cross two
// segments.
//
// TODO: handle large number of combining characters by fully
// normalizing the input segment before iteration. This ensures
// results are consistent across the text repo.
i.N = p
return true
} else if ccc < prevCCC {
i.doNorm(p, ccc) // should be rare, never occurs for NFD and FCC.
} else {
prevCCC = ccc
}
}
done := len(i.Elems) != i.N
i.N = len(i.Elems)
return done
}
// nextNoNorm is the same as next, but does not "normalize" the collation
// elements.
func (i *Iter) nextNoNorm() bool {
// TODO: remove this function. Using this instead of next does not seem
// to improve performance in any significant way. We retain this until
// later for evaluation purposes.
if i.done() {
return false
}
i.appendNext()
i.N = len(i.Elems)
return true
}
const maxCombiningCharacters = 30
// doNorm reorders the collation elements in i.Elems.
// It assumes that blocks of collation elements added with appendNext
// either start and end with the same CCC or start with CCC == 0.
// This allows for a single insertion point for the entire block.
// The correctness of this assumption is verified in builder.go.
func (i *Iter) doNorm(p int, ccc uint8) {
n := len(i.Elems)
k := p
for p--; p > i.N && ccc < i.Elems[p-1].CCC(); p-- {
}
i.Elems = append(i.Elems, i.Elems[p:k]...)
copy(i.Elems[p:], i.Elems[k:])
i.Elems = i.Elems[:n]
}

77
vendor/golang.org/x/text/internal/colltab/iter_test.go generated vendored Normal file
View file

@ -0,0 +1,77 @@
// 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.
package colltab
import (
"testing"
"golang.org/x/text/collate/colltab"
)
const (
defaultSecondary = 0x20
)
func makeCE(w []int) colltab.Elem {
ce, err := colltab.MakeElem(w[0], w[1], w[2], uint8(w[3]))
if err != nil {
panic(err)
}
return ce
}
func TestDoNorm(t *testing.T) {
const div = -1 // The insertion point of the next block.
tests := []struct {
in, out []int
}{{
in: []int{4, div, 3},
out: []int{3, 4},
}, {
in: []int{4, div, 3, 3, 3},
out: []int{3, 3, 3, 4},
}, {
in: []int{0, 4, div, 3},
out: []int{0, 3, 4},
}, {
in: []int{0, 0, 4, 5, div, 3, 3},
out: []int{0, 0, 3, 3, 4, 5},
}, {
in: []int{0, 0, 1, 4, 5, div, 3, 3},
out: []int{0, 0, 1, 3, 3, 4, 5},
}, {
in: []int{0, 0, 1, 4, 5, div, 4, 4},
out: []int{0, 0, 1, 4, 4, 4, 5},
},
}
for j, tt := range tests {
i := Iter{}
var w, p int
for k, cc := range tt.in {
if cc == div {
w = 100
p = k
continue
}
i.Elems = append(i.Elems, makeCE([]int{w, defaultSecondary, 2, cc}))
}
i.doNorm(p, i.Elems[p].CCC())
if len(i.Elems) != len(tt.out) {
t.Errorf("%d: length was %d; want %d", j, len(i.Elems), len(tt.out))
}
prevCCC := uint8(0)
for k, ce := range i.Elems {
if int(ce.CCC()) != tt.out[k] {
t.Errorf("%d:%d: unexpected CCC. Was %d; want %d", j, k, ce.CCC(), tt.out[k])
}
if k > 0 && ce.CCC() == prevCCC && i.Elems[k-1].Primary() > ce.Primary() {
t.Errorf("%d:%d: normalization crossed across CCC boundary.", j, k)
}
}
}
// Combining rune overflow is tested in search/pattern_test.go.
}

43
vendor/golang.org/x/text/internal/format/format.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
// 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.
// Package format contains types for defining language-specific formatting of
// values.
//
// This package is internal now, but will eventually be exposed after the API
// settles.
package format // import "golang.org/x/text/internal/format"
import (
"fmt"
"golang.org/x/text/language"
)
// State represents the printer state passed to custom formatters. It provides
// access to the fmt.State interface and the sentence and language-related
// context.
type State interface {
fmt.State
// Language reports the requested language in which to render a message.
Language() language.Tag
// TODO: more info:
// - sentence context
// - user preferences, like measurement systems
// - options
}
// A Statement is a Var or an Expression.
type Statement interface {
statement()
}
// A String a literal string format.
type String string
func (String) statement() {}
// TODO: Select, Var, Case, StatementSequence

View file

@ -0,0 +1,38 @@
// Copyright 2016 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 plural defines the grammatical plural feature.
//
// The definitions in this package are based on the plural rule handling defined
// in CLDR. See
// http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules for
// details.
package plural
import "golang.org/x/text/internal/format"
// Form defines a plural form. The meaning of plural forms, as well as which
// forms are supported, vary per language. Each language must at least support
// the form "other".
type Form byte
const (
Other Form = iota
Zero
One
Two
Few
Many
)
// Interface is implemented by values that have a plural feature.
type Interface interface {
// PluralForm reports the plural form of a value, depending on the
// language declared by the given state.
PluralForm(s format.State) Form
}
// TODO
// - Select function
// - Definition for message package.

52
vendor/golang.org/x/text/internal/gen.go generated vendored Normal file
View file

@ -0,0 +1,52 @@
// 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
import (
"log"
"golang.org/x/text/internal/gen"
"golang.org/x/text/language"
"golang.org/x/text/unicode/cldr"
)
func main() {
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 w.WriteGoFile("tables.go", "internal")
// Create parents table.
parents := make([]uint16, language.NumCompactTags)
for _, loc := range data.Locales() {
tag := language.MustParse(loc)
index, ok := language.CompactIndex(tag)
if !ok {
continue
}
parentIndex := 0 // und
for p := tag.Parent(); p != language.Und; p = p.Parent() {
if x, ok := language.CompactIndex(p); ok {
parentIndex = x
break
}
}
parents[index] = uint16(parentIndex)
}
w.WriteComment(`
Parent maps a compact index of a tag to the compact index of the parent of
this tag.`)
w.WriteVar("Parent", parents)
}

338
vendor/golang.org/x/text/internal/gen/code.go generated vendored Normal file
View file

@ -0,0 +1,338 @@
// 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.
package gen
import (
"bytes"
"encoding/gob"
"fmt"
"hash"
"hash/fnv"
"io"
"log"
"os"
"reflect"
"strings"
"unicode"
"unicode/utf8"
)
// This file contains utilities for generating code.
// TODO: other write methods like:
// - slices, maps, types, etc.
// CodeWriter is a utility for writing structured code. It computes the content
// hash and size of written content. It ensures there are newlines between
// written code blocks.
type CodeWriter struct {
buf bytes.Buffer
Size int
Hash hash.Hash32 // content hash
gob *gob.Encoder
// For comments we skip the usual one-line separator if they are followed by
// a code block.
skipSep bool
}
func (w *CodeWriter) Write(p []byte) (n int, err error) {
return w.buf.Write(p)
}
// NewCodeWriter returns a new CodeWriter.
func NewCodeWriter() *CodeWriter {
h := fnv.New32()
return &CodeWriter{Hash: h, gob: gob.NewEncoder(h)}
}
// WriteGoFile appends the buffer with the total size of all created structures
// and writes it as a Go file to the the given file with the given package name.
func (w *CodeWriter) WriteGoFile(filename, pkg string) {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("Could not create file %s: %v", filename, err)
}
defer f.Close()
if _, err = w.WriteGo(f, pkg); err != nil {
log.Fatalf("Error writing file %s: %v", filename, err)
}
}
// WriteGo appends the buffer with the total size of all created structures and
// writes it as a Go file to the the given writer with the given package name.
func (w *CodeWriter) WriteGo(out io.Writer, pkg string) (n int, err error) {
sz := w.Size
w.WriteComment("Total table size %d bytes (%dKiB); checksum: %X\n", sz, sz/1024, w.Hash.Sum32())
defer w.buf.Reset()
return WriteGo(out, pkg, w.buf.Bytes())
}
func (w *CodeWriter) printf(f string, x ...interface{}) {
fmt.Fprintf(w, f, x...)
}
func (w *CodeWriter) insertSep() {
if w.skipSep {
w.skipSep = false
return
}
// Use at least two newlines to ensure a blank space between the previous
// block. WriteGoFile will remove extraneous newlines.
w.printf("\n\n")
}
// WriteComment writes a comment block. All line starts are prefixed with "//".
// Initial empty lines are gobbled. The indentation for the first line is
// stripped from consecutive lines.
func (w *CodeWriter) WriteComment(comment string, args ...interface{}) {
s := fmt.Sprintf(comment, args...)
s = strings.Trim(s, "\n")
// Use at least two newlines to ensure a blank space between the previous
// block. WriteGoFile will remove extraneous newlines.
w.printf("\n\n// ")
w.skipSep = true
// strip first indent level.
sep := "\n"
for ; len(s) > 0 && (s[0] == '\t' || s[0] == ' '); s = s[1:] {
sep += s[:1]
}
strings.NewReplacer(sep, "\n// ", "\n", "\n// ").WriteString(w, s)
w.printf("\n")
}
func (w *CodeWriter) writeSizeInfo(size int) {
w.printf("// Size: %d bytes\n", size)
}
// WriteConst writes a constant of the given name and value.
func (w *CodeWriter) WriteConst(name string, x interface{}) {
w.insertSep()
v := reflect.ValueOf(x)
switch v.Type().Kind() {
case reflect.String:
// See golang.org/issue/13145.
const arbitraryCutoff = 16
if v.Len() > arbitraryCutoff {
w.printf("var %s %s = ", name, typeName(x))
} else {
w.printf("const %s %s = ", name, typeName(x))
}
w.WriteString(v.String())
w.printf("\n")
default:
w.printf("const %s = %#v\n", name, x)
}
}
// WriteVar writes a variable of the given name and value.
func (w *CodeWriter) WriteVar(name string, x interface{}) {
w.insertSep()
v := reflect.ValueOf(x)
oldSize := w.Size
sz := int(v.Type().Size())
w.Size += sz
switch v.Type().Kind() {
case reflect.String:
w.printf("var %s %s = ", name, typeName(x))
w.WriteString(v.String())
case reflect.Struct:
w.gob.Encode(x)
fallthrough
case reflect.Slice, reflect.Array:
w.printf("var %s = ", name)
w.writeValue(v)
w.writeSizeInfo(w.Size - oldSize)
default:
w.printf("var %s %s = ", name, typeName(x))
w.gob.Encode(x)
w.writeValue(v)
w.writeSizeInfo(w.Size - oldSize)
}
w.printf("\n")
}
func (w *CodeWriter) writeValue(v reflect.Value) {
x := v.Interface()
switch v.Kind() {
case reflect.String:
w.WriteString(v.String())
case reflect.Array:
// Don't double count: callers of WriteArray count on the size being
// added, so we need to discount it here.
w.Size -= int(v.Type().Size())
w.writeSlice(x, true)
case reflect.Slice:
w.writeSlice(x, false)
case reflect.Struct:
w.printf("%s{\n", typeName(v.Interface()))
t := v.Type()
for i := 0; i < v.NumField(); i++ {
w.printf("%s: ", t.Field(i).Name)
w.writeValue(v.Field(i))
w.printf(",\n")
}
w.printf("}")
default:
w.printf("%#v", x)
}
}
// WriteString writes a string literal.
func (w *CodeWriter) WriteString(s string) {
io.WriteString(w.Hash, s) // content hash
w.Size += len(s)
const maxInline = 40
if len(s) <= maxInline {
w.printf("%q", s)
return
}
// We will render the string as a multi-line string.
const maxWidth = 80 - 4 - len(`"`) - len(`" +`)
// When starting on its own line, go fmt indents line 2+ an extra level.
n, max := maxWidth, maxWidth-4
// Print "" +\n, if a string does not start on its own line.
b := w.buf.Bytes()
if p := len(bytes.TrimRight(b, " \t")); p > 0 && b[p-1] != '\n' {
w.printf("\"\" + // Size: %d bytes\n", len(s))
n, max = maxWidth, maxWidth
}
w.printf(`"`)
for sz, p := 0, 0; p < len(s); {
var r rune
r, sz = utf8.DecodeRuneInString(s[p:])
out := s[p : p+sz]
chars := 1
if !unicode.IsPrint(r) || r == utf8.RuneError || r == '"' {
switch sz {
case 1:
out = fmt.Sprintf("\\x%02x", s[p])
case 2, 3:
out = fmt.Sprintf("\\u%04x", r)
case 4:
out = fmt.Sprintf("\\U%08x", r)
}
chars = len(out)
}
if n -= chars; n < 0 {
w.printf("\" +\n\"")
n = max - len(out)
}
w.printf("%s", out)
p += sz
}
w.printf(`"`)
}
// WriteSlice writes a slice value.
func (w *CodeWriter) WriteSlice(x interface{}) {
w.writeSlice(x, false)
}
// WriteArray writes an array value.
func (w *CodeWriter) WriteArray(x interface{}) {
w.writeSlice(x, true)
}
func (w *CodeWriter) writeSlice(x interface{}, isArray bool) {
v := reflect.ValueOf(x)
w.gob.Encode(v.Len())
w.Size += v.Len() * int(v.Type().Elem().Size())
name := typeName(x)
if isArray {
name = fmt.Sprintf("[%d]%s", v.Len(), name[strings.Index(name, "]")+1:])
}
if isArray {
w.printf("%s{\n", name)
} else {
w.printf("%s{ // %d elements\n", name, v.Len())
}
switch kind := v.Type().Elem().Kind(); kind {
case reflect.String:
for _, s := range x.([]string) {
w.WriteString(s)
w.printf(",\n")
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
// nLine and nBlock are the number of elements per line and block.
nLine, nBlock, format := 8, 64, "%d,"
switch kind {
case reflect.Uint8:
format = "%#02x,"
case reflect.Uint16:
format = "%#04x,"
case reflect.Uint32:
nLine, nBlock, format = 4, 32, "%#08x,"
case reflect.Uint, reflect.Uint64:
nLine, nBlock, format = 4, 32, "%#016x,"
case reflect.Int8:
nLine = 16
}
n := nLine
for i := 0; i < v.Len(); i++ {
if i%nBlock == 0 && v.Len() > nBlock {
w.printf("// Entry %X - %X\n", i, i+nBlock-1)
}
x := v.Index(i).Interface()
w.gob.Encode(x)
w.printf(format, x)
if n--; n == 0 {
n = nLine
w.printf("\n")
}
}
w.printf("\n")
case reflect.Struct:
zero := reflect.Zero(v.Type().Elem()).Interface()
for i := 0; i < v.Len(); i++ {
x := v.Index(i).Interface()
w.gob.EncodeValue(v)
if !reflect.DeepEqual(zero, x) {
line := fmt.Sprintf("%#v,\n", x)
line = line[strings.IndexByte(line, '{'):]
w.printf("%d: ", i)
w.printf(line)
}
}
case reflect.Array:
for i := 0; i < v.Len(); i++ {
w.printf("%d: %#v,\n", i, v.Index(i).Interface())
}
default:
panic("gen: slice elem type not supported")
}
w.printf("}")
}
// WriteType writes a definition of the type of the given value and returns the
// type name.
func (w *CodeWriter) WriteType(x interface{}) string {
t := reflect.TypeOf(x)
w.printf("type %s struct {\n", t.Name())
for i := 0; i < t.NumField(); i++ {
w.printf("\t%s %s\n", t.Field(i).Name, t.Field(i).Type)
}
w.printf("}\n")
return t.Name()
}
// typeName returns the name of the go type of x.
func typeName(x interface{}) string {
t := reflect.ValueOf(x).Type()
return strings.Replace(fmt.Sprint(t), "main.", "", 1)
}

226
vendor/golang.org/x/text/internal/gen/gen.go generated vendored Normal file
View file

@ -0,0 +1,226 @@
// 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.
// Package gen contains common code for the various code generation tools in the
// text repository. Its usage ensures consistency between tools.
//
// This package defines command line flags that are common to most generation
// tools. The flags allow for specifying specific Unicode and CLDR versions
// in the public Unicode data repository (http://www.unicode.org/Public).
//
// A local Unicode data mirror can be set through the flag -local or the
// environment variable UNICODE_DIR. The former takes precedence. The local
// directory should follow the same structure as the public repository.
//
// IANA data can also optionally be mirrored by putting it in the iana directory
// rooted at the top of the local mirror. Beware, though, that IANA data is not
// versioned. So it is up to the developer to use the right version.
package gen // import "golang.org/x/text/internal/gen"
import (
"bytes"
"flag"
"fmt"
"go/format"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"path/filepath"
"unicode"
"golang.org/x/text/unicode/cldr"
)
var (
url = flag.String("url",
"http://www.unicode.org/Public",
"URL of Unicode database directory")
iana = flag.String("iana",
"http://www.iana.org",
"URL of the IANA repository")
unicodeVersion = flag.String("unicode",
getEnv("UNICODE_VERSION", unicode.Version),
"unicode version to use")
cldrVersion = flag.String("cldr",
getEnv("CLDR_VERSION", cldr.Version),
"cldr version to use")
// Allow an environment variable to specify the local directory.
// go generate doesn't allow specifying arguments; this is a useful
// alternative to specifying a local mirror.
localDir = flag.String("local",
os.Getenv("UNICODE_DIR"),
"directory containing local data files; for debugging only.")
)
func getEnv(name, def string) string {
if v := os.Getenv(name); v != "" {
return v
}
return def
}
// Init performs common initialization for a gen command. It parses the flags
// and sets up the standard logging parameters.
func Init() {
log.SetPrefix("")
log.SetFlags(log.Lshortfile)
flag.Parse()
}
const header = `// This file was generated by go generate; DO NOT EDIT
package %s
`
// UnicodeVersion reports the requested Unicode version.
func UnicodeVersion() string {
return *unicodeVersion
}
// UnicodeVersion reports the requested CLDR version.
func CLDRVersion() string {
return *cldrVersion
}
// IsLocal reports whether the user specified a local directory.
func IsLocal() bool {
return *localDir != ""
}
// OpenUCDFile opens the requested UCD file. The file is specified relative to
// the public Unicode root directory. It will call log.Fatal if there are any
// errors.
func OpenUCDFile(file string) io.ReadCloser {
return openUnicode(path.Join(*unicodeVersion, "ucd", file))
}
// OpenCLDRCoreZip opens the CLDR core zip file. It will call log.Fatal if there
// are any errors.
func OpenCLDRCoreZip() io.ReadCloser {
return OpenUnicodeFile("cldr", *cldrVersion, "core.zip")
}
// OpenUnicodeFile opens the requested file of the requested category from the
// root of the Unicode data archive. The file is specified relative to the
// public Unicode root directory. If version is "", it will use the default
// Unicode version. It will call log.Fatal if there are any errors.
func OpenUnicodeFile(category, version, file string) io.ReadCloser {
if version == "" {
version = UnicodeVersion()
}
return openUnicode(path.Join(category, version, file))
}
// OpenIANAFile opens the requested IANA file. The file is specified relative
// to the IANA root, which is typically either http://www.iana.org or the
// iana directory in the local mirror. It will call log.Fatal if there are any
// errors.
func OpenIANAFile(path string) io.ReadCloser {
return Open(*iana, "iana", path)
}
// Open opens subdir/path if a local directory is specified and the file exists,
// where subdir is a directory relative to the local root, or fetches it from
// urlRoot/path otherwise. It will call log.Fatal if there are any errors.
func Open(urlRoot, subdir, path string) io.ReadCloser {
if *localDir != "" {
path = filepath.FromSlash(path)
if f, err := os.Open(filepath.Join(*localDir, subdir, path)); err == nil {
return f
}
}
return get(urlRoot, path)
}
func openUnicode(path string) io.ReadCloser {
if *localDir != "" {
path = filepath.FromSlash(path)
f, err := os.Open(filepath.Join(*localDir, path))
if err != nil {
log.Fatal(err)
}
return f
}
return get(*url, path)
}
func get(root, path string) io.ReadCloser {
url := root + "/" + path
fmt.Printf("Fetching %s...", url)
defer fmt.Println(" done.")
resp, err := http.Get(url)
if err != nil {
log.Fatalf("HTTP GET: %v", err)
}
if resp.StatusCode != 200 {
log.Fatalf("Bad GET status for %q: %q", url, resp.Status)
}
return resp.Body
}
// TODO: use Write*Version in all applicable packages.
// WriteUnicodeVersion writes a constant for the Unicode version from which the
// tables are generated.
func WriteUnicodeVersion(w io.Writer) {
fmt.Fprintf(w, "// UnicodeVersion is the Unicode version from which the tables in this package are derived.\n")
fmt.Fprintf(w, "const UnicodeVersion = %q\n\n", UnicodeVersion())
}
// WriteCLDRVersion writes a constant for the CLDR version from which the
// tables are generated.
func WriteCLDRVersion(w io.Writer) {
fmt.Fprintf(w, "// CLDRVersion is the CLDR version from which the tables in this package are derived.\n")
fmt.Fprintf(w, "const CLDRVersion = %q\n\n", CLDRVersion())
}
// WriteGoFile prepends a standard file comment and package statement to the
// given bytes, applies gofmt, and writes them to a file with the given name.
// It will call log.Fatal if there are any errors.
func WriteGoFile(filename, pkg string, b []byte) {
w, err := os.Create(filename)
if err != nil {
log.Fatalf("Could not create file %s: %v", filename, err)
}
defer w.Close()
if _, err = WriteGo(w, pkg, b); err != nil {
log.Fatalf("Error writing file %s: %v", filename, err)
}
}
// WriteGo prepends a standard file comment and package statement to the given
// bytes, applies gofmt, and writes them to w.
func WriteGo(w io.Writer, pkg string, b []byte) (n int, err error) {
src := []byte(fmt.Sprintf(header, pkg))
src = append(src, b...)
formatted, err := format.Source(src)
if err != nil {
// Print the generated code even in case of an error so that the
// returned error can be meaningfully interpreted.
n, _ = w.Write(src)
return n, err
}
return w.Write(formatted)
}
// Repackage rewrites a Go file from belonging to package main to belonging to
// the given package.
func Repackage(inFile, outFile, pkg string) {
src, err := ioutil.ReadFile(inFile)
if err != nil {
log.Fatalf("reading %s: %v", inFile, err)
}
const toDelete = "package main\n\n"
i := bytes.Index(src, []byte(toDelete))
if i < 0 {
log.Fatalf("Could not find %q in %s.", toDelete, inFile)
}
w := &bytes.Buffer{}
w.Write(src[i+len(toDelete):])
WriteGoFile(outFile, pkg, w.Bytes())
}

38
vendor/golang.org/x/text/internal/gen_test.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
// 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.
package internal
import (
"testing"
"golang.org/x/text/language"
)
func TestParents(t *testing.T) {
testCases := []struct {
tag, parent string
}{
{"af", "und"},
{"en", "und"},
{"en-001", "en"},
{"en-AU", "en-001"},
{"en-US", "en"},
{"en-US-u-va-posix", "en-US"},
{"ca-ES-valencia", "ca-ES"},
}
for _, tc := range testCases {
tag, ok := language.CompactIndex(language.MustParse(tc.tag))
if !ok {
t.Fatalf("Could not get index of flag %s", tc.tag)
}
want, ok := language.CompactIndex(language.MustParse(tc.parent))
if !ok {
t.Fatalf("Could not get index of parent %s of tag %s", tc.parent, tc.tag)
}
if got := int(Parent[tag]); got != want {
t.Errorf("Parent[%s] = %d; want %d (%s)", tc.tag, got, want, tc.parent)
}
}
}

51
vendor/golang.org/x/text/internal/internal.go generated vendored Normal file
View file

@ -0,0 +1,51 @@
// 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.
//go:generate go run gen.go
// Package internal contains non-exported functionality that are used by
// packages in the text repository.
package internal // import "golang.org/x/text/internal"
import (
"sort"
"golang.org/x/text/language"
)
// SortTags sorts tags in place.
func SortTags(tags []language.Tag) {
sort.Sort(sorter(tags))
}
type sorter []language.Tag
func (s sorter) Len() int {
return len(s)
}
func (s sorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s sorter) Less(i, j int) bool {
return s[i].String() < s[j].String()
}
// UniqueTags sorts and filters duplicate tags in place and returns a slice with
// only unique tags.
func UniqueTags(tags []language.Tag) []language.Tag {
if len(tags) <= 1 {
return tags
}
SortTags(tags)
k := 0
for i := 1; i < len(tags); i++ {
if tags[k].String() < tags[i].String() {
k++
tags[k] = tags[i]
}
}
return tags[:k+1]
}

38
vendor/golang.org/x/text/internal/internal_test.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
// 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.
package internal
import (
"fmt"
"strings"
"testing"
"golang.org/x/text/language"
)
func TestUnique(t *testing.T) {
testCases := []struct {
in, want string
}{
{"", "[]"},
{"en", "[en]"},
{"en en", "[en]"},
{"en en en", "[en]"},
{"en-u-cu-eur en", "[en en-u-cu-eur]"},
{"nl en", "[en nl]"},
{"pt-Pt pt", "[pt pt-PT]"},
}
for _, tc := range testCases {
tags := []language.Tag{}
for _, s := range strings.Split(tc.in, " ") {
if s != "" {
tags = append(tags, language.MustParse(s))
}
}
if got := fmt.Sprint(UniqueTags(tags)); got != tc.want {
t.Errorf("Unique(%s) = %s; want %s", tc.in, got, tc.want)
}
}
}

65
vendor/golang.org/x/text/internal/match.go generated vendored Normal file
View file

@ -0,0 +1,65 @@
// 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.
package internal
// This file contains matchers that implement CLDR inheritance.
//
// See http://unicode.org/reports/tr35/#Locale_Inheritance.
//
// Some of the inheritance described in this document is already handled by
// the cldr package.
import (
"golang.org/x/text/language"
)
// TODO: consider if (some of the) matching algorithm needs to be public after
// getting some feel about what is generic and what is specific.
// NewInheritanceMatcher returns a matcher that matches based on the inheritance
// chain.
//
// The matcher uses canonicalization and the parent relationship to find a
// match. The resulting match will always be either Und or a language with the
// same language and script as the requested language. It will not match
// languages for which there is understood to be mutual or one-directional
// intelligibility.
//
// A Match will indicate an Exact match if the language matches after
// canonicalization and High if the matched tag is a parent.
func NewInheritanceMatcher(t []language.Tag) language.Matcher {
tags := make(inheritanceMatcher)
for i, tag := range t {
ct, err := language.All.Canonicalize(tag)
if err != nil {
ct = tag
}
tags[ct] = i
}
return tags
}
type inheritanceMatcher map[language.Tag]int
func (m inheritanceMatcher) Match(want ...language.Tag) (language.Tag, int, language.Confidence) {
for _, t := range want {
ct, err := language.All.Canonicalize(t)
if err != nil {
ct = t
}
conf := language.Exact
for {
if index, ok := m[ct]; ok {
return ct, index, conf
}
if ct == language.Und {
break
}
ct = ct.Parent()
conf = language.High
}
}
return language.Und, 0, language.No
}

56
vendor/golang.org/x/text/internal/match_test.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
// 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.
package internal
import (
"strings"
"testing"
"golang.org/x/text/language"
)
func TestInheritanceMatcher(t *testing.T) {
for i, tt := range []struct {
haveTags string
wantTags string
match string
conf language.Confidence
}{
{"und,en,en-US", "en-US", "en-US", language.Exact}, // most specific match
{"zh-Hant,zh", "zh-TW", "zh-Hant", language.High}, // zh-TW implies Hant.
{"und,zh", "zh-TW", "und", language.High}, // zh-TW does not match zh.
{"zh", "zh-TW", "und", language.No}, // zh-TW does not match zh.
{"iw,en,nl", "he", "he", language.Exact}, // matches after canonicalization
{"he,en,nl", "iw", "he", language.Exact}, // matches after canonicalization
// Prefer first match over more specific match for various reasons:
// a) consistency of user interface is more important than an exact match,
// b) _if_ und is specified, it should be considered a correct and useful match,
// Note that a call to this Match will almost always be with a single tag.
{"und,en,en-US", "he,en-US", "und", language.High},
} {
have := parseTags(tt.haveTags)
m := NewInheritanceMatcher(have)
tag, index, conf := m.Match(parseTags(tt.wantTags)...)
want := language.Raw.Make(tt.match)
if tag != want {
t.Errorf("%d:tag: got %q; want %q", i, tag, want)
}
if conf != language.No {
if got, _ := language.All.Canonicalize(have[index]); got != want {
t.Errorf("%d:index: got %q; want %q ", i, got, want)
}
}
if conf != tt.conf {
t.Errorf("%d:conf: got %v; want %v", i, conf, tt.conf)
}
}
}
func parseTags(list string) (out []language.Tag) {
for _, s := range strings.Split(list, ",") {
out = append(out, language.Raw.Make(strings.TrimSpace(s)))
}
return out
}

92
vendor/golang.org/x/text/internal/number/common.go generated vendored Normal file
View file

@ -0,0 +1,92 @@
// This file was generated by go generate; DO NOT EDIT
package number
import (
"unicode/utf8"
"golang.org/x/text/internal/format/plural"
)
// A system identifies a CLDR numbering system.
type system byte
type systemData struct {
id system
digitSize byte // number of UTF-8 bytes per digit
zero [utf8.UTFMax]byte // UTF-8 sequence of zero digit.
}
// A SymbolType identifies a symbol of a specific kind.
type SymbolType int
const (
SymDecimal SymbolType = iota
SymGroup
SymList
SymPercentSign
SymPlusSign
SymMinusSign
SymExponential
SymSuperscriptingExponent
SymPerMille
SymInfinity
SymNan
SymTimeSeparator
NumSymbolTypes
)
type altSymData struct {
compactTag uint16
system system
symIndex byte
}
var countMap = map[string]plural.Form{
"other": plural.Other,
"zero": plural.Zero,
"one": plural.One,
"two": plural.Two,
"few": plural.Few,
"many": plural.Many,
}
type pluralCheck struct {
// category:
// 3..7: opID
// 0..2: category
cat byte
setID byte
}
// opID identifies the type of operand in the plural rule, being i, n or f.
// (v, w, and t are treated as filters in our implementation.)
type opID byte
const (
opMod opID = 0x1 // is '%' used?
opNotEqual opID = 0x2 // using "!=" to compare
opI opID = 0 << 2 // integers after taking the absolute value
opN opID = 1 << 2 // full number (must be integer)
opF opID = 2 << 2 // fraction
opV opID = 3 << 2 // number of visible digits
opW opID = 4 << 2 // number of visible digits without trailing zeros
opBretonM opID = 5 << 2 // hard-wired rule for Breton
opItalian800 opID = 6 << 2 // hard-wired rule for Italian
opAzerbaijan00s opID = 7 << 2 // hard-wired rule for Azerbaijan
)
const (
// Use this plural form to indicate the next rule needs to match as well.
// The last condition in the list will have the correct plural form.
andNext = 0x7
formMask = 0x7
opShift = 3
// numN indicates the maximum integer, or maximum mod value, for which we
// have inclusion masks.
numN = 100
// The common denominator of the modulo that is taken.
maxMod = 100
)

194
vendor/golang.org/x/text/internal/number/data_test.go generated vendored Normal file
View file

@ -0,0 +1,194 @@
// This file was generated by go generate; DO NOT EDIT
package number
import "golang.org/x/text/internal/format/plural"
type pluralTest struct {
locales string
form plural.Form
integer []string
decimal []string
}
var ordinalTests = []pluralTest{ // 59 elements
0: {locales: "af am ar bg bs ce cs da de dsb el es et eu fa fi fy gl he hr hsb id in is iw ja km kn ko ky lt lv ml mn my nb nl pa pl prg pt root ru sh si sk sl sr sw ta te th tr ur uz zh zu", form: 0x0, integer: []string{"0~15", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
1: {locales: "sv", form: 0x2, integer: []string{"1", "2", "21", "22", "31", "32", "41", "42", "51", "52", "61", "62", "71", "72", "81", "82", "101", "1001"}, decimal: []string(nil)},
2: {locales: "sv", form: 0x0, integer: []string{"0", "3~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
3: {locales: "fil fr ga hy lo mo ms ro tl vi", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
4: {locales: "fil fr ga hy lo mo ms ro tl vi", form: 0x0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
5: {locales: "hu", form: 0x2, integer: []string{"1", "5"}, decimal: []string(nil)},
6: {locales: "hu", form: 0x0, integer: []string{"0", "2~4", "6~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
7: {locales: "ne", form: 0x2, integer: []string{"1~4"}, decimal: []string(nil)},
8: {locales: "ne", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
9: {locales: "be", form: 0x4, integer: []string{"2", "3", "22", "23", "32", "33", "42", "43", "52", "53", "62", "63", "72", "73", "82", "83", "102", "1002"}, decimal: []string(nil)},
10: {locales: "be", form: 0x0, integer: []string{"0", "1", "4~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
11: {locales: "uk", form: 0x4, integer: []string{"3", "23", "33", "43", "53", "63", "73", "83", "103", "1003"}, decimal: []string(nil)},
12: {locales: "uk", form: 0x0, integer: []string{"0~2", "4~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
13: {locales: "kk", form: 0x5, integer: []string{"6", "9", "10", "16", "19", "20", "26", "29", "30", "36", "39", "40", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
14: {locales: "kk", form: 0x0, integer: []string{"0~5", "7", "8", "11~15", "17", "18", "21", "101", "1001"}, decimal: []string(nil)},
15: {locales: "it", form: 0x5, integer: []string{"8", "11", "80", "800"}, decimal: []string(nil)},
16: {locales: "it", form: 0x0, integer: []string{"0~7", "9", "10", "12~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
17: {locales: "ka", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
18: {locales: "ka", form: 0x5, integer: []string{"0", "2~16", "102", "1002"}, decimal: []string(nil)},
19: {locales: "ka", form: 0x0, integer: []string{"21~36", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
20: {locales: "sq", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
21: {locales: "sq", form: 0x5, integer: []string{"4", "24", "34", "44", "54", "64", "74", "84", "104", "1004"}, decimal: []string(nil)},
22: {locales: "sq", form: 0x0, integer: []string{"0", "2", "3", "5~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
23: {locales: "en", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string(nil)},
24: {locales: "en", form: 0x3, integer: []string{"2", "22", "32", "42", "52", "62", "72", "82", "102", "1002"}, decimal: []string(nil)},
25: {locales: "en", form: 0x4, integer: []string{"3", "23", "33", "43", "53", "63", "73", "83", "103", "1003"}, decimal: []string(nil)},
26: {locales: "en", form: 0x0, integer: []string{"0", "4~18", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
27: {locales: "mr", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
28: {locales: "mr", form: 0x3, integer: []string{"2", "3"}, decimal: []string(nil)},
29: {locales: "mr", form: 0x4, integer: []string{"4"}, decimal: []string(nil)},
30: {locales: "mr", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
31: {locales: "ca", form: 0x2, integer: []string{"1", "3"}, decimal: []string(nil)},
32: {locales: "ca", form: 0x3, integer: []string{"2"}, decimal: []string(nil)},
33: {locales: "ca", form: 0x4, integer: []string{"4"}, decimal: []string(nil)},
34: {locales: "ca", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
35: {locales: "mk", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string(nil)},
36: {locales: "mk", form: 0x3, integer: []string{"2", "22", "32", "42", "52", "62", "72", "82", "102", "1002"}, decimal: []string(nil)},
37: {locales: "mk", form: 0x5, integer: []string{"7", "8", "27", "28", "37", "38", "47", "48", "57", "58", "67", "68", "77", "78", "87", "88", "107", "1007"}, decimal: []string(nil)},
38: {locales: "mk", form: 0x0, integer: []string{"0", "3~6", "9~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
39: {locales: "az", form: 0x2, integer: []string{"1", "2", "5", "7", "8", "11", "12", "15", "17", "18", "20~22", "25", "101", "1001"}, decimal: []string(nil)},
40: {locales: "az", form: 0x4, integer: []string{"3", "4", "13", "14", "23", "24", "33", "34", "43", "44", "53", "54", "63", "64", "73", "74", "100", "1003"}, decimal: []string(nil)},
41: {locales: "az", form: 0x5, integer: []string{"0", "6", "16", "26", "36", "40", "46", "56", "106", "1006"}, decimal: []string(nil)},
42: {locales: "az", form: 0x0, integer: []string{"9", "10", "19", "29", "30", "39", "49", "59", "69", "79", "109", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
43: {locales: "gu hi", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
44: {locales: "gu hi", form: 0x3, integer: []string{"2", "3"}, decimal: []string(nil)},
45: {locales: "gu hi", form: 0x4, integer: []string{"4"}, decimal: []string(nil)},
46: {locales: "gu hi", form: 0x5, integer: []string{"6"}, decimal: []string(nil)},
47: {locales: "gu hi", form: 0x0, integer: []string{"0", "5", "7~20", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
48: {locales: "as bn", form: 0x2, integer: []string{"1", "5", "7~10"}, decimal: []string(nil)},
49: {locales: "as bn", form: 0x3, integer: []string{"2", "3"}, decimal: []string(nil)},
50: {locales: "as bn", form: 0x4, integer: []string{"4"}, decimal: []string(nil)},
51: {locales: "as bn", form: 0x5, integer: []string{"6"}, decimal: []string(nil)},
52: {locales: "as bn", form: 0x0, integer: []string{"0", "11~25", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
53: {locales: "cy", form: 0x1, integer: []string{"0", "7~9"}, decimal: []string(nil)},
54: {locales: "cy", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
55: {locales: "cy", form: 0x3, integer: []string{"2"}, decimal: []string(nil)},
56: {locales: "cy", form: 0x4, integer: []string{"3", "4"}, decimal: []string(nil)},
57: {locales: "cy", form: 0x5, integer: []string{"5", "6"}, decimal: []string(nil)},
58: {locales: "cy", form: 0x0, integer: []string{"10~25", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
} // Size: 4272 bytes
var cardinalTests = []pluralTest{ // 115 elements
0: {locales: "bm bo dz id ig ii in ja jbo jv jw kde kea km ko lkt lo ms my nqo root sah ses sg th to vi wo yo zh", form: 0x0, integer: []string{"0~15", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
1: {locales: "am as bn fa gu hi kn mr zu", form: 0x2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.0", "0.00~0.04"}},
2: {locales: "am as bn fa gu hi kn mr zu", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"1.1~2.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
3: {locales: "ff fr hy kab", form: 0x2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.5"}},
4: {locales: "ff fr hy kab", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
5: {locales: "ast ca de en et fi fy gl it ji nl sv sw ur yi", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
6: {locales: "ast ca de en et fi fy gl it ji nl sv sw ur yi", form: 0x0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
7: {locales: "si", form: 0x2, integer: []string{"0", "1"}, decimal: []string{"0.0", "0.1", "1.0", "0.00", "0.01", "1.00", "0.000", "0.001", "1.000", "0.0000", "0.0001", "1.0000"}},
8: {locales: "si", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.2~0.9", "1.1~1.8", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
9: {locales: "ak bh guw ln mg nso pa ti wa", form: 0x2, integer: []string{"0", "1"}, decimal: []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"}},
10: {locales: "ak bh guw ln mg nso pa ti wa", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
11: {locales: "tzm", form: 0x2, integer: []string{"0", "1", "11~24"}, decimal: []string{"0.0", "1.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "20.0", "21.0", "22.0", "23.0", "24.0"}},
12: {locales: "tzm", form: 0x0, integer: []string{"2~10", "100~106", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
13: {locales: "pt", form: 0x2, integer: []string{"0", "1"}, decimal: []string{"0.0", "1.0", "0.00", "1.00", "0.000", "1.000", "0.0000", "1.0000"}},
14: {locales: "pt", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
15: {locales: "af asa az bem bez bg brx ce cgg chr ckb dv ee el eo es eu fo fur gsw ha haw hu jgo jmc ka kaj kcg kk kkj kl ks ksb ku ky lb lg mas mgo ml mn nah nb nd ne nn nnh no nr ny nyn om or os pap ps rm rof rwk saq sdh seh sn so sq ss ssy st syr ta te teo tig tk tn tr ts ug uz ve vo vun wae xh xog", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
16: {locales: "af asa az bem bez bg brx ce cgg chr ckb dv ee el eo es eu fo fur gsw ha haw hu jgo jmc ka kaj kcg kk kkj kl ks ksb ku ky lb lg mas mgo ml mn nah nb nd ne nn nnh no nr ny nyn om or os pap ps rm rof rwk saq sdh seh sn so sq ss ssy st syr ta te teo tig tk tn tr ts ug uz ve vo vun wae xh xog", form: 0x0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
17: {locales: "pt_PT", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
18: {locales: "pt_PT", form: 0x0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
19: {locales: "da", form: 0x2, integer: []string{"1"}, decimal: []string{"0.1~1.6"}},
20: {locales: "da", form: 0x0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "2.0~3.4", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
21: {locales: "is", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1~1.6", "10.1", "100.1", "1000.1"}},
22: {locales: "is", form: 0x0, integer: []string{"0", "2~16", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
23: {locales: "mk", form: 0x2, integer: []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
24: {locales: "mk", form: 0x0, integer: []string{"0", "2~10", "12~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.2~1.0", "1.2~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
25: {locales: "fil tl", form: 0x2, integer: []string{"0~3", "5", "7", "8", "10~13", "15", "17", "18", "20", "21", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.3", "0.5", "0.7", "0.8", "1.0~1.3", "1.5", "1.7", "1.8", "2.0", "2.1", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
26: {locales: "fil tl", form: 0x0, integer: []string{"4", "6", "9", "14", "16", "19", "24", "26", "104", "1004"}, decimal: []string{"0.4", "0.6", "0.9", "1.4", "1.6", "1.9", "2.4", "2.6", "10.4", "100.4", "1000.4"}},
27: {locales: "lv prg", form: 0x1, integer: []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
28: {locales: "lv prg", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1", "1.0", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
29: {locales: "lv prg", form: 0x0, integer: []string{"2~9", "22~29", "102", "1002"}, decimal: []string{"0.2~0.9", "1.2~1.9", "10.2", "100.2", "1000.2"}},
30: {locales: "lag", form: 0x1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
31: {locales: "lag", form: 0x2, integer: []string{"1"}, decimal: []string{"0.1~1.6"}},
32: {locales: "lag", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"2.0~3.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
33: {locales: "ksh", form: 0x1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
34: {locales: "ksh", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
35: {locales: "ksh", form: 0x0, integer: []string{"2~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
36: {locales: "iu kw naq se sma smi smj smn sms", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
37: {locales: "iu kw naq se sma smi smj smn sms", form: 0x3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
38: {locales: "iu kw naq se sma smi smj smn sms", form: 0x0, integer: []string{"0", "3~17", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
39: {locales: "shi", form: 0x2, integer: []string{"0", "1"}, decimal: []string{"0.0~1.0", "0.00~0.04"}},
40: {locales: "shi", form: 0x4, integer: []string{"2~10"}, decimal: []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "2.00", "3.00", "4.00", "5.00", "6.00", "7.00", "8.00"}},
41: {locales: "shi", form: 0x0, integer: []string{"11~26", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"1.1~1.9", "2.1~2.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
42: {locales: "mo ro", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
43: {locales: "mo ro", form: 0x4, integer: []string{"0", "2~16", "101", "1001"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
44: {locales: "mo ro", form: 0x0, integer: []string{"20~35", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
45: {locales: "bs hr sh sr", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
46: {locales: "bs hr sh sr", form: 0x4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string{"0.2~0.4", "1.2~1.4", "2.2~2.4", "3.2~3.4", "4.2~4.4", "5.2", "10.2", "100.2", "1000.2"}},
47: {locales: "bs hr sh sr", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
48: {locales: "gd", form: 0x2, integer: []string{"1", "11"}, decimal: []string{"1.0", "11.0", "1.00", "11.00", "1.000", "11.000", "1.0000"}},
49: {locales: "gd", form: 0x3, integer: []string{"2", "12"}, decimal: []string{"2.0", "12.0", "2.00", "12.00", "2.000", "12.000", "2.0000"}},
50: {locales: "gd", form: 0x4, integer: []string{"3~10", "13~19"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "19.0", "3.00"}},
51: {locales: "gd", form: 0x0, integer: []string{"0", "20~34", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
52: {locales: "sl", form: 0x2, integer: []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"}, decimal: []string(nil)},
53: {locales: "sl", form: 0x3, integer: []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"}, decimal: []string(nil)},
54: {locales: "sl", form: 0x4, integer: []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
55: {locales: "sl", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
56: {locales: "dsb hsb", form: 0x2, integer: []string{"1", "101", "201", "301", "401", "501", "601", "701", "1001"}, decimal: []string{"0.1", "1.1", "2.1", "3.1", "4.1", "5.1", "6.1", "7.1", "10.1", "100.1", "1000.1"}},
57: {locales: "dsb hsb", form: 0x3, integer: []string{"2", "102", "202", "302", "402", "502", "602", "702", "1002"}, decimal: []string{"0.2", "1.2", "2.2", "3.2", "4.2", "5.2", "6.2", "7.2", "10.2", "100.2", "1000.2"}},
58: {locales: "dsb hsb", form: 0x4, integer: []string{"3", "4", "103", "104", "203", "204", "303", "304", "403", "404", "503", "504", "603", "604", "703", "704", "1003"}, decimal: []string{"0.3", "0.4", "1.3", "1.4", "2.3", "2.4", "3.3", "3.4", "4.3", "4.4", "5.3", "5.4", "6.3", "6.4", "7.3", "7.4", "10.3", "100.3", "1000.3"}},
59: {locales: "dsb hsb", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "0.5~1.0", "1.5~2.0", "2.5~2.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
60: {locales: "he iw", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
61: {locales: "he iw", form: 0x3, integer: []string{"2"}, decimal: []string(nil)},
62: {locales: "he iw", form: 0x5, integer: []string{"20", "30", "40", "50", "60", "70", "80", "90", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
63: {locales: "he iw", form: 0x0, integer: []string{"0", "3~17", "101", "1001"}, decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
64: {locales: "cs sk", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
65: {locales: "cs sk", form: 0x4, integer: []string{"2~4"}, decimal: []string(nil)},
66: {locales: "cs sk", form: 0x5, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
67: {locales: "cs sk", form: 0x0, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
68: {locales: "pl", form: 0x2, integer: []string{"1"}, decimal: []string(nil)},
69: {locales: "pl", form: 0x4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string(nil)},
70: {locales: "pl", form: 0x5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
71: {locales: "pl", form: 0x0, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
72: {locales: "be", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"}},
73: {locales: "be", form: 0x4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string{"2.0", "3.0", "4.0", "22.0", "23.0", "24.0", "32.0", "33.0", "102.0", "1002.0"}},
74: {locales: "be", form: 0x5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "11.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
75: {locales: "be", form: 0x0, integer: []string(nil), decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"}},
76: {locales: "lt", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "71.0", "81.0", "101.0", "1001.0"}},
77: {locales: "lt", form: 0x4, integer: []string{"2~9", "22~29", "102", "1002"}, decimal: []string{"2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "22.0", "102.0", "1002.0"}},
78: {locales: "lt", form: 0x5, integer: []string(nil), decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.1", "1000.1"}},
79: {locales: "lt", form: 0x0, integer: []string{"0", "10~20", "30", "40", "50", "60", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
80: {locales: "mt", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
81: {locales: "mt", form: 0x4, integer: []string{"0", "2~10", "102~107", "1002"}, decimal: []string{"0.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "10.0", "102.0", "1002.0"}},
82: {locales: "mt", form: 0x5, integer: []string{"11~19", "111~117", "1011"}, decimal: []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"}},
83: {locales: "mt", form: 0x0, integer: []string{"20~35", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
84: {locales: "ru uk", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "71", "81", "101", "1001"}, decimal: []string(nil)},
85: {locales: "ru uk", form: 0x4, integer: []string{"2~4", "22~24", "32~34", "42~44", "52~54", "62", "102", "1002"}, decimal: []string(nil)},
86: {locales: "ru uk", form: 0x5, integer: []string{"0", "5~19", "100", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
87: {locales: "ru uk", form: 0x0, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
88: {locales: "br", form: 0x2, integer: []string{"1", "21", "31", "41", "51", "61", "81", "101", "1001"}, decimal: []string{"1.0", "21.0", "31.0", "41.0", "51.0", "61.0", "81.0", "101.0", "1001.0"}},
89: {locales: "br", form: 0x3, integer: []string{"2", "22", "32", "42", "52", "62", "82", "102", "1002"}, decimal: []string{"2.0", "22.0", "32.0", "42.0", "52.0", "62.0", "82.0", "102.0", "1002.0"}},
90: {locales: "br", form: 0x4, integer: []string{"3", "4", "9", "23", "24", "29", "33", "34", "39", "43", "44", "49", "103", "1003"}, decimal: []string{"3.0", "4.0", "9.0", "23.0", "24.0", "29.0", "33.0", "34.0", "103.0", "1003.0"}},
91: {locales: "br", form: 0x5, integer: []string{"1000000"}, decimal: []string{"1000000.0", "1000000.00", "1000000.000"}},
92: {locales: "br", form: 0x0, integer: []string{"0", "5~8", "10~20", "100", "1000", "10000", "100000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.0", "100.0", "1000.0", "10000.0", "100000.0"}},
93: {locales: "ga", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
94: {locales: "ga", form: 0x3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
95: {locales: "ga", form: 0x4, integer: []string{"3~6"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "3.00", "4.00", "5.00", "6.00", "3.000", "4.000", "5.000", "6.000", "3.0000", "4.0000", "5.0000", "6.0000"}},
96: {locales: "ga", form: 0x5, integer: []string{"7~10"}, decimal: []string{"7.0", "8.0", "9.0", "10.0", "7.00", "8.00", "9.00", "10.00", "7.000", "8.000", "9.000", "10.000", "7.0000", "8.0000", "9.0000", "10.0000"}},
97: {locales: "ga", form: 0x0, integer: []string{"0", "11~25", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.0~0.9", "1.1~1.6", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
98: {locales: "gv", form: 0x2, integer: []string{"1", "11", "21", "31", "41", "51", "61", "71", "101", "1001"}, decimal: []string(nil)},
99: {locales: "gv", form: 0x3, integer: []string{"2", "12", "22", "32", "42", "52", "62", "72", "102", "1002"}, decimal: []string(nil)},
100: {locales: "gv", form: 0x4, integer: []string{"0", "20", "40", "60", "80", "100", "120", "140", "1000", "10000", "100000", "1000000"}, decimal: []string(nil)},
101: {locales: "gv", form: 0x5, integer: []string(nil), decimal: []string{"0.0~1.5", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
102: {locales: "gv", form: 0x0, integer: []string{"3~10", "13~19", "23", "103", "1003"}, decimal: []string(nil)},
103: {locales: "ar", form: 0x1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
104: {locales: "ar", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
105: {locales: "ar", form: 0x3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
106: {locales: "ar", form: 0x4, integer: []string{"3~10", "103~110", "1003"}, decimal: []string{"3.0", "4.0", "5.0", "6.0", "7.0", "8.0", "9.0", "10.0", "103.0", "1003.0"}},
107: {locales: "ar", form: 0x5, integer: []string{"11~26", "111", "1011"}, decimal: []string{"11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", "18.0", "111.0", "1011.0"}},
108: {locales: "ar", form: 0x0, integer: []string{"100~102", "200~202", "300~302", "400~402", "500~502", "600", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.1", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
109: {locales: "cy", form: 0x1, integer: []string{"0"}, decimal: []string{"0.0", "0.00", "0.000", "0.0000"}},
110: {locales: "cy", form: 0x2, integer: []string{"1"}, decimal: []string{"1.0", "1.00", "1.000", "1.0000"}},
111: {locales: "cy", form: 0x3, integer: []string{"2"}, decimal: []string{"2.0", "2.00", "2.000", "2.0000"}},
112: {locales: "cy", form: 0x4, integer: []string{"3"}, decimal: []string{"3.0", "3.00", "3.000", "3.0000"}},
113: {locales: "cy", form: 0x5, integer: []string{"6"}, decimal: []string{"6.0", "6.00", "6.000", "6.0000"}},
114: {locales: "cy", form: 0x0, integer: []string{"4", "5", "7~20", "100", "1000", "10000", "100000", "1000000"}, decimal: []string{"0.1~0.9", "1.1~1.7", "10.0", "100.0", "1000.0", "10000.0", "100000.0", "1000000.0"}},
} // Size: 8304 bytes
// Total table size 12576 bytes (12KiB); checksum: 35F73741

416
vendor/golang.org/x/text/internal/number/decimal.go generated vendored Normal file
View file

@ -0,0 +1,416 @@
// Copyright 2009 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.
// TODO: use build tags once a low-level public API has been established in
// package strconv.
// Multiprecision decimal numbers.
// For floating-point formatting only; not general purpose.
// Only operations are assign and (binary) left/right shift.
// Can do binary floating point in multiprecision decimal precisely
// because 2 divides 10; cannot do decimal floating point
// in multiprecision binary precisely.
package number
type decimal struct {
d [800]byte // digits, big-endian representation
nd int // number of digits used
dp int // decimal point
neg bool
trunc bool // discarded nonzero digits beyond d[:nd]
}
func (a *decimal) String() string {
n := 10 + a.nd
if a.dp > 0 {
n += a.dp
}
if a.dp < 0 {
n += -a.dp
}
buf := make([]byte, n)
w := 0
switch {
case a.nd == 0:
return "0"
case a.dp <= 0:
// zeros fill space between decimal point and digits
buf[w] = '0'
w++
buf[w] = '.'
w++
w += digitZero(buf[w : w+-a.dp])
w += copy(buf[w:], a.d[0:a.nd])
case a.dp < a.nd:
// decimal point in middle of digits
w += copy(buf[w:], a.d[0:a.dp])
buf[w] = '.'
w++
w += copy(buf[w:], a.d[a.dp:a.nd])
default:
// zeros fill space between digits and decimal point
w += copy(buf[w:], a.d[0:a.nd])
w += digitZero(buf[w : w+a.dp-a.nd])
}
return string(buf[0:w])
}
func digitZero(dst []byte) int {
for i := range dst {
dst[i] = '0'
}
return len(dst)
}
// trim trailing zeros from number.
// (They are meaningless; the decimal point is tracked
// independent of the number of digits.)
func trim(a *decimal) {
for a.nd > 0 && a.d[a.nd-1] == '0' {
a.nd--
}
if a.nd == 0 {
a.dp = 0
}
}
// Assign v to a.
func (a *decimal) Assign(v uint64) {
var buf [24]byte
// Write reversed decimal in buf.
n := 0
for v > 0 {
v1 := v / 10
v -= 10 * v1
buf[n] = byte(v + '0')
n++
v = v1
}
// Reverse again to produce forward decimal in a.d.
a.nd = 0
for n--; n >= 0; n-- {
a.d[a.nd] = buf[n]
a.nd++
}
a.dp = a.nd
trim(a)
}
// Maximum shift that we can do in one pass without overflow.
// A uint has 32 or 64 bits, and we have to be able to accommodate 9<<k.
const uintSize = 32 << (^uint(0) >> 63)
const maxShift = uintSize - 4
// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow.
func rightShift(a *decimal, k uint) {
r := 0 // read pointer
w := 0 // write pointer
// Pick up enough leading digits to cover first shift.
var n uint
for ; n>>k == 0; r++ {
if r >= a.nd {
if n == 0 {
// a == 0; shouldn't get here, but handle anyway.
a.nd = 0
return
}
for n>>k == 0 {
n = n * 10
r++
}
break
}
c := uint(a.d[r])
n = n*10 + c - '0'
}
a.dp -= r - 1
// Pick up a digit, put down a digit.
for ; r < a.nd; r++ {
c := uint(a.d[r])
dig := n >> k
n -= dig << k
a.d[w] = byte(dig + '0')
w++
n = n*10 + c - '0'
}
// Put down extra digits.
for n > 0 {
dig := n >> k
n -= dig << k
if w < len(a.d) {
a.d[w] = byte(dig + '0')
w++
} else if dig > 0 {
a.trunc = true
}
n = n * 10
}
a.nd = w
trim(a)
}
// Cheat sheet for left shift: table indexed by shift count giving
// number of new digits that will be introduced by that shift.
//
// For example, leftcheats[4] = {2, "625"}. That means that
// if we are shifting by 4 (multiplying by 16), it will add 2 digits
// when the string prefix is "625" through "999", and one fewer digit
// if the string prefix is "000" through "624".
//
// Credit for this trick goes to Ken.
type leftCheat struct {
delta int // number of new digits
cutoff string // minus one digit if original < a.
}
var leftcheats = []leftCheat{
// Leading digits of 1/2^i = 5^i.
// 5^23 is not an exact 64-bit floating point number,
// so have to use bc for the math.
// Go up to 60 to be large enough for 32bit and 64bit platforms.
/*
seq 60 | sed 's/^/5^/' | bc |
awk 'BEGIN{ print "\t{ 0, \"\" }," }
{
log2 = log(2)/log(10)
printf("\t{ %d, \"%s\" },\t// * %d\n",
int(log2*NR+1), $0, 2**NR)
}'
*/
{0, ""},
{1, "5"}, // * 2
{1, "25"}, // * 4
{1, "125"}, // * 8
{2, "625"}, // * 16
{2, "3125"}, // * 32
{2, "15625"}, // * 64
{3, "78125"}, // * 128
{3, "390625"}, // * 256
{3, "1953125"}, // * 512
{4, "9765625"}, // * 1024
{4, "48828125"}, // * 2048
{4, "244140625"}, // * 4096
{4, "1220703125"}, // * 8192
{5, "6103515625"}, // * 16384
{5, "30517578125"}, // * 32768
{5, "152587890625"}, // * 65536
{6, "762939453125"}, // * 131072
{6, "3814697265625"}, // * 262144
{6, "19073486328125"}, // * 524288
{7, "95367431640625"}, // * 1048576
{7, "476837158203125"}, // * 2097152
{7, "2384185791015625"}, // * 4194304
{7, "11920928955078125"}, // * 8388608
{8, "59604644775390625"}, // * 16777216
{8, "298023223876953125"}, // * 33554432
{8, "1490116119384765625"}, // * 67108864
{9, "7450580596923828125"}, // * 134217728
{9, "37252902984619140625"}, // * 268435456
{9, "186264514923095703125"}, // * 536870912
{10, "931322574615478515625"}, // * 1073741824
{10, "4656612873077392578125"}, // * 2147483648
{10, "23283064365386962890625"}, // * 4294967296
{10, "116415321826934814453125"}, // * 8589934592
{11, "582076609134674072265625"}, // * 17179869184
{11, "2910383045673370361328125"}, // * 34359738368
{11, "14551915228366851806640625"}, // * 68719476736
{12, "72759576141834259033203125"}, // * 137438953472
{12, "363797880709171295166015625"}, // * 274877906944
{12, "1818989403545856475830078125"}, // * 549755813888
{13, "9094947017729282379150390625"}, // * 1099511627776
{13, "45474735088646411895751953125"}, // * 2199023255552
{13, "227373675443232059478759765625"}, // * 4398046511104
{13, "1136868377216160297393798828125"}, // * 8796093022208
{14, "5684341886080801486968994140625"}, // * 17592186044416
{14, "28421709430404007434844970703125"}, // * 35184372088832
{14, "142108547152020037174224853515625"}, // * 70368744177664
{15, "710542735760100185871124267578125"}, // * 140737488355328
{15, "3552713678800500929355621337890625"}, // * 281474976710656
{15, "17763568394002504646778106689453125"}, // * 562949953421312
{16, "88817841970012523233890533447265625"}, // * 1125899906842624
{16, "444089209850062616169452667236328125"}, // * 2251799813685248
{16, "2220446049250313080847263336181640625"}, // * 4503599627370496
{16, "11102230246251565404236316680908203125"}, // * 9007199254740992
{17, "55511151231257827021181583404541015625"}, // * 18014398509481984
{17, "277555756156289135105907917022705078125"}, // * 36028797018963968
{17, "1387778780781445675529539585113525390625"}, // * 72057594037927936
{18, "6938893903907228377647697925567626953125"}, // * 144115188075855872
{18, "34694469519536141888238489627838134765625"}, // * 288230376151711744
{18, "173472347597680709441192448139190673828125"}, // * 576460752303423488
{19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976
}
// Is the leading prefix of b lexicographically less than s?
func prefixIsLessThan(b []byte, s string) bool {
for i := 0; i < len(s); i++ {
if i >= len(b) {
return true
}
if b[i] != s[i] {
return b[i] < s[i]
}
}
return false
}
// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow.
func leftShift(a *decimal, k uint) {
delta := leftcheats[k].delta
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
delta--
}
r := a.nd // read index
w := a.nd + delta // write index
// Pick up a digit, put down a digit.
var n uint
for r--; r >= 0; r-- {
n += (uint(a.d[r]) - '0') << k
quo := n / 10
rem := n - 10*quo
w--
if w < len(a.d) {
a.d[w] = byte(rem + '0')
} else if rem != 0 {
a.trunc = true
}
n = quo
}
// Put down extra digits.
for n > 0 {
quo := n / 10
rem := n - 10*quo
w--
if w < len(a.d) {
a.d[w] = byte(rem + '0')
} else if rem != 0 {
a.trunc = true
}
n = quo
}
a.nd += delta
if a.nd >= len(a.d) {
a.nd = len(a.d)
}
a.dp += delta
trim(a)
}
// Binary shift left (k > 0) or right (k < 0).
func (a *decimal) Shift(k int) {
switch {
case a.nd == 0:
// nothing to do: a == 0
case k > 0:
for k > maxShift {
leftShift(a, maxShift)
k -= maxShift
}
leftShift(a, uint(k))
case k < 0:
for k < -maxShift {
rightShift(a, maxShift)
k += maxShift
}
rightShift(a, uint(-k))
}
}
// If we chop a at nd digits, should we round up?
func shouldRoundUp(a *decimal, nd int) bool {
if nd < 0 || nd >= a.nd {
return false
}
if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
// if we truncated, a little higher than what's recorded - always round up
if a.trunc {
return true
}
return nd > 0 && (a.d[nd-1]-'0')%2 != 0
}
// not halfway - digit tells all
return a.d[nd] >= '5'
}
// Round a to nd digits (or fewer).
// If nd is zero, it means we're rounding
// just to the left of the digits, as in
// 0.09 -> 0.1.
func (a *decimal) Round(nd int) {
if nd < 0 || nd >= a.nd {
return
}
if shouldRoundUp(a, nd) {
a.RoundUp(nd)
} else {
a.RoundDown(nd)
}
}
// Round a down to nd digits (or fewer).
func (a *decimal) RoundDown(nd int) {
if nd < 0 || nd >= a.nd {
return
}
a.nd = nd
trim(a)
}
// Round a up to nd digits (or fewer).
func (a *decimal) RoundUp(nd int) {
if nd < 0 || nd >= a.nd {
return
}
// round up
for i := nd - 1; i >= 0; i-- {
c := a.d[i]
if c < '9' { // can stop after this digit
a.d[i]++
a.nd = i + 1
return
}
}
// Number is all 9s.
// Change to single 1 with adjusted decimal point.
a.d[0] = '1'
a.nd = 1
a.dp++
}
// Extract integer part, rounded appropriately.
// No guarantees about overflow.
func (a *decimal) RoundedInteger() uint64 {
if a.dp > 20 {
return 0xFFFFFFFFFFFFFFFF
}
var i int
n := uint64(0)
for i = 0; i < a.dp && i < a.nd; i++ {
n = n*10 + uint64(a.d[i]-'0')
}
for ; i < a.dp; i++ {
n *= 10
}
if shouldRoundUp(a, a.dp) {
n++
}
return n
}

671
vendor/golang.org/x/text/internal/number/extfloat.go generated vendored Normal file
View file

@ -0,0 +1,671 @@
// Copyright 2011 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.
// TODO: use build tags once a low-level public API has been established in
// package strconv.
package number
// An extFloat represents an extended floating-point number, with more
// precision than a float64. It does not try to save bits: the
// number represented by the structure is mant*(2^exp), with a negative
// sign if neg is true.
type extFloat struct {
mant uint64
exp int
neg bool
}
// Powers of ten taken from double-conversion library.
// http://code.google.com/p/double-conversion/
const (
firstPowerOfTen = -348
stepPowerOfTen = 8
)
var smallPowersOfTen = [...]extFloat{
{1 << 63, -63, false}, // 1
{0xa << 60, -60, false}, // 1e1
{0x64 << 57, -57, false}, // 1e2
{0x3e8 << 54, -54, false}, // 1e3
{0x2710 << 50, -50, false}, // 1e4
{0x186a0 << 47, -47, false}, // 1e5
{0xf4240 << 44, -44, false}, // 1e6
{0x989680 << 40, -40, false}, // 1e7
}
var powersOfTen = [...]extFloat{
{0xfa8fd5a0081c0288, -1220, false}, // 10^-348
{0xbaaee17fa23ebf76, -1193, false}, // 10^-340
{0x8b16fb203055ac76, -1166, false}, // 10^-332
{0xcf42894a5dce35ea, -1140, false}, // 10^-324
{0x9a6bb0aa55653b2d, -1113, false}, // 10^-316
{0xe61acf033d1a45df, -1087, false}, // 10^-308
{0xab70fe17c79ac6ca, -1060, false}, // 10^-300
{0xff77b1fcbebcdc4f, -1034, false}, // 10^-292
{0xbe5691ef416bd60c, -1007, false}, // 10^-284
{0x8dd01fad907ffc3c, -980, false}, // 10^-276
{0xd3515c2831559a83, -954, false}, // 10^-268
{0x9d71ac8fada6c9b5, -927, false}, // 10^-260
{0xea9c227723ee8bcb, -901, false}, // 10^-252
{0xaecc49914078536d, -874, false}, // 10^-244
{0x823c12795db6ce57, -847, false}, // 10^-236
{0xc21094364dfb5637, -821, false}, // 10^-228
{0x9096ea6f3848984f, -794, false}, // 10^-220
{0xd77485cb25823ac7, -768, false}, // 10^-212
{0xa086cfcd97bf97f4, -741, false}, // 10^-204
{0xef340a98172aace5, -715, false}, // 10^-196
{0xb23867fb2a35b28e, -688, false}, // 10^-188
{0x84c8d4dfd2c63f3b, -661, false}, // 10^-180
{0xc5dd44271ad3cdba, -635, false}, // 10^-172
{0x936b9fcebb25c996, -608, false}, // 10^-164
{0xdbac6c247d62a584, -582, false}, // 10^-156
{0xa3ab66580d5fdaf6, -555, false}, // 10^-148
{0xf3e2f893dec3f126, -529, false}, // 10^-140
{0xb5b5ada8aaff80b8, -502, false}, // 10^-132
{0x87625f056c7c4a8b, -475, false}, // 10^-124
{0xc9bcff6034c13053, -449, false}, // 10^-116
{0x964e858c91ba2655, -422, false}, // 10^-108
{0xdff9772470297ebd, -396, false}, // 10^-100
{0xa6dfbd9fb8e5b88f, -369, false}, // 10^-92
{0xf8a95fcf88747d94, -343, false}, // 10^-84
{0xb94470938fa89bcf, -316, false}, // 10^-76
{0x8a08f0f8bf0f156b, -289, false}, // 10^-68
{0xcdb02555653131b6, -263, false}, // 10^-60
{0x993fe2c6d07b7fac, -236, false}, // 10^-52
{0xe45c10c42a2b3b06, -210, false}, // 10^-44
{0xaa242499697392d3, -183, false}, // 10^-36
{0xfd87b5f28300ca0e, -157, false}, // 10^-28
{0xbce5086492111aeb, -130, false}, // 10^-20
{0x8cbccc096f5088cc, -103, false}, // 10^-12
{0xd1b71758e219652c, -77, false}, // 10^-4
{0x9c40000000000000, -50, false}, // 10^4
{0xe8d4a51000000000, -24, false}, // 10^12
{0xad78ebc5ac620000, 3, false}, // 10^20
{0x813f3978f8940984, 30, false}, // 10^28
{0xc097ce7bc90715b3, 56, false}, // 10^36
{0x8f7e32ce7bea5c70, 83, false}, // 10^44
{0xd5d238a4abe98068, 109, false}, // 10^52
{0x9f4f2726179a2245, 136, false}, // 10^60
{0xed63a231d4c4fb27, 162, false}, // 10^68
{0xb0de65388cc8ada8, 189, false}, // 10^76
{0x83c7088e1aab65db, 216, false}, // 10^84
{0xc45d1df942711d9a, 242, false}, // 10^92
{0x924d692ca61be758, 269, false}, // 10^100
{0xda01ee641a708dea, 295, false}, // 10^108
{0xa26da3999aef774a, 322, false}, // 10^116
{0xf209787bb47d6b85, 348, false}, // 10^124
{0xb454e4a179dd1877, 375, false}, // 10^132
{0x865b86925b9bc5c2, 402, false}, // 10^140
{0xc83553c5c8965d3d, 428, false}, // 10^148
{0x952ab45cfa97a0b3, 455, false}, // 10^156
{0xde469fbd99a05fe3, 481, false}, // 10^164
{0xa59bc234db398c25, 508, false}, // 10^172
{0xf6c69a72a3989f5c, 534, false}, // 10^180
{0xb7dcbf5354e9bece, 561, false}, // 10^188
{0x88fcf317f22241e2, 588, false}, // 10^196
{0xcc20ce9bd35c78a5, 614, false}, // 10^204
{0x98165af37b2153df, 641, false}, // 10^212
{0xe2a0b5dc971f303a, 667, false}, // 10^220
{0xa8d9d1535ce3b396, 694, false}, // 10^228
{0xfb9b7cd9a4a7443c, 720, false}, // 10^236
{0xbb764c4ca7a44410, 747, false}, // 10^244
{0x8bab8eefb6409c1a, 774, false}, // 10^252
{0xd01fef10a657842c, 800, false}, // 10^260
{0x9b10a4e5e9913129, 827, false}, // 10^268
{0xe7109bfba19c0c9d, 853, false}, // 10^276
{0xac2820d9623bf429, 880, false}, // 10^284
{0x80444b5e7aa7cf85, 907, false}, // 10^292
{0xbf21e44003acdd2d, 933, false}, // 10^300
{0x8e679c2f5e44ff8f, 960, false}, // 10^308
{0xd433179d9c8cb841, 986, false}, // 10^316
{0x9e19db92b4e31ba9, 1013, false}, // 10^324
{0xeb96bf6ebadf77d9, 1039, false}, // 10^332
{0xaf87023b9bf0ee6b, 1066, false}, // 10^340
}
// floatBits returns the bits of the float64 that best approximates
// the extFloat passed as receiver. Overflow is set to true if
// the resulting float64 is ±Inf.
func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) {
f.Normalize()
exp := f.exp + 63
// Exponent too small.
if exp < flt.bias+1 {
n := flt.bias + 1 - exp
f.mant >>= uint(n)
exp += n
}
// Extract 1+flt.mantbits bits from the 64-bit mantissa.
mant := f.mant >> (63 - flt.mantbits)
if f.mant&(1<<(62-flt.mantbits)) != 0 {
// Round up.
mant += 1
}
// Rounding might have added a bit; shift down.
if mant == 2<<flt.mantbits {
mant >>= 1
exp++
}
// Infinities.
if exp-flt.bias >= 1<<flt.expbits-1 {
// ±Inf
mant = 0
exp = 1<<flt.expbits - 1 + flt.bias
overflow = true
} else if mant&(1<<flt.mantbits) == 0 {
// Denormalized?
exp = flt.bias
}
// Assemble bits.
bits = mant & (uint64(1)<<flt.mantbits - 1)
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
if f.neg {
bits |= 1 << (flt.mantbits + flt.expbits)
}
return
}
// AssignComputeBounds sets f to the floating point value
// defined by mant, exp and precision given by flt. It returns
// lower, upper such that any number in the closed interval
// [lower, upper] is converted back to the same floating point number.
func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
f.mant = mant
f.exp = exp - int(flt.mantbits)
f.neg = neg
if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
// An exact integer
f.mant >>= uint(-f.exp)
f.exp = 0
return *f, *f
}
expBiased := exp - flt.bias
upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
if mant != 1<<flt.mantbits || expBiased == 1 {
lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
} else {
lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
}
return
}
// Normalize normalizes f so that the highest bit of the mantissa is
// set, and returns the number by which the mantissa was left-shifted.
func (f *extFloat) Normalize() (shift uint) {
mant, exp := f.mant, f.exp
if mant == 0 {
return 0
}
if mant>>(64-32) == 0 {
mant <<= 32
exp -= 32
}
if mant>>(64-16) == 0 {
mant <<= 16
exp -= 16
}
if mant>>(64-8) == 0 {
mant <<= 8
exp -= 8
}
if mant>>(64-4) == 0 {
mant <<= 4
exp -= 4
}
if mant>>(64-2) == 0 {
mant <<= 2
exp -= 2
}
if mant>>(64-1) == 0 {
mant <<= 1
exp -= 1
}
shift = uint(f.exp - exp)
f.mant, f.exp = mant, exp
return
}
// Multiply sets f to the product f*g: the result is correctly rounded,
// but not normalized.
func (f *extFloat) Multiply(g extFloat) {
fhi, flo := f.mant>>32, uint64(uint32(f.mant))
ghi, glo := g.mant>>32, uint64(uint32(g.mant))
// Cross products.
cross1 := fhi * glo
cross2 := flo * ghi
// f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo
f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32)
rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32)
// Round up.
rem += (1 << 31)
f.mant += (rem >> 32)
f.exp = f.exp + g.exp + 64
}
var uint64pow10 = [...]uint64{
1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
}
// AssignDecimal sets f to an approximate value mantissa*10^exp. It
// reports whether the value represented by f is guaranteed to be the
// best approximation of d after being rounded to a float64 or
// float32 depending on flt.
func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) {
const uint64digits = 19
const errorscale = 8
errors := 0 // An upper bound for error, computed in errorscale*ulp.
if trunc {
// the decimal number was truncated.
errors += errorscale / 2
}
f.mant = mantissa
f.exp = 0
f.neg = neg
// Multiply by powers of ten.
i := (exp10 - firstPowerOfTen) / stepPowerOfTen
if exp10 < firstPowerOfTen || i >= len(powersOfTen) {
return false
}
adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
// We multiply by exp%step
if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] {
// We can multiply the mantissa exactly.
f.mant *= uint64pow10[adjExp]
f.Normalize()
} else {
f.Normalize()
f.Multiply(smallPowersOfTen[adjExp])
errors += errorscale / 2
}
// We multiply by 10 to the exp - exp%step.
f.Multiply(powersOfTen[i])
if errors > 0 {
errors += 1
}
errors += errorscale / 2
// Normalize
shift := f.Normalize()
errors <<= shift
// Now f is a good approximation of the decimal.
// Check whether the error is too large: that is, if the mantissa
// is perturbated by the error, the resulting float64 will change.
// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
//
// In many cases the approximation will be good enough.
denormalExp := flt.bias - 63
var extrabits uint
if f.exp <= denormalExp {
// f.mant * 2^f.exp is smaller than 2^(flt.bias+1).
extrabits = 63 - flt.mantbits + 1 + uint(denormalExp-f.exp)
} else {
extrabits = 63 - flt.mantbits
}
halfway := uint64(1) << (extrabits - 1)
mant_extra := f.mant & (1<<extrabits - 1)
// Do a signed comparison here! If the error estimate could make
// the mantissa round differently for the conversion to double,
// then we can't give a definite answer.
if int64(halfway)-int64(errors) < int64(mant_extra) &&
int64(mant_extra) < int64(halfway)+int64(errors) {
return false
}
return true
}
// Frexp10 is an analogue of math.Frexp for decimal powers. It scales
// f by an approximate power of ten 10^-exp, and returns exp10, so
// that f*10^exp10 has the same value as the old f, up to an ulp,
// as well as the index of 10^-exp in the powersOfTen table.
func (f *extFloat) frexp10() (exp10, index int) {
// The constants expMin and expMax constrain the final value of the
// binary exponent of f. We want a small integral part in the result
// because finding digits of an integer requires divisions, whereas
// digits of the fractional part can be found by repeatedly multiplying
// by 10.
const expMin = -60
const expMax = -32
// Find power of ten such that x * 10^n has a binary exponent
// between expMin and expMax.
approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
Loop:
for {
exp := f.exp + powersOfTen[i].exp + 64
switch {
case exp < expMin:
i++
case exp > expMax:
i--
default:
break Loop
}
}
// Apply the desired decimal shift on f. It will have exponent
// in the desired range. This is multiplication by 10^-exp10.
f.Multiply(powersOfTen[i])
return -(firstPowerOfTen + i*stepPowerOfTen), i
}
// frexp10Many applies a common shift by a power of ten to a, b, c.
func frexp10Many(a, b, c *extFloat) (exp10 int) {
exp10, i := c.frexp10()
a.Multiply(powersOfTen[i])
b.Multiply(powersOfTen[i])
return
}
// FixedDecimal stores in d the first n significant digits
// of the decimal representation of f. It returns false
// if it cannot be sure of the answer.
func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
if f.mant == 0 {
d.nd = 0
d.dp = 0
d.neg = f.neg
return true
}
if n == 0 {
panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
}
// Multiply by an appropriate power of ten to have a reasonable
// number to process.
f.Normalize()
exp10, _ := f.frexp10()
shift := uint(-f.exp)
integer := uint32(f.mant >> shift)
fraction := f.mant - (uint64(integer) << shift)
ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
// Write exactly n digits to d.
needed := n // how many digits are left to write.
integerDigits := 0 // the number of decimal digits of integer.
pow10 := uint64(1) // the power of ten by which f was scaled.
for i, pow := 0, uint64(1); i < 20; i++ {
if pow > uint64(integer) {
integerDigits = i
break
}
pow *= 10
}
rest := integer
if integerDigits > needed {
// the integral part is already large, trim the last digits.
pow10 = uint64pow10[integerDigits-needed]
integer /= uint32(pow10)
rest -= integer * uint32(pow10)
} else {
rest = 0
}
// Write the digits of integer: the digits of rest are omitted.
var buf [32]byte
pos := len(buf)
for v := integer; v > 0; {
v1 := v / 10
v -= 10 * v1
pos--
buf[pos] = byte(v + '0')
v = v1
}
for i := pos; i < len(buf); i++ {
d.d[i-pos] = buf[i]
}
nd := len(buf) - pos
d.nd = nd
d.dp = integerDigits + exp10
needed -= nd
if needed > 0 {
if rest != 0 || pow10 != 1 {
panic("strconv: internal error, rest != 0 but needed > 0")
}
// Emit digits for the fractional part. Each time, 10*fraction
// fits in a uint64 without overflow.
for needed > 0 {
fraction *= 10
ε *= 10 // the uncertainty scales as we multiply by ten.
if 2*ε > 1<<shift {
// the error is so large it could modify which digit to write, abort.
return false
}
digit := fraction >> shift
d.d[nd] = byte(digit + '0')
fraction -= digit << shift
nd++
needed--
}
d.nd = nd
}
// We have written a truncation of f (a numerator / 10^d.dp). The remaining part
// can be interpreted as a small number (< 1) to be added to the last digit of the
// numerator.
//
// If rest > 0, the amount is:
// (rest<<shift | fraction) / (pow10 << shift)
// fraction being known with a ±ε uncertainty.
// The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
//
// If rest = 0, pow10 == 1 and the amount is
// fraction / (1 << shift)
// fraction being known with a ±ε uncertainty.
//
// We pass this information to the rounding routine for adjustment.
ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
if !ok {
return false
}
// Trim trailing zeros.
for i := d.nd - 1; i >= 0; i-- {
if d.d[i] != '0' {
d.nd = i + 1
break
}
}
return true
}
// adjustLastDigitFixed assumes d contains the representation of the integral part
// of some number, whose fractional part is num / (den << shift). The numerator
// num is only known up to an uncertainty of size ε, assumed to be less than
// (den << shift)/2.
//
// It will increase the last digit by one to account for correct rounding, typically
// when the fractional part is greater than 1/2, and will return false if ε is such
// that no correct answer can be given.
func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
if num > den<<shift {
panic("strconv: num > den<<shift in adjustLastDigitFixed")
}
if 2*ε > den<<shift {
panic("strconv: ε > (den<<shift)/2")
}
if 2*(num+ε) < den<<shift {
return true
}
if 2*(num-ε) > den<<shift {
// increment d by 1.
i := d.nd - 1
for ; i >= 0; i-- {
if d.d[i] == '9' {
d.nd--
} else {
break
}
}
if i < 0 {
d.d[0] = '1'
d.nd = 1
d.dp++
} else {
d.d[i]++
}
return true
}
return false
}
// ShortestDecimal stores in d the shortest decimal representation of f
// which belongs to the open interval (lower, upper), where f is supposed
// to lie. It returns false whenever the result is unsure. The implementation
// uses the Grisu3 algorithm.
func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
if f.mant == 0 {
d.nd = 0
d.dp = 0
d.neg = f.neg
return true
}
if f.exp == 0 && *lower == *f && *lower == *upper {
// an exact integer.
var buf [24]byte
n := len(buf) - 1
for v := f.mant; v > 0; {
v1 := v / 10
v -= 10 * v1
buf[n] = byte(v + '0')
n--
v = v1
}
nd := len(buf) - n - 1
for i := 0; i < nd; i++ {
d.d[i] = buf[n+1+i]
}
d.nd, d.dp = nd, nd
for d.nd > 0 && d.d[d.nd-1] == '0' {
d.nd--
}
if d.nd == 0 {
d.dp = 0
}
d.neg = f.neg
return true
}
upper.Normalize()
// Uniformize exponents.
if f.exp > upper.exp {
f.mant <<= uint(f.exp - upper.exp)
f.exp = upper.exp
}
if lower.exp > upper.exp {
lower.mant <<= uint(lower.exp - upper.exp)
lower.exp = upper.exp
}
exp10 := frexp10Many(lower, f, upper)
// Take a safety margin due to rounding in frexp10Many, but we lose precision.
upper.mant++
lower.mant--
// The shortest representation of f is either rounded up or down, but
// in any case, it is a truncation of upper.
shift := uint(-upper.exp)
integer := uint32(upper.mant >> shift)
fraction := upper.mant - (uint64(integer) << shift)
// How far we can go down from upper until the result is wrong.
allowance := upper.mant - lower.mant
// How far we should go to get a very precise result.
targetDiff := upper.mant - f.mant
// Count integral digits: there are at most 10.
var integerDigits int
for i, pow := 0, uint64(1); i < 20; i++ {
if pow > uint64(integer) {
integerDigits = i
break
}
pow *= 10
}
for i := 0; i < integerDigits; i++ {
pow := uint64pow10[integerDigits-i-1]
digit := integer / uint32(pow)
d.d[i] = byte(digit + '0')
integer -= digit * uint32(pow)
// evaluate whether we should stop.
if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance {
d.nd = i + 1
d.dp = integerDigits + exp10
d.neg = f.neg
// Sometimes allowance is so large the last digit might need to be
// decremented to get closer to f.
return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2)
}
}
d.nd = integerDigits
d.dp = d.nd + exp10
d.neg = f.neg
// Compute digits of the fractional part. At each step fraction does not
// overflow. The choice of minExp implies that fraction is less than 2^60.
var digit int
multiplier := uint64(1)
for {
fraction *= 10
multiplier *= 10
digit = int(fraction >> shift)
d.d[d.nd] = byte(digit + '0')
d.nd++
fraction -= uint64(digit) << shift
if fraction < allowance*multiplier {
// We are in the admissible range. Note that if allowance is about to
// overflow, that is, allowance > 2^64/10, the condition is automatically
// true due to the limited range of fraction.
return adjustLastDigit(d,
fraction, targetDiff*multiplier, allowance*multiplier,
1<<shift, multiplier*2)
}
}
}
// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
// It assumes that a decimal digit is worth ulpDecimal*ε, and that
// all data is known with a error estimate of ulpBinary*ε.
func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
if ulpDecimal < 2*ulpBinary {
// Approximation is too wide.
return false
}
for currentDiff+ulpDecimal/2+ulpBinary < targetDiff {
d.d[d.nd-1]--
currentDiff += ulpDecimal
}
if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary {
// we have two choices, and don't know what to do.
return false
}
if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary {
// we went too far
return false
}
if d.nd == 1 && d.d[0] == '0' {
// the number has actually reached zero.
d.nd = 0
d.dp = 0
}
return true
}

448
vendor/golang.org/x/text/internal/number/ftoa.go generated vendored Normal file
View file

@ -0,0 +1,448 @@
// Copyright 2009 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.
// TODO: use build tags once a low-level public API has been established in
// package strconv.
// Binary to decimal floating point conversion.
// Algorithm:
// 1) store mantissa in multiprecision decimal
// 2) shift decimal by exponent
// 3) read digits out & format
package number
import "math"
var optimize = true
// TODO: move elsewhere?
type floatInfo struct {
mantbits uint
expbits uint
bias int
}
var float32info = floatInfo{23, 8, -127}
var float64info = floatInfo{52, 11, -1023}
// genericFtoa converts the floating-point number f to a string,
// according to the format fmt and precision prec. It rounds the
// result assuming that the original was obtained from a floating-point
// value of bitSize bits (32 for float32, 64 for float64).
//
// The format fmt is one of
// 'b' (-ddddp±ddd, a binary exponent),
// 'e' (-d.dddde±dd, a decimal exponent),
// 'E' (-d.ddddE±dd, a decimal exponent),
// 'f' (-ddd.dddd, no exponent),
// 'g' ('e' for large exponents, 'f' otherwise), or
// 'G' ('E' for large exponents, 'f' otherwise).
//
// The precision prec controls the number of digits
// (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats.
// For 'e', 'E', and 'f' it is the number of digits after the decimal point.
// For 'g' and 'G' it is the total number of digits.
// The special precision -1 uses the smallest number of digits
// necessary such that ParseFloat will return f exactly.
func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
var bits uint64
var flt *floatInfo
switch bitSize {
case 32:
bits = uint64(math.Float32bits(float32(val)))
flt = &float32info
case 64:
bits = math.Float64bits(val)
flt = &float64info
default:
panic("strconv: illegal AppendFloat/FormatFloat bitSize")
}
neg := bits>>(flt.expbits+flt.mantbits) != 0
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
mant := bits & (uint64(1)<<flt.mantbits - 1)
switch exp {
case 1<<flt.expbits - 1:
// Inf, NaN
var s string
switch {
case mant != 0:
s = "NaN"
case neg:
s = "-Inf"
default:
s = "+Inf"
}
return append(dst, s...)
case 0:
// denormalized
exp++
default:
// add implicit top bit
mant |= uint64(1) << flt.mantbits
}
exp += flt.bias
// Pick off easy binary format.
if fmt == 'b' {
return fmtB(dst, neg, mant, exp, flt)
}
if !optimize {
return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
var digs decimalSlice
ok := false
// Negative precision means "only as much as needed to be exact."
shortest := prec < 0
if shortest {
// Try Grisu3 algorithm.
f := new(extFloat)
lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
var buf [32]byte
digs.d = buf[:]
ok = f.ShortestDecimal(&digs, &lower, &upper)
if !ok {
return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = max(digs.nd-1, 0)
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
prec = digs.nd
}
} else if fmt != 'f' {
// Fixed number of digits.
digits := prec
switch fmt {
case 'e', 'E':
digits++
case 'g', 'G':
if prec == 0 {
prec = 1
}
digits = prec
}
if digits <= 15 {
// try fast algorithm when the number of digits is reasonable.
var buf [24]byte
digs.d = buf[:]
f := extFloat{mant, exp - int(flt.mantbits), neg}
ok = f.FixedDecimal(&digs, digits)
}
}
if !ok {
return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
return formatDigits(dst, shortest, neg, digs, prec, fmt)
}
// bigFtoa uses multiprecision computations to format a float.
func bigFtoa(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
d := new(decimal)
d.Assign(mant)
d.Shift(exp - int(flt.mantbits))
var digs decimalSlice
shortest := prec < 0
if shortest {
roundShortest(d, mant, exp, flt)
digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = digs.nd - 1
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
prec = digs.nd
}
} else {
// Round appropriately.
switch fmt {
case 'e', 'E':
d.Round(prec + 1)
case 'f':
d.Round(d.dp + prec)
case 'g', 'G':
if prec == 0 {
prec = 1
}
d.Round(prec)
}
digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
}
return formatDigits(dst, shortest, neg, digs, prec, fmt)
}
func formatDigits(dst []byte, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) []byte {
switch fmt {
case 'e', 'E':
return fmtE(dst, neg, digs, prec, fmt)
case 'f':
return fmtF(dst, neg, digs, prec)
case 'g', 'G':
// trailing fractional zeros in 'e' form will be trimmed.
eprec := prec
if eprec > digs.nd && digs.nd >= digs.dp {
eprec = digs.nd
}
// %e is used if the exponent from the conversion
// is less than -4 or greater than or equal to the precision.
// if precision was the shortest possible, use precision 6 for this decision.
if shortest {
eprec = 6
}
exp := digs.dp - 1
if exp < -4 || exp >= eprec {
if prec > digs.nd {
prec = digs.nd
}
return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g')
}
if prec > digs.dp {
prec = digs.nd
}
return fmtF(dst, neg, digs, max(prec-digs.dp, 0))
}
// unknown format
return append(dst, '%', fmt)
}
// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits
// that will let the original floating point value be precisely reconstructed.
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// If mantissa is zero, the number is zero; stop now.
if mant == 0 {
d.nd = 0
return
}
// Compute upper and lower such that any decimal number
// between upper and lower (possibly inclusive)
// will round to the original floating point number.
// We may see at once that the number is already shortest.
//
// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
// The closest shorter number is at least 10^(dp-nd) away.
// The lower/upper bounds computed below are at distance
// at most 2^(exp-mantbits).
//
// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
// or equivalently log2(10)*(dp-nd) > exp-mantbits.
// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
minexp := flt.bias + 1 // minimum possible exponent
if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
// The number is already shortest.
return
}
// d = mant << (exp - mantbits)
// Next highest floating point number is mant+1 << exp-mantbits.
// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
upper := new(decimal)
upper.Assign(mant*2 + 1)
upper.Shift(exp - int(flt.mantbits) - 1)
// d = mant << (exp - mantbits)
// Next lowest floating point number is mant-1 << exp-mantbits,
// unless mant-1 drops the significant bit and exp is not the minimum exp,
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
// Either way, call it mantlo << explo-mantbits.
// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
var mantlo uint64
var explo int
if mant > 1<<flt.mantbits || exp == minexp {
mantlo = mant - 1
explo = exp
} else {
mantlo = mant*2 - 1
explo = exp - 1
}
lower := new(decimal)
lower.Assign(mantlo*2 + 1)
lower.Shift(explo - int(flt.mantbits) - 1)
// The upper and lower bounds are possible outputs only if
// the original mantissa is even, so that IEEE round-to-even
// would round to the original mantissa and not the neighbors.
inclusive := mant%2 == 0
// Now we can figure out the minimum number of digits required.
// Walk along until d has distinguished itself from upper and lower.
for i := 0; i < d.nd; i++ {
l := byte('0') // lower digit
if i < lower.nd {
l = lower.d[i]
}
m := d.d[i] // middle digit
u := byte('0') // upper digit
if i < upper.nd {
u = upper.d[i]
}
// Okay to round down (truncate) if lower has a different digit
// or if lower is inclusive and is exactly the result of rounding
// down (i.e., and we have reached the final digit of lower).
okdown := l != m || inclusive && i+1 == lower.nd
// Okay to round up if upper has a different digit and either upper
// is inclusive or upper is bigger than the result of rounding up.
okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
// If it's okay to do either, then round to the nearest one.
// If it's okay to do only one, do it.
switch {
case okdown && okup:
d.Round(i + 1)
return
case okdown:
d.RoundDown(i + 1)
return
case okup:
d.RoundUp(i + 1)
return
}
}
}
type decimalSlice struct {
d []byte
nd, dp int
neg bool
}
// %e: -d.ddddde±dd
func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte {
// sign
if neg {
dst = append(dst, '-')
}
// first digit
ch := byte('0')
if d.nd != 0 {
ch = d.d[0]
}
dst = append(dst, ch)
// .moredigits
if prec > 0 {
dst = append(dst, '.')
i := 1
m := min(d.nd, prec+1)
if i < m {
dst = append(dst, d.d[i:m]...)
i = m
}
for ; i <= prec; i++ {
dst = append(dst, '0')
}
}
// e±
dst = append(dst, fmt)
exp := d.dp - 1
if d.nd == 0 { // special case: 0 has exponent 0
exp = 0
}
if exp < 0 {
ch = '-'
exp = -exp
} else {
ch = '+'
}
dst = append(dst, ch)
// dd or ddd
switch {
case exp < 10:
dst = append(dst, '0', byte(exp)+'0')
case exp < 100:
dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0')
default:
dst = append(dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0')
}
return dst
}
// %f: -ddddddd.ddddd
func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte {
// sign
if neg {
dst = append(dst, '-')
}
// integer, padded with zeros as needed.
if d.dp > 0 {
m := min(d.nd, d.dp)
dst = append(dst, d.d[:m]...)
for ; m < d.dp; m++ {
dst = append(dst, '0')
}
} else {
dst = append(dst, '0')
}
// fraction
if prec > 0 {
dst = append(dst, '.')
for i := 0; i < prec; i++ {
ch := byte('0')
if j := d.dp + i; 0 <= j && j < d.nd {
ch = d.d[j]
}
dst = append(dst, ch)
}
}
return dst
}
// %b: -ddddddddp±ddd
func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
// sign
if neg {
dst = append(dst, '-')
}
// mantissa
dst, _ = formatBits(dst, mant, 10, false, true)
// p
dst = append(dst, 'p')
// ±exponent
exp -= int(flt.mantbits)
if exp >= 0 {
dst = append(dst, '+')
}
dst, _ = formatBits(dst, uint64(exp), 10, exp < 0, true)
return dst
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}

466
vendor/golang.org/x/text/internal/number/gen.go generated vendored Normal file
View file

@ -0,0 +1,466 @@
// Copyright 2016 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
import (
"flag"
"fmt"
"log"
"reflect"
"strings"
"unicode/utf8"
"golang.org/x/text/internal"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/number"
"golang.org/x/text/internal/stringset"
"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.")
outputFile = flag.String("output", "tables.go", "output file")
outputTestFile = flag.String("testoutput", "data_test.go", "output file")
draft = flag.String("draft",
"contributed",
`Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
)
func main() {
gen.Init()
const pkg = "number"
gen.Repackage("gen_common.go", "common.go", pkg)
// Read the CLDR zip file.
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
d.SetDirFilter("supplemental", "main")
d.SetSectionFilter("numbers", "numberingSystem", "plurals")
data, err := d.DecodeZip(r)
if err != nil {
log.Fatalf("DecodeZip: %v", err)
}
w := gen.NewCodeWriter()
defer w.WriteGoFile(*outputFile, pkg)
fmt.Fprintln(w, `import "golang.org/x/text/internal/stringset"`)
gen.WriteCLDRVersion(w)
genNumSystem(w, data)
genSymbols(w, data)
genPlurals(w, data)
genFormats(w, data)
w = gen.NewCodeWriter()
defer w.WriteGoFile(*outputTestFile, pkg)
fmt.Fprintln(w, `import "golang.org/x/text/internal/format/plural"`)
genPluralsTests(w, data)
}
var systemMap = map[string]system{"latn": 0}
func getNumberSystem(str string) system {
ns, ok := systemMap[str]
if !ok {
log.Fatalf("No index for numbering system %q", str)
}
return ns
}
func genNumSystem(w *gen.CodeWriter, data *cldr.CLDR) {
numSysData := []systemData{
{digitSize: 1, zero: [4]byte{'0'}},
}
for _, ns := range data.Supplemental().NumberingSystems.NumberingSystem {
if len(ns.Digits) == 0 {
continue
}
switch ns.Id {
case "latn":
// hard-wired
continue
case "hanidec":
// non-consecutive digits: treat as "algorithmic"
continue
}
zero, sz := utf8.DecodeRuneInString(ns.Digits)
if ns.Digits[sz-1]+9 > 0xBF { // 1011 1111: highest continuation byte
log.Fatalf("Last byte of zero value overflows for %s", ns.Id)
}
i := rune(0)
for _, r := range ns.Digits {
// Verify that we can do simple math on the UTF-8 byte sequence
// of zero to get the digit.
if zero+i != r {
// Runes not consecutive.
log.Fatalf("Digit %d of %s (%U) is not offset correctly from zero value", i, ns.Id, r)
}
i++
}
var x [utf8.UTFMax]byte
utf8.EncodeRune(x[:], zero)
id := system(len(numSysData))
systemMap[ns.Id] = id
numSysData = append(numSysData, systemData{
id: id,
digitSize: byte(sz),
zero: x,
})
}
w.WriteVar("numSysData", numSysData)
algoID := system(len(numSysData))
fmt.Fprintln(w, "const (")
for _, ns := range data.Supplemental().NumberingSystems.NumberingSystem {
id, ok := systemMap[ns.Id]
if !ok {
id = algoID
systemMap[ns.Id] = id
algoID++
}
fmt.Fprintf(w, "num%s = %#x\n", strings.Title(ns.Id), id)
}
fmt.Fprintln(w, "numNumberSystems")
fmt.Fprintln(w, ")")
fmt.Fprintln(w, "var systemMap = map[string]system{")
for _, ns := range data.Supplemental().NumberingSystems.NumberingSystem {
fmt.Fprintf(w, "%q: num%s,\n", ns.Id, strings.Title(ns.Id))
w.Size += len(ns.Id) + 16 + 1 // very coarse approximation
}
fmt.Fprintln(w, "}")
}
func genSymbols(w *gen.CodeWriter, data *cldr.CLDR) {
d, err := cldr.ParseDraft(*draft)
if err != nil {
log.Fatalf("invalid draft level: %v", err)
}
nNumberSystems := system(len(systemMap))
type symbols [NumSymbolTypes]string
type key struct {
tag int // from language.CompactIndex
system system
}
symbolMap := map[key]*symbols{}
defaults := map[int]system{}
for _, lang := range data.Locales() {
ldml := data.RawLDML(lang)
if ldml.Numbers == nil {
continue
}
langIndex, ok := language.CompactIndex(language.MustParse(lang))
if !ok {
log.Fatalf("No compact index for language %s", lang)
}
if d := ldml.Numbers.DefaultNumberingSystem; len(d) > 0 {
defaults[langIndex] = getNumberSystem(d[0].Data())
}
syms := cldr.MakeSlice(&ldml.Numbers.Symbols)
syms.SelectDraft(d)
getFirst := func(name string, x interface{}) string {
v := reflect.ValueOf(x)
slice := cldr.MakeSlice(x)
slice.SelectAnyOf("alt", "", "alt")
if reflect.Indirect(v).Len() == 0 {
return ""
} else if reflect.Indirect(v).Len() > 1 {
log.Fatalf("%s: multiple values of %q within single symbol not supported.", lang, name)
}
return reflect.Indirect(v).Index(0).MethodByName("Data").Call(nil)[0].String()
}
for _, sym := range ldml.Numbers.Symbols {
if sym.NumberSystem == "" {
// This is just linking the default of root to "latn".
continue
}
symbolMap[key{langIndex, getNumberSystem(sym.NumberSystem)}] = &symbols{
SymDecimal: getFirst("decimal", &sym.Decimal),
SymGroup: getFirst("group", &sym.Group),
SymList: getFirst("list", &sym.List),
SymPercentSign: getFirst("percentSign", &sym.PercentSign),
SymPlusSign: getFirst("plusSign", &sym.PlusSign),
SymMinusSign: getFirst("minusSign", &sym.MinusSign),
SymExponential: getFirst("exponential", &sym.Exponential),
SymSuperscriptingExponent: getFirst("superscriptingExponent", &sym.SuperscriptingExponent),
SymPerMille: getFirst("perMille", &sym.PerMille),
SymInfinity: getFirst("infinity", &sym.Infinity),
SymNan: getFirst("nan", &sym.Nan),
SymTimeSeparator: getFirst("timeSeparator", &sym.TimeSeparator),
}
}
}
// Expand all values.
for k, syms := range symbolMap {
for t := SymDecimal; t < NumSymbolTypes; t++ {
p := k.tag
for syms[t] == "" {
p = int(internal.Parent[p])
if pSyms, ok := symbolMap[key{p, k.system}]; ok && (*pSyms)[t] != "" {
syms[t] = (*pSyms)[t]
break
}
if p == 0 /* und */ {
// Default to root, latn.
syms[t] = (*symbolMap[key{}])[t]
}
}
}
}
// Unique the symbol sets and write the string data.
m := map[symbols]int{}
sb := stringset.NewBuilder()
symIndex := [][NumSymbolTypes]byte{}
for ns := system(0); ns < nNumberSystems; ns++ {
for _, l := range data.Locales() {
langIndex, _ := language.CompactIndex(language.MustParse(l))
s := symbolMap[key{langIndex, ns}]
if s == nil {
continue
}
if _, ok := m[*s]; !ok {
m[*s] = len(symIndex)
sb.Add(s[:]...)
var x [NumSymbolTypes]byte
for i := SymDecimal; i < NumSymbolTypes; i++ {
x[i] = byte(sb.Index((*s)[i]))
}
symIndex = append(symIndex, x)
}
}
}
w.WriteVar("symIndex", symIndex)
w.WriteVar("symData", sb.Set())
// resolveSymbolIndex gets the index from the closest matching locale,
// including the locale itself.
resolveSymbolIndex := func(langIndex int, ns system) byte {
for {
if sym := symbolMap[key{langIndex, ns}]; sym != nil {
return byte(m[*sym])
}
if langIndex == 0 {
return 0 // und, latn
}
langIndex = int(internal.Parent[langIndex])
}
}
// Create an index with the symbols for each locale for the latn numbering
// system. If this is not the default, or the only one, for a locale, we
// will overwrite the value later.
var langToDefaults [language.NumCompactTags]byte
for _, l := range data.Locales() {
langIndex, _ := language.CompactIndex(language.MustParse(l))
langToDefaults[langIndex] = resolveSymbolIndex(langIndex, 0)
}
// Delete redundant entries.
for _, l := range data.Locales() {
langIndex, _ := language.CompactIndex(language.MustParse(l))
def := defaults[langIndex]
syms := symbolMap[key{langIndex, def}]
if syms == nil {
continue
}
for ns := system(0); ns < nNumberSystems; ns++ {
if ns == def {
continue
}
if altSyms, ok := symbolMap[key{langIndex, ns}]; ok && *altSyms == *syms {
delete(symbolMap, key{langIndex, ns})
}
}
}
// Create a sorted list of alternatives per language. This will only need to
// be referenced if a user specified an alternative numbering system.
var langToAlt []altSymData
for _, l := range data.Locales() {
langIndex, _ := language.CompactIndex(language.MustParse(l))
start := len(langToAlt)
if start > 0x7F {
log.Fatal("Number of alternative assignments > 0x7F")
}
// Create the entry for the default value.
def := defaults[langIndex]
langToAlt = append(langToAlt, altSymData{
compactTag: uint16(langIndex),
system: def,
symIndex: resolveSymbolIndex(langIndex, def),
})
for ns := system(0); ns < nNumberSystems; ns++ {
if def == ns {
continue
}
if sym := symbolMap[key{langIndex, ns}]; sym != nil {
langToAlt = append(langToAlt, altSymData{
compactTag: uint16(langIndex),
system: ns,
symIndex: resolveSymbolIndex(langIndex, ns),
})
}
}
if def == 0 && len(langToAlt) == start+1 {
// No additional data: erase the entry.
langToAlt = langToAlt[:start]
} else {
// Overwrite the entry in langToDefaults.
langToDefaults[langIndex] = 0x80 | byte(start)
}
}
w.WriteComment(`
langToDefaults maps a compact language index to the default numbering system
and default symbol set`)
w.WriteVar("langToDefaults", langToDefaults)
w.WriteComment(`
langToAlt is a list of numbering system and symbol set pairs, sorted and
marked by compact language index.`)
w.WriteVar("langToAlt", langToAlt)
}
// genFormats generates the lookup table for decimal, scientific and percent
// patterns.
//
// CLDR allows for patterns to be different per language for different numbering
// systems. In practice the patterns are set to be consistent for a language
// independent of the numbering system. genFormats verifies that no language
// deviates from this.
func genFormats(w *gen.CodeWriter, data *cldr.CLDR) {
d, err := cldr.ParseDraft(*draft)
if err != nil {
log.Fatalf("invalid draft level: %v", err)
}
// Fill the first slot with a dummy so we can identify unspecified tags.
formats := []number.Format{{}}
patterns := map[string]int{}
// TODO: It would be possible to eliminate two of these slices by having
// another indirection and store a reference to the combination of patterns.
decimal := make([]byte, language.NumCompactTags)
scientific := make([]byte, language.NumCompactTags)
percent := make([]byte, language.NumCompactTags)
for _, lang := range data.Locales() {
ldml := data.RawLDML(lang)
if ldml.Numbers == nil {
continue
}
langIndex, ok := language.CompactIndex(language.MustParse(lang))
if !ok {
log.Fatalf("No compact index for language %s", lang)
}
type patternSlice []*struct {
cldr.Common
Numbers string `xml:"numbers,attr"`
Count string `xml:"count,attr"`
}
add := func(name string, tags []byte, ps patternSlice) {
sl := cldr.MakeSlice(&ps)
sl.SelectDraft(d)
if len(ps) == 0 {
return
}
if len(ps) > 2 || len(ps) == 2 && ps[0] != ps[1] {
log.Fatalf("Inconsistent %d patterns for language %s", name, lang)
}
s := ps[0].Data()
index, ok := patterns[s]
if !ok {
nf, err := number.ParsePattern(s)
if err != nil {
log.Fatal(err)
}
index = len(formats)
patterns[s] = index
formats = append(formats, *nf)
}
tags[langIndex] = byte(index)
}
for _, df := range ldml.Numbers.DecimalFormats {
for _, l := range df.DecimalFormatLength {
if l.Type != "" {
continue
}
for _, f := range l.DecimalFormat {
add("decimal", decimal, f.Pattern)
}
}
}
for _, df := range ldml.Numbers.ScientificFormats {
for _, l := range df.ScientificFormatLength {
if l.Type != "" {
continue
}
for _, f := range l.ScientificFormat {
add("scientific", scientific, f.Pattern)
}
}
}
for _, df := range ldml.Numbers.PercentFormats {
for _, l := range df.PercentFormatLength {
if l.Type != "" {
continue
}
for _, f := range l.PercentFormat {
add("percent", percent, f.Pattern)
}
}
}
}
// Complete the parent tag array to reflect inheritance. An index of 0
// indicates an unspecified value.
for _, data := range [][]byte{decimal, scientific, percent} {
for i := range data {
p := uint16(i)
for ; data[p] == 0; p = internal.Parent[p] {
}
data[i] = data[p]
}
}
w.WriteVar("tagToDecimal", decimal)
w.WriteVar("tagToScientific", scientific)
w.WriteVar("tagToPercent", percent)
value := strings.Replace(fmt.Sprintf("%#v", formats), "number.", "", -1)
// Break up the lines. This won't give ideal perfect formatting, but it is
// better than one huge line.
value = strings.Replace(value, ", ", ",\n", -1)
fmt.Fprintf(w, "var formats = %s\n", value)
}

96
vendor/golang.org/x/text/internal/number/gen_common.go generated vendored Normal file
View file

@ -0,0 +1,96 @@
// Copyright 2016 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
import (
"unicode/utf8"
"golang.org/x/text/internal/format/plural"
)
// A system identifies a CLDR numbering system.
type system byte
type systemData struct {
id system
digitSize byte // number of UTF-8 bytes per digit
zero [utf8.UTFMax]byte // UTF-8 sequence of zero digit.
}
// A SymbolType identifies a symbol of a specific kind.
type SymbolType int
const (
SymDecimal SymbolType = iota
SymGroup
SymList
SymPercentSign
SymPlusSign
SymMinusSign
SymExponential
SymSuperscriptingExponent
SymPerMille
SymInfinity
SymNan
SymTimeSeparator
NumSymbolTypes
)
type altSymData struct {
compactTag uint16
system system
symIndex byte
}
var countMap = map[string]plural.Form{
"other": plural.Other,
"zero": plural.Zero,
"one": plural.One,
"two": plural.Two,
"few": plural.Few,
"many": plural.Many,
}
type pluralCheck struct {
// category:
// 3..7: opID
// 0..2: category
cat byte
setID byte
}
// opID identifies the type of operand in the plural rule, being i, n or f.
// (v, w, and t are treated as filters in our implementation.)
type opID byte
const (
opMod opID = 0x1 // is '%' used?
opNotEqual opID = 0x2 // using "!=" to compare
opI opID = 0 << 2 // integers after taking the absolute value
opN opID = 1 << 2 // full number (must be integer)
opF opID = 2 << 2 // fraction
opV opID = 3 << 2 // number of visible digits
opW opID = 4 << 2 // number of visible digits without trailing zeros
opBretonM opID = 5 << 2 // hard-wired rule for Breton
opItalian800 opID = 6 << 2 // hard-wired rule for Italian
opAzerbaijan00s opID = 7 << 2 // hard-wired rule for Azerbaijan
)
const (
// Use this plural form to indicate the next rule needs to match as well.
// The last condition in the list will have the correct plural form.
andNext = 0x7
formMask = 0x7
opShift = 3
// numN indicates the maximum integer, or maximum mod value, for which we
// have inclusion masks.
numN = 100
// The common denominator of the modulo that is taken.
maxMod = 100
)

471
vendor/golang.org/x/text/internal/number/gen_plural.go generated vendored Normal file
View file

@ -0,0 +1,471 @@
// Copyright 2016 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 data for the CLDR plural rules, as defined in
// http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules
//
// We assume a slightly simplified grammar:
//
// condition = and_condition ('or' and_condition)* samples
// and_condition = relation ('and' relation)*
// relation = expr ('=' | '!=') range_list
// expr = operand ('%' '10' '0'* )?
// operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
// range_list = (range | value) (',' range_list)*
// range = value'..'value
// value = digit+
// digit = 0|1|2|3|4|5|6|7|8|9
//
// samples = ('@integer' sampleList)?
// ('@decimal' sampleList)?
// sampleList = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
// sampleRange = decimalValue ('~' decimalValue)?
// decimalValue = value ('.' value)?
//
// Symbol Value
// n absolute value of the source number (integer and decimals).
// i integer digits of n.
// v number of visible fraction digits in n, with trailing zeros.
// w number of visible fraction digits in n, without trailing zeros.
// f visible fractional digits in n, with trailing zeros.
// t visible fractional digits in n, without trailing zeros.
//
// The algorithm for which the data is generated is based on the following
// observations
//
// - the number of different sets of numbers which the plural rules use to
// test inclusion is limited,
// - most numbers that are tested on are < 100
//
// This allows us to define a bitmap for each number < 100 where a bit i
// indicates whether this number is included in some defined set i.
// The function matchPlural in plural.go defines how we can subsequently use
// this data to determine inclusion.
//
// There are a few languages for which this doesn't work. For one Italian and
// Azerbaijan, which both test against numbers > 100 for ordinals and Breton,
// which considers whether numbers are multiples of hundreds. The model here
// could be extended to handle Italian and Azerbaijan fairly easily (by
// considering the numbers 100, 200, 300, ..., 800, 900 in addition to the first
// 100), but for now it seems easier to just hard-code these cases.
import (
"bufio"
"bytes"
"fmt"
"log"
"strconv"
"strings"
"golang.org/x/text/internal"
"golang.org/x/text/internal/format/plural"
"golang.org/x/text/internal/gen"
"golang.org/x/text/language"
"golang.org/x/text/unicode/cldr"
)
type pluralTest struct {
locales string // space-separated list of locales for this test
form plural.Form
integer []string // Entries of the form \d+ or \d+~\d+
decimal []string // Entries of the form \f+ or \f+ +~\f+, where f is \d+\.\d+
}
func genPluralsTests(w *gen.CodeWriter, data *cldr.CLDR) {
w.WriteType(pluralTest{})
for _, plurals := range data.Supplemental().Plurals {
if plurals.Type == "" {
// The empty type is reserved for plural ranges.
continue
}
tests := []pluralTest{}
for _, pRules := range plurals.PluralRules {
for _, rule := range pRules.PluralRule {
test := pluralTest{
locales: pRules.Locales,
form: countMap[rule.Count],
}
scan := bufio.NewScanner(strings.NewReader(rule.Data()))
scan.Split(splitTokens)
var p *[]string
for scan.Scan() {
switch t := scan.Text(); t {
case "@integer":
p = &test.integer
case "@decimal":
p = &test.decimal
case ",", "…":
default:
if p != nil {
*p = append(*p, t)
}
}
}
tests = append(tests, test)
}
}
w.WriteVar(plurals.Type+"Tests", tests)
}
}
func genPlurals(w *gen.CodeWriter, data *cldr.CLDR) {
for _, plurals := range data.Supplemental().Plurals {
if plurals.Type == "" {
continue
}
// Initialize setMap and inclusionMasks. They are already populated with
// a few entries to serve as an example and to assign nice numbers to
// common cases.
// setMap contains sets of numbers represented by boolean arrays where
// a true value for element i means that the number i is included.
setMap := map[[numN]bool]int{
// The above init func adds an entry for including all numbers.
[numN]bool{1: true}: 1, // fix {1} to a nice value
[numN]bool{2: true}: 2, // fix {2} to a nice value
[numN]bool{0: true}: 3, // fix {0} to a nice value
}
// inclusionMasks contains bit masks for every number under numN to
// indicate in which set the number is included. Bit 1 << x will be set
// if it is included in set x.
inclusionMasks := [numN]uint64{
// Note: these entries are not complete: more bits will be set along the way.
0: 1 << 3,
1: 1 << 1,
2: 1 << 2,
}
// Create set {0..99}. We will assign this set the identifier 0.
var all [numN]bool
for i := range all {
// Mark number i as being included in the set (which has identifier 0).
inclusionMasks[i] |= 1 << 0
// Mark number i as included in the set.
all[i] = true
}
// Register the identifier for the set.
setMap[all] = 0
rules := []pluralCheck{}
index := []byte{0}
langMap := map[int]byte{0: 0} // From compact language index to index
for _, pRules := range plurals.PluralRules {
// Parse the rules.
var conds []orCondition
for _, rule := range pRules.PluralRule {
form := countMap[rule.Count]
conds = parsePluralCondition(conds, rule.Data(), form)
}
// Encode the rules.
for _, c := range conds {
// If an or condition only has filters, we create an entry for
// this filter and the set that contains all values.
empty := true
for _, b := range c.used {
empty = empty && !b
}
if empty {
rules = append(rules, pluralCheck{
cat: byte(opMod<<opShift) | byte(c.form),
setID: 0, // all values
})
continue
}
// We have some entries with values.
for i, set := range c.set {
if !c.used[i] {
continue
}
index, ok := setMap[set]
if !ok {
index = len(setMap)
setMap[set] = index
for i := range inclusionMasks {
if set[i] {
inclusionMasks[i] |= 1 << uint64(index)
}
}
}
rules = append(rules, pluralCheck{
cat: byte(i<<opShift | andNext),
setID: byte(index),
})
}
// Now set the last entry to the plural form the rule matches.
rules[len(rules)-1].cat &^= formMask
rules[len(rules)-1].cat |= byte(c.form)
}
// Point the relevant locales to the created entries.
for _, loc := range strings.Split(pRules.Locales, " ") {
if strings.TrimSpace(loc) == "" {
continue
}
lang, ok := language.CompactIndex(language.MustParse(loc))
if !ok {
log.Printf("No compact index for locale %q", loc)
}
langMap[lang] = byte(len(index) - 1)
}
index = append(index, byte(len(rules)))
}
w.WriteVar(plurals.Type+"Rules", rules)
w.WriteVar(plurals.Type+"Index", index)
// Expand the values.
langToIndex := make([]byte, language.NumCompactTags)
for i := range langToIndex {
for p := i; ; p = int(internal.Parent[p]) {
if x, ok := langMap[p]; ok {
langToIndex[i] = x
break
}
}
}
w.WriteVar(plurals.Type+"LangToIndex", langToIndex)
// Need to convert array to slice because of golang.org/issue/7651.
// This will allow tables to be dropped when unused. This is especially
// relevant for the ordinal data, which I suspect won't be used as much.
w.WriteVar(plurals.Type+"InclusionMasks", inclusionMasks[:])
if len(rules) > 0xFF {
log.Fatalf("Too many entries for rules: %#x", len(rules))
}
if len(index) > 0xFF {
log.Fatalf("Too many entries for index: %#x", len(index))
}
if len(setMap) > 64 { // maximum number of bits.
log.Fatalf("Too many entries for setMap: %d", len(setMap))
}
w.WriteComment(
"Slots used for %s: %X of 0xFF rules; %X of 0xFF indexes; %d of 64 sets",
plurals.Type, len(rules), len(index), len(setMap))
// Prevent comment from attaching to the next entry.
fmt.Fprint(w, "\n\n")
}
}
type orCondition struct {
original string // for debugging
form plural.Form
used [32]bool
set [32][numN]bool
}
func (o *orCondition) add(op opID, mod int, v []int) (ok bool) {
ok = true
for _, x := range v {
if x >= maxMod {
ok = false
break
}
}
for i := 0; i < numN; i++ {
m := i
if mod != 0 {
m = i % mod
}
if !intIn(m, v) {
o.set[op][i] = false
}
}
if ok {
o.used[op] = true
}
return ok
}
func intIn(x int, a []int) bool {
for _, y := range a {
if x == y {
return true
}
}
return false
}
var operandIndex = map[string]opID{
"i": opI,
"n": opN,
"f": opF,
"v": opV,
"w": opW,
}
// parsePluralCondition parses the condition of a single pluralRule and appends
// the resulting or conditions to conds.
//
// Example rules:
// // Category "one" in English: only allow 1 with no visible fraction
// i = 1 and v = 0 @integer 1
//
// // Category "few" in Czech: all numbers with visible fractions
// v != 0 @decimal ...
//
// // Category "zero" in Latvian: all multiples of 10 or the numbers 11-19 or
// // numbers with a fraction 11..19 and no trailing zeros.
// n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19 @integer ...
//
// @integer and @decimal are followed by examples and are not relevant for the
// rule itself. The are used here to signal the termination of the rule.
func parsePluralCondition(conds []orCondition, s string, f plural.Form) []orCondition {
scan := bufio.NewScanner(strings.NewReader(s))
scan.Split(splitTokens)
for {
cond := orCondition{original: s, form: f}
// Set all numbers to be allowed for all number classes and restrict
// from here on.
for i := range cond.set {
for j := range cond.set[i] {
cond.set[i][j] = true
}
}
andLoop:
for {
var token string
scan.Scan() // Must exist.
switch class := scan.Text(); class {
case "t":
class = "w" // equal to w for t == 0
fallthrough
case "n", "i", "f", "v", "w":
op := scanToken(scan)
opCode := operandIndex[class]
mod := 0
if op == "%" {
opCode |= opMod
switch v := scanUint(scan); v {
case 10, 100:
mod = v
case 1000:
// A more general solution would be to allow checking
// against multiples of 100 and include entries for the
// numbers 100..900 in the inclusion masks. At the
// moment this would only help Azerbaijan and Italian.
// Italian doesn't use '%', so this must be Azerbaijan.
cond.used[opAzerbaijan00s] = true
return append(conds, cond)
case 1000000:
cond.used[opBretonM] = true
return append(conds, cond)
default:
log.Fatalf("Modulo value not supported %d", v)
}
op = scanToken(scan)
}
if op != "=" && op != "!=" {
log.Fatalf("Unexpected op %q", op)
}
if op == "!=" {
opCode |= opNotEqual
}
a := []int{}
v := scanUint(scan)
if class == "w" && v != 0 {
log.Fatalf("Must compare against zero for operand type %q", class)
}
token = scanToken(scan)
for {
switch token {
case "..":
end := scanUint(scan)
for ; v <= end; v++ {
a = append(a, v)
}
token = scanToken(scan)
default: // ",", "or", "and", "@..."
a = append(a, v)
}
if token != "," {
break
}
v = scanUint(scan)
token = scanToken(scan)
}
if !cond.add(opCode, mod, a) {
// Detected large numbers. As we ruled out Azerbaijan, this
// must be the many rule for Italian ordinals.
cond.set[opItalian800] = cond.set[opN]
cond.used[opItalian800] = true
}
case "@integer", "@decimal": // "other" entry: tests only.
return conds
default:
log.Fatalf("Unexpected operand class %q (%s)", class, s)
}
switch token {
case "or":
conds = append(conds, cond)
break andLoop
case "@integer", "@decimal": // examples
// There is always an example in practice, so we always terminate here.
if err := scan.Err(); err != nil {
log.Fatal(err)
}
return append(conds, cond)
case "and":
// keep accumulating
default:
log.Fatalf("Unexpected token %q", token)
}
}
}
}
func scanToken(scan *bufio.Scanner) string {
scan.Scan()
return scan.Text()
}
func scanUint(scan *bufio.Scanner) int {
scan.Scan()
val, err := strconv.ParseUint(scan.Text(), 10, 32)
if err != nil {
log.Fatal(err)
}
return int(val)
}
// splitTokens can be used with bufio.Scanner to tokenize CLDR plural rules.
func splitTokens(data []byte, atEOF bool) (advance int, token []byte, err error) {
condTokens := [][]byte{
[]byte(".."),
[]byte(","),
[]byte("!="),
[]byte("="),
}
advance, token, err = bufio.ScanWords(data, atEOF)
for _, t := range condTokens {
if len(t) >= len(token) {
continue
}
switch p := bytes.Index(token, t); {
case p == -1:
case p == 0:
advance = len(t)
token = token[:len(t)]
return advance - len(token) + len(t), token[:len(t)], err
case p < advance:
// Don't split when "=" overlaps "!=".
if t[0] == '=' && token[p-1] == '!' {
continue
}
advance = p
token = token[:p]
}
}
return advance, token, err
}

111
vendor/golang.org/x/text/internal/number/itoa.go generated vendored Normal file
View file

@ -0,0 +1,111 @@
// Copyright 2009 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.
// TODO: use build tags once a low-level public API has been established in
// package strconv.
package number
const (
digits = "0123456789abcdefghijklmnopqrstuvwxyz"
)
var shifts = [len(digits) + 1]uint{
1 << 1: 1,
1 << 2: 2,
1 << 3: 3,
1 << 4: 4,
1 << 5: 5,
}
// formatBits computes the string representation of u in the given base.
// If neg is set, u is treated as negative int64 value. If append_ is
// set, the string is appended to dst and the resulting byte slice is
// returned as the first result value; otherwise the string is returned
// as the second result value.
//
func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) {
if base < 2 || base > len(digits) {
panic("strconv: illegal AppendInt/FormatInt base")
}
// 2 <= base && base <= len(digits)
var a [64 + 1]byte // +1 for sign of 64bit value in base 2
i := len(a)
if neg {
u = -u
}
// convert bits
if base == 10 {
// common case: use constants for / because
// the compiler can optimize it into a multiply+shift
if ^uintptr(0)>>32 == 0 {
for u > uint64(^uintptr(0)) {
q := u / 1e9
us := uintptr(u - q*1e9) // us % 1e9 fits into a uintptr
for j := 9; j > 0; j-- {
i--
qs := us / 10
a[i] = byte(us - qs*10 + '0')
us = qs
}
u = q
}
}
// u guaranteed to fit into a uintptr
us := uintptr(u)
for us >= 10 {
i--
q := us / 10
a[i] = byte(us - q*10 + '0')
us = q
}
// u < 10
i--
a[i] = byte(us + '0')
} else if s := shifts[base]; s > 0 {
// base is power of 2: use shifts and masks instead of / and %
b := uint64(base)
m := uintptr(b) - 1 // == 1<<s - 1
for u >= b {
i--
a[i] = digits[uintptr(u)&m]
u >>= s
}
// u < base
i--
a[i] = digits[uintptr(u)]
} else {
// general case
b := uint64(base)
for u >= b {
i--
q := u / b
a[i] = digits[uintptr(u-q*b)]
u = q
}
// u < base
i--
a[i] = digits[uintptr(u)]
}
// add sign, if any
if neg {
i--
a[i] = '-'
}
if append_ {
d = append(dst, a[i:]...)
return
}
s = string(a[i:])
return
}

145
vendor/golang.org/x/text/internal/number/number.go generated vendored Normal file
View file

@ -0,0 +1,145 @@
// Copyright 2016 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.
//go:generate go run gen.go gen_common.go gen_plural.go
// Package number contains tools and data for formatting numbers.
package number
import (
"unicode/utf8"
"golang.org/x/text/internal"
"golang.org/x/text/language"
)
// Info holds number formatting configuration data.
type Info struct {
system systemData // numbering system information
symIndex byte // index to symbols
}
// InfoFromLangID returns a Info for the given compact language identifier and
// numbering system identifier. If system is the empty string, the default
// numbering system will be taken for that language.
func InfoFromLangID(compactIndex int, numberSystem string) Info {
p := langToDefaults[compactIndex]
// Lookup the entry for the language.
pSymIndex := byte(0) // Default: Latin, default symbols
system, ok := systemMap[numberSystem]
if !ok {
// Take the value for the default numbering system. This is by far the
// most common case as an alternative numbering system is hardly used.
if p&0x80 == 0 {
pSymIndex = p
} else {
// Take the first entry from the alternatives list.
data := langToAlt[p&^0x80]
pSymIndex = data.symIndex
system = data.system
}
} else {
langIndex := compactIndex
ns := system
outerLoop:
for {
if p&0x80 == 0 {
if ns == 0 {
// The index directly points to the symbol data.
pSymIndex = p
break
}
// Move to the parent and retry.
langIndex = int(internal.Parent[langIndex])
}
// The index points to a list of symbol data indexes.
for _, e := range langToAlt[p&^0x80:] {
if int(e.compactTag) != langIndex {
if langIndex == 0 {
// The CLDR root defines full symbol information for all
// numbering systems (even though mostly by means of
// aliases). This means that we will never fall back to
// the default of the language. Also, the loop is
// guaranteed to terminate as a consequence.
ns = numLatn
// Fall back to Latin and start from the original
// language. See
// http://unicode.org/reports/tr35/#Locale_Inheritance.
langIndex = compactIndex
} else {
// Fall back to parent.
langIndex = int(internal.Parent[langIndex])
}
break
}
if e.system == ns {
pSymIndex = e.symIndex
break outerLoop
}
}
}
}
if int(system) >= len(numSysData) { // algorithmic
// Will generate ASCII digits in case the user inadvertently calls
// WriteDigit or Digit on it.
d := numSysData[0]
d.id = system
return Info{
system: d,
symIndex: pSymIndex,
}
}
return Info{
system: numSysData[system],
symIndex: pSymIndex,
}
}
// InfoFromTag returns a Info for the given language tag.
func InfoFromTag(t language.Tag) Info {
for {
if index, ok := language.CompactIndex(t); ok {
return InfoFromLangID(index, t.TypeForKey("nu"))
}
t = t.Parent()
}
}
// IsDecimal reports if the numbering system can convert decimal to native
// symbols one-to-one.
func (n Info) IsDecimal() bool {
return int(n.system.id) < len(numSysData)
}
// WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII
// digit to dst and reports the number of bytes written. dst must be large
// enough to hold the rune (can be up to utf8.UTFMax bytes).
func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
copy(dst, n.system.zero[:n.system.digitSize])
dst[n.system.digitSize-1] += byte(asciiDigit - '0')
return int(n.system.digitSize)
}
// Digit returns the digit for the numbering system for the corresponding ASCII
// value. For example, ni.Digit('3') could return '三'. Note that the argument
// is the rune constant '3', which equals 51, not the integer constant 3.
func (n Info) Digit(asciiDigit rune) rune {
var x [utf8.UTFMax]byte
n.WriteDigit(x[:], asciiDigit)
r, _ := utf8.DecodeRune(x[:])
return r
}
// Symbol returns the string for the given symbol type.
func (n Info) Symbol(t SymbolType) string {
return symData.Elem(int(symIndex[n.symIndex][t]))
}
func formatForLang(t language.Tag, index []byte) *Format {
for ; ; t = t.Parent() {
if x, ok := language.CompactIndex(t); ok {
return &formats[index[x]]
}
}
}

View file

@ -0,0 +1,90 @@
// Copyright 2016 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 number
import (
"testing"
"golang.org/x/text/internal/testtext"
"golang.org/x/text/language"
)
func TestInfo(t *testing.T) {
testCases := []struct {
lang string
sym SymbolType
wantSym string
wantNine rune
}{
{"und", SymDecimal, ".", '9'},
{"de", SymGroup, ".", '9'},
{"de-BE", SymGroup, ".", '9'}, // inherits from de (no number data in CLDR)
{"de-BE-oxendict", SymGroup, ".", '9'}, // inherits from de (no compact index)
// U+096F DEVANAGARI DIGIT NINE ('९')
{"de-BE-u-nu-deva", SymGroup, ".", '\u096f'}, // miss -> latn -> de
{"de-Cyrl-BE", SymGroup, ",", '9'}, // inherits from root
{"de-CH", SymGroup, "'", '9'}, // overrides values in de
{"de-CH-oxendict", SymGroup, "'", '9'}, // inherits from de-CH (no compact index)
{"de-CH-u-nu-deva", SymGroup, "'", '\u096f'}, // miss -> latn -> de-CH
{"pa", SymExponential, "E", '9'},
// "×۱۰^" -> U+00d7 U+06f1 U+06f0^"
// U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO
// U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE
// U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE
{"pa-u-nu-arabext", SymExponential, "\u00d7\u06f1\u06f0^", '\u06f9'},
// "གྲངས་མེད" - > U+0f42 U+0fb2 U+0f44 U+0f66 U+0f0b U+0f58 U+0f7a U+0f51
// Examples:
// U+0F29 TIBETAN DIGIT NINE (༩)
{"dz", SymInfinity, "\u0f42\u0fb2\u0f44\u0f66\u0f0b\u0f58\u0f7a\u0f51", '\u0f29'}, // defaults to tibt
{"dz-u-nu-latn", SymInfinity, "∞", '9'}, // select alternative
{"dz-u-nu-tibt", SymInfinity, "\u0f42\u0fb2\u0f44\u0f66\u0f0b\u0f58\u0f7a\u0f51", '\u0f29'},
{"en-u-nu-tibt", SymInfinity, "∞", '\u0f29'},
// algorithmic number systems fall back to ASCII if Digits is used.
{"en-u-nu-hanidec", SymPlusSign, "+", '9'},
{"en-u-nu-roman", SymPlusSign, "+", '9'},
}
for _, tc := range testCases {
info := InfoFromTag(language.MustParse(tc.lang))
if got := info.Symbol(tc.sym); got != tc.wantSym {
t.Errorf("%s:%v:sym: got %q; want %q", tc.lang, tc.sym, got, tc.wantSym)
}
if got := info.Digit('9'); got != tc.wantNine {
t.Errorf("%s:%v:nine: got %q; want %q", tc.lang, tc.sym, got, tc.wantNine)
}
}
}
func TestFormats(t *testing.T) {
testCases := []struct {
lang string
pattern string
index []byte
}{
{"en", "#,##0.###", tagToDecimal},
{"de", "#,##0.###", tagToDecimal},
{"de-CH", "#,##0.###", tagToDecimal},
{"pa", "#,##,##0.###", tagToDecimal},
{"pa-Arab", "#,##0.###", tagToDecimal}, // Does NOT inherit from pa!
{"mr", "#,##,##0.###", tagToDecimal},
{"mr-IN", "#,##,##0.###", tagToDecimal}, // Inherits from mr.
{"nl", "#E0", tagToScientific},
{"nl-MX", "#E0", tagToScientific}, // Inherits through Tag.Parent.
{"zgh", "#,##0 %", tagToPercent},
}
for _, tc := range testCases {
testtext.Run(t, tc.lang, func(t *testing.T) {
got := formatForLang(language.MustParse(tc.lang), tc.index)
want, _ := ParsePattern(tc.pattern)
if *got != *want {
t.Errorf("\ngot %#v;\nwant %#v", got, want)
}
})
}
}

386
vendor/golang.org/x/text/internal/number/pattern.go generated vendored Normal file
View file

@ -0,0 +1,386 @@
// 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.
package number
import (
"errors"
"unicode/utf8"
)
// This file contains a parser for the CLDR number patterns as described in
// http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
//
// The following BNF is derived from this standard.
//
// pattern := subpattern (';' subpattern)?
// subpattern := affix? number exponent? affix?
// number := decimal | sigDigits
// decimal := '#'* '0'* ('.' fraction)? | '#' | '0'
// fraction := '0'* '#'*
// sigDigits := '#'* '@' '@'* '#'*
// exponent := 'E' '+'? '0'* '0'
// padSpec := '*' \L
//
// Notes:
// - An affix pattern may contain any runes, but runes with special meaning
// should be escaped.
// - Sequences of digits, '#', and '@' in decimal and sigDigits may have
// interstitial commas.
// TODO: replace special characters in affixes (-, +, ¤) with control codes.
// Format holds information for formatting numbers. It is designed to hold
// information from CLDR number patterns.
//
// This pattern is precompiled for all patterns for all languages. Even though
// the number of patterns is not very large, we want to keep this small.
//
// This type is only intended for internal use.
type Format struct {
// TODO: this struct can be packed a lot better than it is now. Should be
// possible to make it 32 bytes.
Affix string // includes prefix and suffix. First byte is prefix length.
Offset uint16 // Offset into Affix for prefix and suffix
NegOffset uint16 // Offset into Affix for negative prefix and suffix or 0.
Multiplier uint32
RoundIncrement uint32 // Use Min*Digits to determine scale
PadRune rune
FormatWidth uint16
GroupingSize [2]uint8
Flags FormatFlag
// Number of digits.
MinIntegerDigits uint8
MaxIntegerDigits uint8
MinFractionDigits uint8
MaxFractionDigits uint8
MinSignificantDigits uint8
MaxSignificantDigits uint8
MinExponentDigits uint8
}
// A FormatFlag is a bit mask for the flag field of a Format.
type FormatFlag uint8
const (
AlwaysSign FormatFlag = 1 << iota
AlwaysExpSign
AlwaysDecimalSeparator
ParenthesisForNegative // Common pattern. Saves space.
PadAfterNumber
PadAfterAffix
PadBeforePrefix = 0 // Default
PadAfterPrefix = PadAfterAffix
PadBeforeSuffix = PadAfterNumber
PadAfterSuffix = PadAfterNumber | PadAfterAffix
PadMask = PadAfterNumber | PadAfterAffix
)
type parser struct {
*Format
leadingSharps int
pos int
err error
doNotTerminate bool
groupingCount uint
hasGroup bool
buf []byte
}
func (p *parser) setError(err error) {
if p.err == nil {
p.err = err
}
}
func (p *parser) updateGrouping() {
if p.hasGroup && p.groupingCount < 255 {
p.GroupingSize[1] = p.GroupingSize[0]
p.GroupingSize[0] = uint8(p.groupingCount)
}
p.groupingCount = 0
p.hasGroup = true
}
var (
// TODO: more sensible and localizeable error messages.
errMultiplePadSpecifiers = errors.New("format: pattern has multiple pad specifiers")
errInvalidPadSpecifier = errors.New("format: invalid pad specifier")
errInvalidQuote = errors.New("format: invalid quote")
errAffixTooLarge = errors.New("format: prefix or suffix exceeds maximum UTF-8 length of 256 bytes")
errDuplicatePercentSign = errors.New("format: duplicate percent sign")
errDuplicatePermilleSign = errors.New("format: duplicate permille sign")
errUnexpectedEnd = errors.New("format: unexpected end of pattern")
)
// ParsePattern extracts formatting information from a CLDR number pattern.
//
// See http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns.
func ParsePattern(s string) (f *Format, err error) {
p := parser{Format: &Format{}}
s = p.parseSubPattern(s)
if s != "" {
// Parse negative sub pattern.
if s[0] != ';' {
p.setError(errors.New("format: error parsing first sub pattern"))
return nil, p.err
}
neg := parser{Format: &Format{}} // just for extracting the affixes.
s = neg.parseSubPattern(s[len(";"):])
p.NegOffset = uint16(len(p.buf))
p.buf = append(p.buf, neg.buf...)
}
if s != "" {
p.setError(errors.New("format: spurious characters at end of pattern"))
}
if p.err != nil {
return nil, p.err
}
if affix := string(p.buf); affix == "\x00\x00" || affix == "\x00\x00\x00\x00" {
// No prefix or suffixes.
p.NegOffset = 0
} else {
p.Affix = affix
}
return p.Format, nil
}
func (p *parser) parseSubPattern(s string) string {
s = p.parsePad(s, PadBeforePrefix)
s = p.parseAffix(s)
s = p.parsePad(s, PadAfterPrefix)
s = p.parse(p.number, s)
s = p.parsePad(s, PadBeforeSuffix)
s = p.parseAffix(s)
s = p.parsePad(s, PadAfterSuffix)
return s
}
func (p *parser) parsePad(s string, f FormatFlag) (tail string) {
if len(s) >= 2 && s[0] == '*' {
r, sz := utf8.DecodeRuneInString(s[1:])
if p.PadRune != 0 {
p.err = errMultiplePadSpecifiers
} else {
p.Flags |= f
p.PadRune = r
}
return s[1+sz:]
}
return s
}
func (p *parser) parseAffix(s string) string {
x := len(p.buf)
p.buf = append(p.buf, 0) // placeholder for affix length
s = p.parse(p.affix, s)
n := len(p.buf) - x - 1
if n > 0xFF {
p.setError(errAffixTooLarge)
}
p.buf[x] = uint8(n)
return s
}
// state implements a state transition. It returns the new state. A state
// function may set an error on the parser or may simply return on an incorrect
// token and let the next phase fail.
type state func(r rune) state
// parse repeatedly applies a state function on the given string until a
// termination condition is reached.
func (p *parser) parse(fn state, s string) (tail string) {
for i, r := range s {
p.doNotTerminate = false
if fn = fn(r); fn == nil || p.err != nil {
return s[i:]
}
p.FormatWidth++
}
if p.doNotTerminate {
p.setError(errUnexpectedEnd)
}
return ""
}
func (p *parser) affix(r rune) state {
switch r {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'#', '@', '.', '*', ',', ';':
return nil
case '\'':
return p.escape
case '%':
if p.Multiplier != 0 {
p.setError(errDuplicatePercentSign)
}
p.Multiplier = 100
case '\u2030': // ‰ Per mille
if p.Multiplier != 0 {
p.setError(errDuplicatePermilleSign)
}
p.Multiplier = 1000
// TODO: handle currency somehow: ¤, ¤¤, ¤¤¤, ¤¤¤¤
}
p.buf = append(p.buf, string(r)...)
return p.affix
}
func (p *parser) escape(r rune) state {
switch r {
case '\'':
return p.affix
default:
p.buf = append(p.buf, string(r)...)
}
return p.escape
}
// number parses a number. The BNF says the integer part should always have
// a '0', but that does not appear to be the case according to the rest of the
// documentation. We will allow having only '#' numbers.
func (p *parser) number(r rune) state {
switch r {
case '#':
p.groupingCount++
p.leadingSharps++
case '@':
p.groupingCount++
p.leadingSharps = 0
return p.sigDigits(r)
case ',':
if p.leadingSharps == 0 { // no leading commas
return nil
}
p.updateGrouping()
case 'E':
p.MaxIntegerDigits = uint8(p.leadingSharps)
return p.exponent
case '.': // allow ".##" etc.
p.updateGrouping()
return p.fraction
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return p.integer(r)
default:
return nil
}
return p.number
}
func (p *parser) integer(r rune) state {
if !('0' <= r && r <= '9') {
var next state
switch r {
case 'E':
if p.leadingSharps > 0 {
p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
}
next = p.exponent
case '.':
next = p.fraction
}
p.updateGrouping()
return next
}
p.RoundIncrement = p.RoundIncrement*10 + uint32(r-'0')
p.groupingCount++
p.MinIntegerDigits++
return p.integer
}
func (p *parser) sigDigits(r rune) state {
switch r {
case '@':
p.groupingCount++
p.MaxSignificantDigits++
p.MinSignificantDigits++
case '#':
return p.sigDigitsFinal(r)
case 'E':
p.updateGrouping()
return p.normalizeSigDigitsWithExponent()
default:
p.updateGrouping()
return nil
}
return p.sigDigits
}
func (p *parser) sigDigitsFinal(r rune) state {
switch r {
case '#':
p.groupingCount++
p.MaxSignificantDigits++
case 'E':
p.updateGrouping()
return p.normalizeSigDigitsWithExponent()
default:
p.updateGrouping()
return nil
}
return p.sigDigitsFinal
}
func (p *parser) normalizeSigDigitsWithExponent() state {
p.MinIntegerDigits, p.MaxIntegerDigits = 1, 1
p.MinFractionDigits = p.MinSignificantDigits - 1
p.MaxFractionDigits = p.MaxSignificantDigits - 1
p.MinSignificantDigits, p.MaxSignificantDigits = 0, 0
return p.exponent
}
func (p *parser) fraction(r rune) state {
switch r {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
p.RoundIncrement = p.RoundIncrement*10 + uint32(r-'0')
p.MinFractionDigits++
p.MaxFractionDigits++
case '#':
p.MaxFractionDigits++
case 'E':
if p.leadingSharps > 0 {
p.MaxIntegerDigits = uint8(p.leadingSharps) + p.MinIntegerDigits
}
return p.exponent
default:
return nil
}
return p.fraction
}
func (p *parser) exponent(r rune) state {
switch r {
case '+':
// Set mode and check it wasn't already set.
if p.Flags&AlwaysExpSign != 0 || p.MinExponentDigits > 0 {
break
}
p.Flags |= AlwaysExpSign
p.doNotTerminate = true
return p.exponent
case '0':
p.MinExponentDigits++
return p.exponent
}
// termination condition
if p.MinExponentDigits == 0 {
p.setError(errors.New("format: need at least one digit"))
}
return nil
}

View file

@ -0,0 +1,300 @@
// 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.
package number
import (
"reflect"
"testing"
"unsafe"
)
var testCases = []struct {
pat string
want *Format
}{{
"#",
&Format{
FormatWidth: 1,
// TODO: Should MinIntegerDigits be 1?
},
}, {
"0",
&Format{
FormatWidth: 1,
MinIntegerDigits: 1,
},
}, {
"0000",
&Format{
FormatWidth: 4,
MinIntegerDigits: 4,
},
}, {
".#",
&Format{
FormatWidth: 2,
MaxFractionDigits: 1,
},
}, {
"#0.###",
&Format{
FormatWidth: 6,
MinIntegerDigits: 1,
MaxFractionDigits: 3,
},
}, {
"#0.######",
&Format{
FormatWidth: 9,
MinIntegerDigits: 1,
MaxFractionDigits: 6,
},
}, {
"#,##0.###",
&Format{
FormatWidth: 9,
GroupingSize: [2]uint8{3, 0},
MinIntegerDigits: 1,
MaxFractionDigits: 3,
},
}, {
"#,##,##0.###",
&Format{
FormatWidth: 12,
GroupingSize: [2]uint8{3, 2},
MinIntegerDigits: 1,
MaxFractionDigits: 3,
},
}, {
// Ignore additional separators.
"#,####,##,##0.###",
&Format{
FormatWidth: 17,
GroupingSize: [2]uint8{3, 2},
MinIntegerDigits: 1,
MaxFractionDigits: 3,
},
}, {
"#E0",
&Format{
FormatWidth: 3,
MaxIntegerDigits: 1,
MinExponentDigits: 1,
},
}, {
"0E0",
&Format{
FormatWidth: 3,
MinIntegerDigits: 1,
MinExponentDigits: 1,
},
}, {
"##00.0#E0",
&Format{
FormatWidth: 9,
MinIntegerDigits: 2,
MaxIntegerDigits: 4,
MinFractionDigits: 1,
MaxFractionDigits: 2,
MinExponentDigits: 1,
},
}, {
"#00.0E+0",
&Format{
FormatWidth: 8,
Flags: AlwaysExpSign,
MinIntegerDigits: 2,
MaxIntegerDigits: 3,
MinFractionDigits: 1,
MaxFractionDigits: 1,
MinExponentDigits: 1,
},
}, {
"0.0E++0",
nil,
}, {
"#0E+",
nil,
}, {
// significant digits
"@",
&Format{
FormatWidth: 1,
MinSignificantDigits: 1,
MaxSignificantDigits: 1,
},
}, {
// significant digits
"@@@@",
&Format{
FormatWidth: 4,
MinSignificantDigits: 4,
MaxSignificantDigits: 4,
},
}, {
"@###",
&Format{
FormatWidth: 4,
MinSignificantDigits: 1,
MaxSignificantDigits: 4,
},
}, {
// Exponents in significant digits mode gets normalized.
"@@E0",
&Format{
FormatWidth: 4,
MinIntegerDigits: 1,
MaxIntegerDigits: 1,
MinFractionDigits: 1,
MaxFractionDigits: 1,
MinExponentDigits: 1,
},
}, {
"@###E00",
&Format{
FormatWidth: 7,
MinIntegerDigits: 1,
MaxIntegerDigits: 1,
MinFractionDigits: 0,
MaxFractionDigits: 3,
MinExponentDigits: 2,
},
}, {
// The significant digits mode does not allow fractions.
"@###.#E0",
nil,
}, {
//alternative negative pattern
"#0.###;(#0.###)",
&Format{
Affix: "\x00\x00\x01(\x01)",
NegOffset: 2,
FormatWidth: 6,
MinIntegerDigits: 1,
MaxFractionDigits: 3,
},
}, {
// Rounding increments
"1.05",
&Format{
RoundIncrement: 105,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
"0.0%",
&Format{
Affix: "\x00\x01%",
Multiplier: 100,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 1,
MaxFractionDigits: 1,
},
}, {
"0.0‰",
&Format{
Affix: "\x00\x03‰",
Multiplier: 1000,
FormatWidth: 4,
MinIntegerDigits: 1,
MinFractionDigits: 1,
MaxFractionDigits: 1,
},
}, {
"#,##0.00¤",
&Format{
Affix: "\x00\x02¤",
FormatWidth: 9,
GroupingSize: [2]uint8{3, 0},
MinIntegerDigits: 1,
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
"#,##0.00 ¤;(#,##0.00 ¤)",
&Format{Affix: "\x00\x04\u00a0¤\x01(\x05\u00a0¤)",
NegOffset: 6,
Multiplier: 0,
FormatWidth: 10,
GroupingSize: [2]uint8{3, 0},
MinIntegerDigits: 1,
MinFractionDigits: 2,
MaxFractionDigits: 2,
},
}, {
// padding
"*x#",
&Format{
PadRune: 'x',
FormatWidth: 1,
},
}, {
// padding
"#*x",
&Format{
PadRune: 'x',
FormatWidth: 1,
Flags: PadBeforeSuffix,
},
}, {
"*xpre#suf",
&Format{
Affix: "\x03pre\x03suf",
PadRune: 'x',
FormatWidth: 7,
},
}, {
"pre*x#suf",
&Format{
Affix: "\x03pre\x03suf",
PadRune: 'x',
FormatWidth: 7,
Flags: PadAfterPrefix,
},
}, {
"pre#*xsuf",
&Format{
Affix: "\x03pre\x03suf",
PadRune: 'x',
FormatWidth: 7,
Flags: PadBeforeSuffix,
},
}, {
"pre#suf*x",
&Format{
Affix: "\x03pre\x03suf",
PadRune: 'x',
FormatWidth: 7,
Flags: PadAfterSuffix,
},
}, {
// no duplicate padding
"*xpre#suf*x", nil,
}, {
// no duplicate padding
"*xpre#suf*x", nil,
}}
func TestParsePattern(t *testing.T) {
for i, tc := range testCases {
f, err := ParsePattern(tc.pat)
if !reflect.DeepEqual(f, tc.want) {
t.Errorf("%d:%s:\ngot %#v;\nwant %#v", i, tc.pat, f, tc.want)
}
if got, want := err != nil, tc.want == nil; got != want {
t.Errorf("%d:%s:error: got %v; want %v", i, tc.pat, err, want)
}
}
}
func TestPatternSize(t *testing.T) {
if sz := unsafe.Sizeof(Format{}); sz > 48 {
t.Errorf("got %d; want 48", sz)
}
}

119
vendor/golang.org/x/text/internal/number/plural.go generated vendored Normal file
View file

@ -0,0 +1,119 @@
// Copyright 2016 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 number
import "golang.org/x/text/internal/format/plural"
type pluralRules struct {
rules []pluralCheck
index []byte
langToIndex []byte
inclusionMasks []uint64
}
var (
ordinalData = pluralRules{
ordinalRules,
ordinalIndex,
ordinalLangToIndex,
ordinalInclusionMasks[:],
}
cardinalData = pluralRules{
cardinalRules,
cardinalIndex,
cardinalLangToIndex,
cardinalInclusionMasks[:],
}
)
// See gen_plural.go for an explanation of the algorithm.
func matchPlural(p *pluralRules, index int, n, f, v int) plural.Form {
nMask := p.inclusionMasks[n%maxMod]
// Compute the fMask inline in the rules below, as it is relatively rare.
// fMask := p.inclusionMasks[f%maxMod]
vMask := p.inclusionMasks[v%maxMod]
// Do the matching
offset := p.langToIndex[index]
rules := p.rules[p.index[offset]:p.index[offset+1]]
for i := 0; i < len(rules); i++ {
rule := rules[i]
setBit := uint64(1 << rule.setID)
var skip bool
switch op := opID(rule.cat >> opShift); op {
case opI: // i = x
skip = n >= numN || nMask&setBit == 0
case opI | opNotEqual: // i != x
skip = n < numN && nMask&setBit != 0
case opI | opMod: // i % m = x
skip = nMask&setBit == 0
case opI | opMod | opNotEqual: // i % m != x
skip = nMask&setBit != 0
case opN: // n = x
skip = f != 0 || n >= numN || nMask&setBit == 0
case opN | opNotEqual: // n != x
skip = f == 0 && n < numN && nMask&setBit != 0
case opN | opMod: // n % m = x
skip = f != 0 || nMask&setBit == 0
case opN | opMod | opNotEqual: // n % m != x
skip = f == 0 && nMask&setBit != 0
case opF: // f = x
skip = f >= numN || p.inclusionMasks[f%maxMod]&setBit == 0
case opF | opNotEqual: // f != x
skip = f < numN && p.inclusionMasks[f%maxMod]&setBit != 0
case opF | opMod: // f % m = x
skip = p.inclusionMasks[f%maxMod]&setBit == 0
case opF | opMod | opNotEqual: // f % m != x
skip = p.inclusionMasks[f%maxMod]&setBit != 0
case opV: // v = x
skip = v < numN && vMask&setBit == 0
case opV | opNotEqual: // v != x
skip = v < numN && vMask&setBit != 0
case opW: // w == 0
skip = f != 0
case opW | opNotEqual: // w != 0
skip = f == 0
// Hard-wired rules that cannot be handled by our algorithm.
case opBretonM:
skip = f != 0 || n == 0 || n%1000000 != 0
case opAzerbaijan00s:
// 100,200,300,400,500,600,700,800,900
skip = n == 0 || n >= 1000 || n%100 != 0
case opItalian800:
skip = (f != 0 || n >= numN || nMask&setBit == 0) && n != 800
}
if skip {
// advance over AND entries.
for ; i < len(rules) && rules[i].cat&formMask == andNext; i++ {
}
continue
}
// return if we have a final entry.
if cat := rule.cat & formMask; cat != andNext {
return plural.Form(cat)
}
}
return plural.Other
}

110
vendor/golang.org/x/text/internal/number/plural_test.go generated vendored Normal file
View file

@ -0,0 +1,110 @@
// Copyright 2016 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 number
import (
"strconv"
"strings"
"testing"
"golang.org/x/text/language"
)
func TestOrdinal(t *testing.T) {
testPlurals(t, &ordinalData, ordinalTests)
}
func TestCardinal(t *testing.T) {
testPlurals(t, &cardinalData, cardinalTests)
}
func testPlurals(t *testing.T, p *pluralRules, testCases []pluralTest) {
for _, tc := range testCases {
for _, loc := range strings.Split(tc.locales, " ") {
langIndex, _ := language.CompactIndex(language.MustParse(loc))
// Test integers
for _, s := range tc.integer {
a := strings.Split(s, "~")
from := parseUint(t, a[0])
to := from
if len(a) > 1 {
to = parseUint(t, a[1])
}
for n := from; n <= to; n++ {
if f := matchPlural(p, langIndex, n, 0, 0); f != tc.form {
t.Errorf("%s:int(%d) = %v; want %v", loc, n, f, tc.form)
}
}
}
// Test decimals
for _, s := range tc.decimal {
a := strings.Split(s, "~")
from, scale := parseFixedPoint(t, a[0])
to := from
if len(a) > 1 {
var toScale int
if to, toScale = parseFixedPoint(t, a[1]); toScale != scale {
t.Fatalf("%s:%s: non-matching scales %d versus %d", loc, s, scale, toScale)
}
}
m := 1
for i := 0; i < scale; i++ {
m *= 10
}
for n := from; n <= to; n++ {
if f := matchPlural(p, langIndex, n/m, n%m, scale); f != tc.form {
t.Errorf("%[1]s:dec(%[2]d.%0[4]*[3]d) = %[5]v; want %[6]v", loc, n/m, n%m, scale, f, tc.form)
}
}
}
}
}
}
func parseUint(t *testing.T, s string) int {
val, err := strconv.ParseUint(s, 10, 32)
if err != nil {
t.Fatal(err)
}
return int(val)
}
func parseFixedPoint(t *testing.T, s string) (val, scale int) {
p := strings.Index(s, ".")
s = strings.Replace(s, ".", "", 1)
v, err := strconv.ParseUint(s, 10, 32)
if err != nil {
t.Fatal(err)
}
return int(v), len(s) - p
}
func BenchmarkPluralSimpleCases(b *testing.B) {
p := &cardinalData
en, _ := language.CompactIndex(language.English)
zh, _ := language.CompactIndex(language.Chinese)
for i := 0; i < b.N; i++ {
matchPlural(p, en, 0, 0, 0) // 0
matchPlural(p, en, 1, 0, 0) // 1
matchPlural(p, en, 2, 12, 3) // 2.120
matchPlural(p, zh, 0, 0, 0) // 0
matchPlural(p, zh, 1, 0, 0) // 1
matchPlural(p, zh, 2, 12, 3) // 2.120
}
}
func BenchmarkPluralComplexCases(b *testing.B) {
p := &cardinalData
ar, _ := language.CompactIndex(language.Arabic)
lv, _ := language.CompactIndex(language.Latvian)
for i := 0; i < b.N; i++ {
matchPlural(p, lv, 0, 19, 2) // 0.19
matchPlural(p, lv, 11, 0, 3) // 11.000
matchPlural(p, lv, 100, 123, 4) // 0.1230
matchPlural(p, ar, 0, 0, 0) // 0
matchPlural(p, ar, 110, 0, 0) // 110
matchPlural(p, ar, 99, 99, 2) // 99.99
}
}

1633
vendor/golang.org/x/text/internal/number/tables.go generated vendored Normal file

File diff suppressed because it is too large Load diff

125
vendor/golang.org/x/text/internal/number/tables_test.go generated vendored Normal file
View file

@ -0,0 +1,125 @@
// Copyright 2016 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 number
import (
"flag"
"log"
"reflect"
"testing"
"golang.org/x/text/internal/gen"
"golang.org/x/text/internal/testtext"
"golang.org/x/text/language"
"golang.org/x/text/unicode/cldr"
)
var draft = flag.String("draft",
"contributed",
`Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
func TestNumberSystems(t *testing.T) {
testtext.SkipIfNotLong(t)
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
d.SetDirFilter("supplemental")
d.SetSectionFilter("numberingSystem")
data, err := d.DecodeZip(r)
if err != nil {
t.Fatalf("DecodeZip: %v", err)
}
for _, ns := range data.Supplemental().NumberingSystems.NumberingSystem {
n := systemMap[ns.Id]
if int(n) >= len(numSysData) {
continue
}
info := InfoFromLangID(0, ns.Id)
val := '0'
for _, rWant := range ns.Digits {
if rGot := info.Digit(val); rGot != rWant {
t.Errorf("%s:%d: got %U; want %U", ns.Id, val, rGot, rWant)
}
val++
}
}
}
func TestSymbols(t *testing.T) {
testtext.SkipIfNotLong(t)
draft, err := cldr.ParseDraft(*draft)
if err != nil {
log.Fatalf("invalid draft level: %v", err)
}
r := gen.OpenCLDRCoreZip()
defer r.Close()
d := &cldr.Decoder{}
d.SetDirFilter("main")
d.SetSectionFilter("numbers")
data, err := d.DecodeZip(r)
if err != nil {
t.Fatalf("DecodeZip: %v", err)
}
for _, lang := range data.Locales() {
ldml := data.RawLDML(lang)
if ldml.Numbers == nil {
continue
}
langIndex, ok := language.CompactIndex(language.MustParse(lang))
if !ok {
t.Fatalf("No compact index for language %s", lang)
}
syms := cldr.MakeSlice(&ldml.Numbers.Symbols)
syms.SelectDraft(draft)
for _, sym := range ldml.Numbers.Symbols {
if sym.NumberSystem == "" {
continue
}
testCases := []struct {
name string
st SymbolType
x interface{}
}{
{"Decimal", SymDecimal, sym.Decimal},
{"Group", SymGroup, sym.Group},
{"List", SymList, sym.List},
{"PercentSign", SymPercentSign, sym.PercentSign},
{"PlusSign", SymPlusSign, sym.PlusSign},
{"MinusSign", SymMinusSign, sym.MinusSign},
{"Exponential", SymExponential, sym.Exponential},
{"SuperscriptingExponent", SymSuperscriptingExponent, sym.SuperscriptingExponent},
{"PerMille", SymPerMille, sym.PerMille},
{"Infinity", SymInfinity, sym.Infinity},
{"NaN", SymNan, sym.Nan},
{"TimeSeparator", SymTimeSeparator, sym.TimeSeparator},
}
info := InfoFromLangID(langIndex, sym.NumberSystem)
for _, tc := range testCases {
// Extract the wanted value.
v := reflect.ValueOf(tc.x)
if v.Len() == 0 {
return
}
if v.Len() > 1 {
t.Fatalf("Multiple values of %q within single symbol not supported.", tc.name)
}
want := v.Index(0).MethodByName("Data").Call(nil)[0].String()
got := info.Symbol(tc.st)
if got != want {
t.Errorf("%s:%s:%s: got %q; want %q", lang, sym.NumberSystem, tc.name, got, want)
}
}
}
}
}

86
vendor/golang.org/x/text/internal/stringset/set.go generated vendored Normal file
View file

@ -0,0 +1,86 @@
// Copyright 2016 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 stringset provides a way to represent a collection of strings
// compactly.
package stringset
import "sort"
// A Set holds a collection of strings that can be looked up by an index number.
type Set struct {
// These fields are exported to allow for code generation.
Data string
Index []uint16
}
// Elem returns the string with index i. It panics if i is out of range.
func (s *Set) Elem(i int) string {
return s.Data[s.Index[i]:s.Index[i+1]]
}
// Len returns the number of strings in the set.
func (s *Set) Len() int {
return len(s.Index) - 1
}
// Search returns the index of the given string or -1 if it is not in the set.
// The Set must have been created with strings in sorted order.
func Search(s *Set, str string) int {
// TODO: optimize this if it gets used a lot.
n := len(s.Index) - 1
p := sort.Search(n, func(i int) bool {
return s.Elem(i) >= str
})
if p == n || str != s.Elem(p) {
return -1
}
return p
}
// A Builder constructs Sets.
type Builder struct {
set Set
index map[string]int
}
// NewBuilder returns a new and initialized Builder.
func NewBuilder() *Builder {
return &Builder{
set: Set{
Index: []uint16{0},
},
index: map[string]int{},
}
}
// Set creates the set created so far.
func (b *Builder) Set() Set {
return b.set
}
// Index returns the index for the given string, which must have been added
// before.
func (b *Builder) Index(s string) int {
return b.index[s]
}
// Add adds a string to the index. Strings that are added by a single Add will
// be stored together, unless they match an existing string.
func (b *Builder) Add(ss ...string) {
// First check if the string already exists.
for _, s := range ss {
if _, ok := b.index[s]; ok {
continue
}
b.index[s] = len(b.set.Index) - 1
b.set.Data += s
x := len(b.set.Data)
if x > 0xFFFF {
panic("Index too > 0xFFFF")
}
b.set.Index = append(b.set.Index, uint16(x))
}
}

View file

@ -0,0 +1,53 @@
// Copyright 2016 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 stringset
import "testing"
func TestStringSet(t *testing.T) {
testCases := [][]string{
{""},
{"∫"},
{"a", "b", "c"},
{"", "a", "bb", "ccc"},
{" ", "aaa", "bb", "c"},
}
test := func(tc int, b *Builder) {
set := b.Set()
if set.Len() != len(testCases[tc]) {
t.Errorf("%d:Len() = %d; want %d", tc, set.Len(), len(testCases[tc]))
}
for i, s := range testCases[tc] {
if x := b.Index(s); x != i {
t.Errorf("%d:Index(%q) = %d; want %d", tc, s, x, i)
}
if p := Search(&set, s); p != i {
t.Errorf("%d:Search(%q) = %d; want %d", tc, s, p, i)
}
if set.Elem(i) != s {
t.Errorf("%d:Elem(%d) = %s; want %s", tc, i, set.Elem(i), s)
}
}
if p := Search(&set, "apple"); p != -1 {
t.Errorf(`%d:Search("apple") = %d; want -1`, tc, p)
}
}
for i, tc := range testCases {
b := NewBuilder()
for _, s := range tc {
b.Add(s)
}
b.Add(tc...)
test(i, b)
}
for i, tc := range testCases {
b := NewBuilder()
b.Add(tc...)
for _, s := range tc {
b.Add(s)
}
test(i, b)
}
}

116
vendor/golang.org/x/text/internal/tables.go generated vendored Normal file
View file

@ -0,0 +1,116 @@
// This file was generated by go generate; DO NOT EDIT
package internal
// Parent maps a compact index of a tag to the compact index of the parent of
// this tag.
var Parent = []uint16{ // 747 elements
// Entry 0 - 3F
0x0000, 0x0052, 0x00e3, 0x0000, 0x0003, 0x0003, 0x0000, 0x0006,
0x0000, 0x0008, 0x0000, 0x000a, 0x0000, 0x000c, 0x000c, 0x000c,
0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
0x000c, 0x0000, 0x0029, 0x0000, 0x002b, 0x0000, 0x002d, 0x0000,
0x0000, 0x0030, 0x002f, 0x002f, 0x0000, 0x0034, 0x0000, 0x0036,
0x0000, 0x0038, 0x0000, 0x003a, 0x0000, 0x003c, 0x0000, 0x0000,
// Entry 40 - 7F
0x003f, 0x0000, 0x0041, 0x0041, 0x0000, 0x0044, 0x0044, 0x0000,
0x0047, 0x0000, 0x0049, 0x0000, 0x0000, 0x004c, 0x004b, 0x004b,
0x0000, 0x0050, 0x0050, 0x0050, 0x0050, 0x0000, 0x0055, 0x0000,
0x0057, 0x0000, 0x0059, 0x0000, 0x005b, 0x005b, 0x0000, 0x005e,
0x0000, 0x0060, 0x0000, 0x0062, 0x0000, 0x0064, 0x0064, 0x0000,
0x0067, 0x0000, 0x0069, 0x0069, 0x0069, 0x0069, 0x0069, 0x0069,
0x0000, 0x0070, 0x0000, 0x0072, 0x0000, 0x0074, 0x0000, 0x0000,
0x0077, 0x0000, 0x0079, 0x0000, 0x007b, 0x0000, 0x007d, 0x007d,
// Entry 80 - BF
0x0000, 0x0080, 0x0080, 0x0000, 0x0083, 0x0084, 0x0084, 0x0084,
0x0083, 0x0085, 0x0084, 0x0084, 0x0084, 0x0083, 0x0084, 0x0084,
0x0084, 0x0084, 0x0084, 0x0084, 0x0085, 0x0084, 0x0084, 0x0084,
0x0084, 0x0085, 0x0084, 0x0085, 0x0084, 0x0084, 0x0085, 0x0084,
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
0x0083, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
0x0084, 0x0084, 0x0083, 0x0084, 0x0083, 0x0084, 0x0084, 0x0084,
// Entry C0 - FF
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0085, 0x0084, 0x0084,
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0083, 0x0084, 0x0084,
0x0084, 0x0084, 0x0084, 0x0085, 0x0084, 0x0084, 0x0085, 0x0084,
0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
0x0084, 0x0084, 0x0083, 0x0083, 0x0084, 0x0084, 0x0083, 0x0084,
0x0084, 0x0084, 0x0084, 0x0084, 0x0000, 0x00ec, 0x0000, 0x00ee,
0x00ef, 0x00ef, 0x00ef, 0x00ef, 0x00ef, 0x00ef, 0x00ef, 0x00ef,
0x00ee, 0x00ef, 0x00ee, 0x00ee, 0x00ef, 0x00ef, 0x00ee, 0x00ef,
// Entry 100 - 13F
0x00ef, 0x00ef, 0x00ef, 0x00ee, 0x00ef, 0x00ef, 0x00ef, 0x00ef,
0x00ef, 0x00ef, 0x0000, 0x010a, 0x0000, 0x010c, 0x0000, 0x010e,
0x0000, 0x0110, 0x0110, 0x0000, 0x0113, 0x0113, 0x0113, 0x0113,
0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x011c, 0x011c, 0x0000,
0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f,
0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f,
0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f,
0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f,
// Entry 140 - 17F
0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f,
0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x011f, 0x0000, 0x014e,
0x0000, 0x0150, 0x0000, 0x0152, 0x0000, 0x0154, 0x0000, 0x0156,
0x0000, 0x0158, 0x0158, 0x0158, 0x0000, 0x015c, 0x0000, 0x0000,
0x015f, 0x0000, 0x0161, 0x0000, 0x0163, 0x0163, 0x0163, 0x0000,
0x0167, 0x0000, 0x0169, 0x0000, 0x016b, 0x0000, 0x016d, 0x016d,
0x0000, 0x0170, 0x0000, 0x0172, 0x0000, 0x0174, 0x0000, 0x0176,
0x0000, 0x0178, 0x0000, 0x017a, 0x0000, 0x017c, 0x0000, 0x017e,
// Entry 180 - 1BF
0x017e, 0x017e, 0x0000, 0x0000, 0x0183, 0x0000, 0x0000, 0x0186,
0x0000, 0x0188, 0x0000, 0x0000, 0x018b, 0x0000, 0x018d, 0x0000,
0x0000, 0x0190, 0x0000, 0x0000, 0x0193, 0x0000, 0x0195, 0x0000,
0x0197, 0x0000, 0x0199, 0x0000, 0x019b, 0x0000, 0x019d, 0x0000,
0x019f, 0x0000, 0x01a1, 0x0000, 0x01a3, 0x0000, 0x01a5, 0x0000,
0x01a7, 0x01a7, 0x0000, 0x01aa, 0x0000, 0x01ac, 0x0000, 0x01ae,
0x0000, 0x01b0, 0x0000, 0x01b2, 0x0000, 0x0000, 0x01b5, 0x0000,
0x01b7, 0x0000, 0x01b9, 0x0000, 0x01bb, 0x0000, 0x01bd, 0x0000,
// Entry 1C0 - 1FF
0x01bf, 0x0000, 0x01c1, 0x01c1, 0x01c1, 0x01c1, 0x0000, 0x01c6,
0x0000, 0x01c8, 0x01c8, 0x0000, 0x01cb, 0x0000, 0x01cd, 0x0000,
0x01cf, 0x0000, 0x01d1, 0x0000, 0x01d3, 0x0000, 0x01d5, 0x01d5,
0x0000, 0x01d8, 0x0000, 0x01da, 0x0000, 0x01dc, 0x0000, 0x01de,
0x0000, 0x01e0, 0x0000, 0x01e2, 0x0000, 0x01e4, 0x0000, 0x01e6,
0x0000, 0x01e8, 0x0000, 0x01ea, 0x01ea, 0x01ea, 0x0000, 0x01ee,
0x0000, 0x01f0, 0x0000, 0x01f2, 0x0000, 0x01f4, 0x0000, 0x0000,
0x01f7, 0x0000, 0x01f9, 0x01f9, 0x0000, 0x01fc, 0x0000, 0x01fe,
// Entry 200 - 23F
0x01fe, 0x0000, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201, 0x0201,
0x0201, 0x0000, 0x0209, 0x0000, 0x020b, 0x0000, 0x020d, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0213, 0x0000, 0x0000, 0x0216,
0x0000, 0x0218, 0x0218, 0x0000, 0x021b, 0x0000, 0x021d, 0x021d,
0x0000, 0x0000, 0x0221, 0x0220, 0x0220, 0x0000, 0x0000, 0x0226,
0x0000, 0x0228, 0x0000, 0x022a, 0x0000, 0x0236, 0x022c, 0x0236,
0x0236, 0x0236, 0x0236, 0x0236, 0x0236, 0x0236, 0x022c, 0x0236,
0x0236, 0x0000, 0x0239, 0x0239, 0x0239, 0x0000, 0x023d, 0x0000,
// Entry 240 - 27F
0x023f, 0x0000, 0x0241, 0x0241, 0x0000, 0x0244, 0x0000, 0x0246,
0x0246, 0x0246, 0x0246, 0x0246, 0x0246, 0x0000, 0x024d, 0x0000,
0x024f, 0x0000, 0x0251, 0x0000, 0x0253, 0x0000, 0x0255, 0x0000,
0x0000, 0x0258, 0x0258, 0x0258, 0x0000, 0x025c, 0x0000, 0x025e,
0x0000, 0x0260, 0x0000, 0x0000, 0x0263, 0x0262, 0x0262, 0x0000,
0x0267, 0x0000, 0x0269, 0x0000, 0x026b, 0x0000, 0x0000, 0x0000,
0x0000, 0x0270, 0x0000, 0x0000, 0x0273, 0x0000, 0x0275, 0x0275,
0x0275, 0x0275, 0x0000, 0x027a, 0x027a, 0x027a, 0x0000, 0x027e,
// Entry 280 - 2BF
0x027e, 0x027e, 0x027e, 0x027e, 0x0000, 0x0284, 0x0284, 0x0284,
0x0284, 0x0000, 0x0000, 0x0000, 0x0000, 0x028c, 0x028c, 0x028c,
0x0000, 0x0290, 0x0290, 0x0290, 0x0290, 0x0000, 0x0000, 0x0296,
0x0296, 0x0296, 0x0296, 0x0000, 0x029b, 0x0000, 0x029d, 0x029d,
0x0000, 0x02a0, 0x0000, 0x02a2, 0x02a2, 0x0000, 0x0000, 0x02a6,
0x0000, 0x0000, 0x02a9, 0x0000, 0x02ab, 0x02ab, 0x0000, 0x0000,
0x02af, 0x0000, 0x02b1, 0x0000, 0x02b3, 0x0000, 0x02b5, 0x0000,
0x02b7, 0x02b7, 0x0000, 0x0000, 0x02bb, 0x0000, 0x02bd, 0x02ba,
// Entry 2C0 - 2FF
0x02ba, 0x0000, 0x0000, 0x02c2, 0x02c1, 0x02c1, 0x0000, 0x0000,
0x02c7, 0x0000, 0x02c9, 0x0000, 0x02cb, 0x0000, 0x0000, 0x02ce,
0x0000, 0x0000, 0x0000, 0x02d2, 0x0000, 0x02d4, 0x0000, 0x02d6,
0x0000, 0x02d8, 0x02d8, 0x0000, 0x02db, 0x0000, 0x02dd, 0x0000,
0x02df, 0x02df, 0x02df, 0x02df, 0x02df, 0x0000, 0x02e5, 0x02e6,
0x02e5, 0x0000, 0x02e9,
} // Size: 1518 bytes
// Total table size 1518 bytes (1KiB); checksum: 836CD65C

100
vendor/golang.org/x/text/internal/tag/tag.go generated vendored Normal file
View file

@ -0,0 +1,100 @@
// 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.
// Package tag contains functionality handling tags and related data.
package tag // import "golang.org/x/text/internal/tag"
import "sort"
// An Index converts tags to a compact numeric value.
//
// All elements are of size 4. Tags may be up to 4 bytes long. Excess bytes can
// be used to store additional information about the tag.
type Index string
// Elem returns the element data at the given index.
func (s Index) Elem(x int) string {
return string(s[x*4 : x*4+4])
}
// Index reports the index of the given key or -1 if it could not be found.
// Only the first len(key) bytes from the start of the 4-byte entries will be
// considered for the search and the first match in Index will be returned.
func (s Index) Index(key []byte) int {
n := len(key)
// search the index of the first entry with an equal or higher value than
// key in s.
index := sort.Search(len(s)/4, func(i int) bool {
return cmp(s[i*4:i*4+n], key) != -1
})
i := index * 4
if cmp(s[i:i+len(key)], key) != 0 {
return -1
}
return index
}
// Next finds the next occurrence of key after index x, which must have been
// obtained from a call to Index using the same key. It returns x+1 or -1.
func (s Index) Next(key []byte, x int) int {
if x++; x*4 < len(s) && cmp(s[x*4:x*4+len(key)], key) == 0 {
return x
}
return -1
}
// cmp returns an integer comparing a and b lexicographically.
func cmp(a Index, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
for i, c := range b[:n] {
switch {
case a[i] > c:
return 1
case a[i] < c:
return -1
}
}
switch {
case len(a) < len(b):
return -1
case len(a) > len(b):
return 1
}
return 0
}
// Compare returns an integer comparing a and b lexicographically.
func Compare(a string, b []byte) int {
return cmp(Index(a), b)
}
// FixCase reformats b to the same pattern of cases as form.
// If returns false if string b is malformed.
func FixCase(form string, b []byte) bool {
if len(form) != len(b) {
return false
}
for i, c := range b {
if form[i] <= 'Z' {
if c >= 'a' {
c -= 'z' - 'Z'
}
if c < 'A' || 'Z' < c {
return false
}
} else {
if c <= 'Z' {
c += 'z' - 'Z'
}
if c < 'a' || 'z' < c {
return false
}
}
b[i] = c
}
return true
}

67
vendor/golang.org/x/text/internal/tag/tag_test.go generated vendored Normal file
View file

@ -0,0 +1,67 @@
// 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.
package tag
import (
"strings"
"testing"
)
var strdata = []string{
"aa ",
"aaa ",
"aaaa",
"aaab",
"aab ",
"ab ",
"ba ",
"xxxx",
"\xff\xff\xff\xff",
}
var testCases = map[string]int{
"a": 0,
"aa": 0,
"aaa": 1,
"aa ": 0,
"aaaa": 2,
"aaab": 3,
"b": 6,
"ba": 6,
" ": -1,
"aaax": -1,
"bbbb": -1,
"zzzz": -1,
}
func TestIndex(t *testing.T) {
index := Index(strings.Join(strdata, ""))
for k, v := range testCases {
if i := index.Index([]byte(k)); i != v {
t.Errorf("%s: got %d; want %d", k, i, v)
}
}
}
func TestFixCase(t *testing.T) {
tests := []string{
"aaaa", "AbCD", "abcd",
"Zzzz", "AbCD", "Abcd",
"Zzzz", "AbC", "",
"XXX", "ab ", "",
"XXX", "usd", "USD",
"cmn", "AB ", "",
"gsw", "CMN", "cmn",
}
for tc := tests; len(tc) > 0; tc = tc[3:] {
b := []byte(tc[1])
if !FixCase(tc[0], b) {
b = nil
}
if string(b) != tc[2] {
t.Errorf("FixCase(%q, %q) = %q; want %q", tc[0], tc[1], b, tc[2])
}
}
}

53
vendor/golang.org/x/text/internal/testtext/codesize.go generated vendored Normal file
View file

@ -0,0 +1,53 @@
// 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.
package testtext
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
)
// CodeSize builds the given code sample and returns the binary size or en error
// if an error occurred. The code sample typically will look like this:
// package main
// import "golang.org/x/text/somepackage"
// func main() {
// somepackage.Func() // reference Func to cause it to be linked in.
// }
// See dict_test.go in the display package for an example.
func CodeSize(s string) (int, error) {
// Write the file.
tmpdir, err := ioutil.TempDir(os.TempDir(), "testtext")
if err != nil {
return 0, fmt.Errorf("testtext: failed to create tmpdir: %v", err)
}
defer os.RemoveAll(tmpdir)
filename := filepath.Join(tmpdir, "main.go")
if err := ioutil.WriteFile(filename, []byte(s), 0644); err != nil {
return 0, fmt.Errorf("testtext: failed to write main.go: %v", err)
}
// Build the binary.
w := &bytes.Buffer{}
cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), "build", "-o", "main")
cmd.Dir = tmpdir
cmd.Stderr = w
cmd.Stdout = w
if err := cmd.Run(); err != nil {
return 0, fmt.Errorf("testtext: failed to execute command: %v\nmain.go:\n%vErrors:%s", err, s, w)
}
// Determine the size.
fi, err := os.Stat(filepath.Join(tmpdir, "main"))
if err != nil {
return 0, fmt.Errorf("testtext: failed to get file info: %v", err)
}
return int(fi.Size()), nil
}

22
vendor/golang.org/x/text/internal/testtext/flag.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
// 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.
package testtext
import (
"flag"
"testing"
"golang.org/x/text/internal/gen"
)
var long = flag.Bool("long", false,
"run tests that require fetching data online")
// SkipIfNotLong returns whether long tests should be performed.
func SkipIfNotLong(t *testing.T) {
if !gen.IsLocal() && !*long {
t.Skip("skipping test to prevent downloading; to run use -long or use -local or UNICODE_DIR to specify a local source")
}
}

14
vendor/golang.org/x/text/internal/testtext/gc.go generated vendored Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2016 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 !gccgo
package testtext
import "testing"
// AllocsPerRun wraps testing.AllocsPerRun.
func AllocsPerRun(runs int, f func()) (avg float64) {
return testing.AllocsPerRun(runs, f)
}

11
vendor/golang.org/x/text/internal/testtext/gccgo.go generated vendored Normal file
View file

@ -0,0 +1,11 @@
// Copyright 2016 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 gccgo
package testtext
// AllocsPerRun always returns 0 for gccgo until gccgo implements escape
// analysis equal or better to that of gc.
func AllocsPerRun(runs int, f func()) (avg float64) { return 0 }

14
vendor/golang.org/x/text/internal/testtext/go1_6.go generated vendored Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2016 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 !go1.7
package testtext
import "testing"
func Run(t *testing.T, name string, fn func(t *testing.T)) {
t.Logf("Running %s...", name)
fn(t)
}

13
vendor/golang.org/x/text/internal/testtext/go1_7.go generated vendored Normal file
View file

@ -0,0 +1,13 @@
// Copyright 2016 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 go1.7
package testtext
import "testing"
func Run(t *testing.T, name string, fn func(t *testing.T)) {
t.Run(name, fn)
}

105
vendor/golang.org/x/text/internal/testtext/text.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
// 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.
// Package testtext contains test data that is of common use to the text
// repository.
package testtext // import "golang.org/x/text/internal/testtext"
const (
// ASCII is an ASCII string containing all letters in the English alphabet.
ASCII = "The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. " +
"The quick brown fox jumps over the lazy dog. "
// Vietnamese is a snippet from http://creativecommons.org/licenses/by-sa/3.0/vn/
Vietnamese = `Với các điều kiện sau: Ghi nhận công của tác giả.
Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ
nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc
một giấy phép khác các điều khoản tương tự như giấy phép này
cho dự án của bạn. Hiểu rằng: Miễn Bất kỳ các điều kiện nào
trên đây cũng thể được miễn bỏ nếu bạn được sự cho phép của
người sở hữu bản quyền. Phạm vi công chúng Khi tác phẩm hoặc
bất kỳ chương nào của tác phẩm đã trong vùng dành cho công
chúng theo quy định của pháp luật thì tình trạng của không
bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.`
// Russian is a snippet from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
Russian = `При обязательном соблюдении следующих условий:
Attribution Вы должны атрибутировать произведение (указывать
автора и источник) в порядке, предусмотренном автором или
лицензиаром (но только так, чтобы никоим образом не подразумевалось,
что они поддерживают вас или использование вами данного произведения).
Υπό τις ακόλουθες προϋποθέσεις:`
// Greek is a snippet from http://creativecommons.org/licenses/by-sa/3.0/gr/
Greek = `Αναφορά Δημιουργού Θα πρέπει να κάνετε την αναφορά στο έργο με τον
τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια
(χωρίς όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή
τη χρήση του έργου από εσάς). Παρόμοια Διανομή Εάν αλλοιώσετε,
τροποποιήσετε ή δημιουργήσετε περαιτέρω βασισμένοι στο έργο θα
μπορείτε να διανέμετε το έργο που θα προκύψει μόνο με την ίδια ή
παρόμοια άδεια.`
// Arabic is a snippet from http://creativecommons.org/licenses/by-sa/3.0/deed.ar
Arabic = `بموجب الشروط التالية نسب المصنف يجب عليك أن
تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من
الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).
المشاركة على قدم المساواة إذا كنت يعدل ، والتغيير ، أو الاستفادة
من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد
لهذا الترخيص.`
// Hebrew is a snippet from http://creativecommons.org/licenses/by-sa/1.0/il/
Hebrew = `בכפוף לתנאים הבאים: ייחוס עליך לייחס את היצירה (לתת קרדיט) באופן
המצויין על-ידי היוצר או מעניק הרישיון (אך לא בשום אופן המרמז על כך
שהם תומכים בך או בשימוש שלך ביצירה). שיתוף זהה אם תחליט/י לשנות,
לעבד או ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/י להפיץ את יצירתך
החדשה רק תחת אותו הרישיון או רישיון דומה לרישיון זה.`
TwoByteUTF8 = Russian + Greek + Arabic + Hebrew
// Thai is a snippet from http://creativecommons.org/licenses/by-sa/3.0/th/
Thai = `ภายใต้เงื่อนไข ดังต่อไปนี้ : แสดงที่มา คุณต้องแสดงที่
มาของงานดังกล่าว ตามรูปแบบที่ผู้สร้างสรรค์หรือผู้อนุญาตกำหนด (แต่
ไม่ใช่ในลักษณะที่ว่า พวกเขาสนับสนุนคุณหรือสนับสนุนการที่
คุณนำงานไปใช้) อนุญาตแบบเดียวกัน หากคุณดัดแปลง เปลี่ยนรูป หรื
อต่อเติมงานนี้ คุณต้องใช้สัญญาอนุญาตแบบเดียวกันหรือแบบที่เหมื
อนกับสัญญาอนุญาตที่ใช้กับงานนี้เท่านั้น`
ThreeByteUTF8 = Thai
// Japanese is a snippet from http://creativecommons.org/licenses/by-sa/2.0/jp/
Japanese = `あなたの従うべき条件は以下の通りです
表示 あなたは原著作者のクレジットを表示しなければなりません
継承 もしあなたがこの作品を改変変形または加工した場合
あなたはその結果生じた作品をこの作品と同一の許諾条件の下でのみ
頒布することができます`
// Chinese is a snippet from http://creativecommons.org/licenses/by-sa/2.5/cn/
Chinese = `您可以自由 复制发行展览表演放映
广播或通过信息网络传播本作品 创作演绎作品
对本作品进行商业性使用 惟须遵守下列条件
署名 您必须按照作者或者许可人指定的方式对作品进行署名
相同方式共享 如果您改变转换本作品或者以本作品为基础进行创作
您只能采用与本协议相同的许可协议发布基于本作品的演绎作品`
// Korean is a snippet from http://creativecommons.org/licenses/by-sa/2.0/kr/
Korean = `다음과 같은 조건을 따라야 합니다: 저작자표시
저작자나 이용허락자가 정한 방법으로 저작물의
원저작자를 표시하여야 합니다(그러나 원저작자가 이용자나 이용자의
이용을 보증하거나 추천한다는 의미로 표시해서는 안됩니다).
동일조건변경허락 저작물을 이용하여 만든 이차적 저작물에는
라이선스와 동일한 라이선스를 적용해야 합니다.`
CJK = Chinese + Japanese + Korean
All = ASCII + Vietnamese + TwoByteUTF8 + ThreeByteUTF8 + CJK
)

58
vendor/golang.org/x/text/internal/triegen/compact.go generated vendored Normal file
View file

@ -0,0 +1,58 @@
// Copyright 2014 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 triegen
// This file defines Compacter and its implementations.
import "io"
// A Compacter generates an alternative, more space-efficient way to store a
// trie value block. A trie value block holds all possible values for the last
// byte of a UTF-8 encoded rune. Excluding ASCII characters, a trie value block
// always has 64 values, as a UTF-8 encoding ends with a byte in [0x80, 0xC0).
type Compacter interface {
// Size returns whether the Compacter could encode the given block as well
// as its size in case it can. len(v) is always 64.
Size(v []uint64) (sz int, ok bool)
// Store stores the block using the Compacter's compression method.
// It returns a handle with which the block can be retrieved.
// len(v) is always 64.
Store(v []uint64) uint32
// Print writes the data structures associated to the given store to w.
Print(w io.Writer) error
// Handler returns the name of a function that gets called during trie
// lookup for blocks generated by the Compacter. The function should be of
// the form func (n uint32, b byte) uint64, where n is the index returned by
// the Compacter's Store method and b is the last byte of the UTF-8
// encoding, where 0x80 <= b < 0xC0, for which to do the lookup in the
// block.
Handler() string
}
// simpleCompacter is the default Compacter used by builder. It implements a
// normal trie block.
type simpleCompacter builder
func (b *simpleCompacter) Size([]uint64) (sz int, ok bool) {
return blockSize * b.ValueSize, true
}
func (b *simpleCompacter) Store(v []uint64) uint32 {
h := uint32(len(b.ValueBlocks) - blockOffset)
b.ValueBlocks = append(b.ValueBlocks, v)
return h
}
func (b *simpleCompacter) Print(io.Writer) error {
// Structures are printed in print.go.
return nil
}
func (b *simpleCompacter) Handler() string {
panic("Handler should be special-cased for this Compacter")
}

875
vendor/golang.org/x/text/internal/triegen/data_test.go generated vendored Normal file
View file

@ -0,0 +1,875 @@
// This file is generated with "go test -tags generate". DO NOT EDIT!
// +build !generate
package triegen_test
// lookup returns the trie value for the first UTF-8 encoding in s and
// the width in bytes of this encoding. The size will be 0 if s does not
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
func (t *randTrie) lookup(s []byte) (v uint8, sz int) {
c0 := s[0]
switch {
case c0 < 0x80: // is ASCII
return randValues[c0], 1
case c0 < 0xC2:
return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
case c0 < 0xE0: // 2-byte UTF-8
if len(s) < 2 {
return 0, 0
}
i := randIndex[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c1), 2
case c0 < 0xF0: // 3-byte UTF-8
if len(s) < 3 {
return 0, 0
}
i := randIndex[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = randIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c2), 3
case c0 < 0xF8: // 4-byte UTF-8
if len(s) < 4 {
return 0, 0
}
i := randIndex[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = randIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
o = uint32(i)<<6 + uint32(c2)
i = randIndex[o]
c3 := s[3]
if c3 < 0x80 || 0xC0 <= c3 {
return 0, 3 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c3), 4
}
// Illegal rune
return 0, 1
}
// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
// s must start with a full and valid UTF-8 encoded rune.
func (t *randTrie) lookupUnsafe(s []byte) uint8 {
c0 := s[0]
if c0 < 0x80 { // is ASCII
return randValues[c0]
}
i := randIndex[c0]
if c0 < 0xE0 { // 2-byte UTF-8
return t.lookupValue(uint32(i), s[1])
}
i = randIndex[uint32(i)<<6+uint32(s[1])]
if c0 < 0xF0 { // 3-byte UTF-8
return t.lookupValue(uint32(i), s[2])
}
i = randIndex[uint32(i)<<6+uint32(s[2])]
if c0 < 0xF8 { // 4-byte UTF-8
return t.lookupValue(uint32(i), s[3])
}
return 0
}
// lookupString returns the trie value for the first UTF-8 encoding in s and
// the width in bytes of this encoding. The size will be 0 if s does not
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
func (t *randTrie) lookupString(s string) (v uint8, sz int) {
c0 := s[0]
switch {
case c0 < 0x80: // is ASCII
return randValues[c0], 1
case c0 < 0xC2:
return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
case c0 < 0xE0: // 2-byte UTF-8
if len(s) < 2 {
return 0, 0
}
i := randIndex[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c1), 2
case c0 < 0xF0: // 3-byte UTF-8
if len(s) < 3 {
return 0, 0
}
i := randIndex[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = randIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c2), 3
case c0 < 0xF8: // 4-byte UTF-8
if len(s) < 4 {
return 0, 0
}
i := randIndex[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = randIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
o = uint32(i)<<6 + uint32(c2)
i = randIndex[o]
c3 := s[3]
if c3 < 0x80 || 0xC0 <= c3 {
return 0, 3 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c3), 4
}
// Illegal rune
return 0, 1
}
// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
// s must start with a full and valid UTF-8 encoded rune.
func (t *randTrie) lookupStringUnsafe(s string) uint8 {
c0 := s[0]
if c0 < 0x80 { // is ASCII
return randValues[c0]
}
i := randIndex[c0]
if c0 < 0xE0 { // 2-byte UTF-8
return t.lookupValue(uint32(i), s[1])
}
i = randIndex[uint32(i)<<6+uint32(s[1])]
if c0 < 0xF0 { // 3-byte UTF-8
return t.lookupValue(uint32(i), s[2])
}
i = randIndex[uint32(i)<<6+uint32(s[2])]
if c0 < 0xF8 { // 4-byte UTF-8
return t.lookupValue(uint32(i), s[3])
}
return 0
}
// randTrie. Total size: 9280 bytes (9.06 KiB). Checksum: 6debd324a8debb8f.
type randTrie struct{}
func newRandTrie(i int) *randTrie {
return &randTrie{}
}
// lookupValue determines the type of block n and looks up the value for b.
func (t *randTrie) lookupValue(n uint32, b byte) uint8 {
switch {
default:
return uint8(randValues[n<<6+uint32(b)])
}
}
// randValues: 56 blocks, 3584 entries, 3584 bytes
// The third block is the zero block.
var randValues = [3584]uint8{
// Block 0x0, offset 0x0
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
0xc9: 0x0001,
// Block 0x4, offset 0x100
0x100: 0x0001,
// Block 0x5, offset 0x140
0x155: 0x0001,
// Block 0x6, offset 0x180
0x196: 0x0001,
// Block 0x7, offset 0x1c0
0x1ef: 0x0001,
// Block 0x8, offset 0x200
0x206: 0x0001,
// Block 0x9, offset 0x240
0x258: 0x0001,
// Block 0xa, offset 0x280
0x288: 0x0001,
// Block 0xb, offset 0x2c0
0x2f2: 0x0001,
// Block 0xc, offset 0x300
0x304: 0x0001,
// Block 0xd, offset 0x340
0x34b: 0x0001,
// Block 0xe, offset 0x380
0x3ba: 0x0001,
// Block 0xf, offset 0x3c0
0x3f5: 0x0001,
// Block 0x10, offset 0x400
0x41d: 0x0001,
// Block 0x11, offset 0x440
0x442: 0x0001,
// Block 0x12, offset 0x480
0x4bb: 0x0001,
// Block 0x13, offset 0x4c0
0x4e9: 0x0001,
// Block 0x14, offset 0x500
0x53e: 0x0001,
// Block 0x15, offset 0x540
0x55f: 0x0001,
// Block 0x16, offset 0x580
0x5b7: 0x0001,
// Block 0x17, offset 0x5c0
0x5d9: 0x0001,
// Block 0x18, offset 0x600
0x60e: 0x0001,
// Block 0x19, offset 0x640
0x652: 0x0001,
// Block 0x1a, offset 0x680
0x68f: 0x0001,
// Block 0x1b, offset 0x6c0
0x6dc: 0x0001,
// Block 0x1c, offset 0x700
0x703: 0x0001,
// Block 0x1d, offset 0x740
0x741: 0x0001,
// Block 0x1e, offset 0x780
0x79b: 0x0001,
// Block 0x1f, offset 0x7c0
0x7f1: 0x0001,
// Block 0x20, offset 0x800
0x833: 0x0001,
// Block 0x21, offset 0x840
0x853: 0x0001,
// Block 0x22, offset 0x880
0x8a2: 0x0001,
// Block 0x23, offset 0x8c0
0x8f8: 0x0001,
// Block 0x24, offset 0x900
0x917: 0x0001,
// Block 0x25, offset 0x940
0x945: 0x0001,
// Block 0x26, offset 0x980
0x99e: 0x0001,
// Block 0x27, offset 0x9c0
0x9fd: 0x0001,
// Block 0x28, offset 0xa00
0xa0d: 0x0001,
// Block 0x29, offset 0xa40
0xa66: 0x0001,
// Block 0x2a, offset 0xa80
0xaab: 0x0001,
// Block 0x2b, offset 0xac0
0xaea: 0x0001,
// Block 0x2c, offset 0xb00
0xb2d: 0x0001,
// Block 0x2d, offset 0xb40
0xb54: 0x0001,
// Block 0x2e, offset 0xb80
0xb90: 0x0001,
// Block 0x2f, offset 0xbc0
0xbe5: 0x0001,
// Block 0x30, offset 0xc00
0xc28: 0x0001,
// Block 0x31, offset 0xc40
0xc7c: 0x0001,
// Block 0x32, offset 0xc80
0xcbf: 0x0001,
// Block 0x33, offset 0xcc0
0xcc7: 0x0001,
// Block 0x34, offset 0xd00
0xd34: 0x0001,
// Block 0x35, offset 0xd40
0xd61: 0x0001,
// Block 0x36, offset 0xd80
0xdb9: 0x0001,
// Block 0x37, offset 0xdc0
0xdda: 0x0001,
}
// randIndex: 89 blocks, 5696 entries, 5696 bytes
// Block 0 is the zero block.
var randIndex = [5696]uint8{
// Block 0x0, offset 0x0
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
0xe1: 0x02, 0xe3: 0x03, 0xe4: 0x04,
0xea: 0x05, 0xeb: 0x06, 0xec: 0x07,
0xf0: 0x10, 0xf1: 0x24, 0xf2: 0x3d, 0xf3: 0x4f, 0xf4: 0x56,
// Block 0x4, offset 0x100
0x107: 0x01,
// Block 0x5, offset 0x140
0x16c: 0x02,
// Block 0x6, offset 0x180
0x19c: 0x03,
0x1ae: 0x04,
// Block 0x7, offset 0x1c0
0x1d8: 0x05,
0x1f7: 0x06,
// Block 0x8, offset 0x200
0x20c: 0x07,
// Block 0x9, offset 0x240
0x24a: 0x08,
// Block 0xa, offset 0x280
0x2b6: 0x09,
// Block 0xb, offset 0x2c0
0x2d5: 0x0a,
// Block 0xc, offset 0x300
0x31a: 0x0b,
// Block 0xd, offset 0x340
0x373: 0x0c,
// Block 0xe, offset 0x380
0x38b: 0x0d,
// Block 0xf, offset 0x3c0
0x3f0: 0x0e,
// Block 0x10, offset 0x400
0x433: 0x0f,
// Block 0x11, offset 0x440
0x45d: 0x10,
// Block 0x12, offset 0x480
0x491: 0x08, 0x494: 0x09, 0x497: 0x0a,
0x49b: 0x0b, 0x49c: 0x0c,
0x4a1: 0x0d,
0x4ad: 0x0e,
0x4ba: 0x0f,
// Block 0x13, offset 0x4c0
0x4c1: 0x11,
// Block 0x14, offset 0x500
0x531: 0x12,
// Block 0x15, offset 0x540
0x546: 0x13,
// Block 0x16, offset 0x580
0x5ab: 0x14,
// Block 0x17, offset 0x5c0
0x5d4: 0x11,
0x5fe: 0x11,
// Block 0x18, offset 0x600
0x618: 0x0a,
// Block 0x19, offset 0x640
0x65b: 0x15,
// Block 0x1a, offset 0x680
0x6a0: 0x16,
// Block 0x1b, offset 0x6c0
0x6d2: 0x17,
0x6f6: 0x18,
// Block 0x1c, offset 0x700
0x711: 0x19,
// Block 0x1d, offset 0x740
0x768: 0x1a,
// Block 0x1e, offset 0x780
0x783: 0x1b,
// Block 0x1f, offset 0x7c0
0x7f9: 0x1c,
// Block 0x20, offset 0x800
0x831: 0x1d,
// Block 0x21, offset 0x840
0x85e: 0x1e,
// Block 0x22, offset 0x880
0x898: 0x1f,
// Block 0x23, offset 0x8c0
0x8c7: 0x18,
0x8d5: 0x14,
0x8f7: 0x20,
0x8fe: 0x1f,
// Block 0x24, offset 0x900
0x905: 0x21,
// Block 0x25, offset 0x940
0x966: 0x03,
// Block 0x26, offset 0x980
0x981: 0x07, 0x983: 0x11,
0x989: 0x12, 0x98a: 0x13, 0x98e: 0x14, 0x98f: 0x15,
0x992: 0x16, 0x995: 0x17, 0x996: 0x18,
0x998: 0x19, 0x999: 0x1a, 0x99b: 0x1b, 0x99f: 0x1c,
0x9a3: 0x1d,
0x9ad: 0x1e, 0x9af: 0x1f,
0x9b0: 0x20, 0x9b1: 0x21,
0x9b8: 0x22, 0x9bd: 0x23,
// Block 0x27, offset 0x9c0
0x9cd: 0x22,
// Block 0x28, offset 0xa00
0xa0c: 0x08,
// Block 0x29, offset 0xa40
0xa6f: 0x1c,
// Block 0x2a, offset 0xa80
0xa90: 0x1a,
0xaaf: 0x23,
// Block 0x2b, offset 0xac0
0xae3: 0x19,
0xae8: 0x24,
0xafc: 0x25,
// Block 0x2c, offset 0xb00
0xb13: 0x26,
// Block 0x2d, offset 0xb40
0xb67: 0x1c,
// Block 0x2e, offset 0xb80
0xb8f: 0x0b,
// Block 0x2f, offset 0xbc0
0xbcb: 0x27,
0xbe7: 0x26,
// Block 0x30, offset 0xc00
0xc34: 0x16,
// Block 0x31, offset 0xc40
0xc62: 0x03,
// Block 0x32, offset 0xc80
0xcbb: 0x12,
// Block 0x33, offset 0xcc0
0xcdf: 0x09,
// Block 0x34, offset 0xd00
0xd34: 0x0a,
// Block 0x35, offset 0xd40
0xd41: 0x1e,
// Block 0x36, offset 0xd80
0xd83: 0x28,
// Block 0x37, offset 0xdc0
0xdc0: 0x15,
// Block 0x38, offset 0xe00
0xe1a: 0x15,
// Block 0x39, offset 0xe40
0xe65: 0x29,
// Block 0x3a, offset 0xe80
0xe86: 0x1f,
// Block 0x3b, offset 0xec0
0xeec: 0x18,
// Block 0x3c, offset 0xf00
0xf28: 0x2a,
// Block 0x3d, offset 0xf40
0xf53: 0x08,
// Block 0x3e, offset 0xf80
0xfa2: 0x2b,
0xfaa: 0x17,
// Block 0x3f, offset 0xfc0
0xfc0: 0x25, 0xfc2: 0x26,
0xfc9: 0x27, 0xfcd: 0x28, 0xfce: 0x29,
0xfd5: 0x2a,
0xfd8: 0x2b, 0xfd9: 0x2c, 0xfdf: 0x2d,
0xfe1: 0x2e, 0xfe2: 0x2f, 0xfe3: 0x30, 0xfe6: 0x31,
0xfe9: 0x32, 0xfec: 0x33, 0xfed: 0x34, 0xfef: 0x35,
0xff1: 0x36, 0xff2: 0x37, 0xff3: 0x38, 0xff4: 0x39,
0xffa: 0x3a, 0xffc: 0x3b, 0xffe: 0x3c,
// Block 0x40, offset 0x1000
0x102c: 0x2c,
// Block 0x41, offset 0x1040
0x1074: 0x2c,
// Block 0x42, offset 0x1080
0x108c: 0x08,
0x10a0: 0x2d,
// Block 0x43, offset 0x10c0
0x10e8: 0x10,
// Block 0x44, offset 0x1100
0x110f: 0x13,
// Block 0x45, offset 0x1140
0x114b: 0x2e,
// Block 0x46, offset 0x1180
0x118b: 0x23,
0x119d: 0x0c,
// Block 0x47, offset 0x11c0
0x11c3: 0x12,
0x11f9: 0x0f,
// Block 0x48, offset 0x1200
0x121e: 0x1b,
// Block 0x49, offset 0x1240
0x1270: 0x2f,
// Block 0x4a, offset 0x1280
0x128a: 0x1b,
0x12a7: 0x02,
// Block 0x4b, offset 0x12c0
0x12fb: 0x14,
// Block 0x4c, offset 0x1300
0x1333: 0x30,
// Block 0x4d, offset 0x1340
0x134d: 0x31,
// Block 0x4e, offset 0x1380
0x138e: 0x15,
// Block 0x4f, offset 0x13c0
0x13f4: 0x32,
// Block 0x50, offset 0x1400
0x141b: 0x33,
// Block 0x51, offset 0x1440
0x1448: 0x3e, 0x1449: 0x3f, 0x144a: 0x40, 0x144f: 0x41,
0x1459: 0x42, 0x145c: 0x43, 0x145e: 0x44, 0x145f: 0x45,
0x1468: 0x46, 0x1469: 0x47, 0x146c: 0x48, 0x146d: 0x49, 0x146e: 0x4a,
0x1472: 0x4b, 0x1473: 0x4c,
0x1479: 0x4d, 0x147b: 0x4e,
// Block 0x52, offset 0x1480
0x1480: 0x34,
0x1499: 0x11,
0x14b6: 0x2c,
// Block 0x53, offset 0x14c0
0x14e4: 0x0d,
// Block 0x54, offset 0x1500
0x1527: 0x08,
// Block 0x55, offset 0x1540
0x1555: 0x2b,
// Block 0x56, offset 0x1580
0x15b2: 0x35,
// Block 0x57, offset 0x15c0
0x15f2: 0x1c, 0x15f4: 0x29,
// Block 0x58, offset 0x1600
0x1600: 0x50, 0x1603: 0x51,
0x1608: 0x52, 0x160a: 0x53, 0x160d: 0x54, 0x160e: 0x55,
}
// lookup returns the trie value for the first UTF-8 encoding in s and
// the width in bytes of this encoding. The size will be 0 if s does not
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
func (t *multiTrie) lookup(s []byte) (v uint64, sz int) {
c0 := s[0]
switch {
case c0 < 0x80: // is ASCII
return t.ascii[c0], 1
case c0 < 0xC2:
return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
case c0 < 0xE0: // 2-byte UTF-8
if len(s) < 2 {
return 0, 0
}
i := t.utf8Start[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c1), 2
case c0 < 0xF0: // 3-byte UTF-8
if len(s) < 3 {
return 0, 0
}
i := t.utf8Start[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = multiIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c2), 3
case c0 < 0xF8: // 4-byte UTF-8
if len(s) < 4 {
return 0, 0
}
i := t.utf8Start[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = multiIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
o = uint32(i)<<6 + uint32(c2)
i = multiIndex[o]
c3 := s[3]
if c3 < 0x80 || 0xC0 <= c3 {
return 0, 3 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c3), 4
}
// Illegal rune
return 0, 1
}
// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
// s must start with a full and valid UTF-8 encoded rune.
func (t *multiTrie) lookupUnsafe(s []byte) uint64 {
c0 := s[0]
if c0 < 0x80 { // is ASCII
return t.ascii[c0]
}
i := t.utf8Start[c0]
if c0 < 0xE0 { // 2-byte UTF-8
return t.lookupValue(uint32(i), s[1])
}
i = multiIndex[uint32(i)<<6+uint32(s[1])]
if c0 < 0xF0 { // 3-byte UTF-8
return t.lookupValue(uint32(i), s[2])
}
i = multiIndex[uint32(i)<<6+uint32(s[2])]
if c0 < 0xF8 { // 4-byte UTF-8
return t.lookupValue(uint32(i), s[3])
}
return 0
}
// lookupString returns the trie value for the first UTF-8 encoding in s and
// the width in bytes of this encoding. The size will be 0 if s does not
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
func (t *multiTrie) lookupString(s string) (v uint64, sz int) {
c0 := s[0]
switch {
case c0 < 0x80: // is ASCII
return t.ascii[c0], 1
case c0 < 0xC2:
return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
case c0 < 0xE0: // 2-byte UTF-8
if len(s) < 2 {
return 0, 0
}
i := t.utf8Start[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c1), 2
case c0 < 0xF0: // 3-byte UTF-8
if len(s) < 3 {
return 0, 0
}
i := t.utf8Start[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = multiIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c2), 3
case c0 < 0xF8: // 4-byte UTF-8
if len(s) < 4 {
return 0, 0
}
i := t.utf8Start[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = multiIndex[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
o = uint32(i)<<6 + uint32(c2)
i = multiIndex[o]
c3 := s[3]
if c3 < 0x80 || 0xC0 <= c3 {
return 0, 3 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c3), 4
}
// Illegal rune
return 0, 1
}
// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
// s must start with a full and valid UTF-8 encoded rune.
func (t *multiTrie) lookupStringUnsafe(s string) uint64 {
c0 := s[0]
if c0 < 0x80 { // is ASCII
return t.ascii[c0]
}
i := t.utf8Start[c0]
if c0 < 0xE0 { // 2-byte UTF-8
return t.lookupValue(uint32(i), s[1])
}
i = multiIndex[uint32(i)<<6+uint32(s[1])]
if c0 < 0xF0 { // 3-byte UTF-8
return t.lookupValue(uint32(i), s[2])
}
i = multiIndex[uint32(i)<<6+uint32(s[2])]
if c0 < 0xF8 { // 4-byte UTF-8
return t.lookupValue(uint32(i), s[3])
}
return 0
}
// multiTrie. Total size: 18250 bytes (17.82 KiB). Checksum: a69a609d8696aa5e.
type multiTrie struct {
ascii []uint64 // index for ASCII bytes
utf8Start []uint8 // index for UTF-8 bytes >= 0xC0
}
func newMultiTrie(i int) *multiTrie {
h := multiTrieHandles[i]
return &multiTrie{multiValues[uint32(h.ascii)<<6:], multiIndex[uint32(h.multi)<<6:]}
}
type multiTrieHandle struct {
ascii, multi uint8
}
// multiTrieHandles: 5 handles, 10 bytes
var multiTrieHandles = [5]multiTrieHandle{
{0, 0}, // 8c1e77823143d35c: all
{0, 23}, // 8fb58ff8243b45b0: ASCII only
{0, 23}, // 8fb58ff8243b45b0: ASCII only 2
{0, 24}, // 2ccc43994f11046f: BMP only
{30, 25}, // ce448591bdcb4733: No BMP
}
// lookupValue determines the type of block n and looks up the value for b.
func (t *multiTrie) lookupValue(n uint32, b byte) uint64 {
switch {
default:
return uint64(multiValues[n<<6+uint32(b)])
}
}
// multiValues: 32 blocks, 2048 entries, 16384 bytes
// The third block is the zero block.
var multiValues = [2048]uint64{
// Block 0x0, offset 0x0
0x03: 0x6e361699800b9fb8, 0x04: 0x52d3935a34f6f0b, 0x05: 0x2948319393e7ef10,
0x07: 0x20f03b006704f663, 0x08: 0x6c15c0732bb2495f, 0x09: 0xe54e2c59d953551,
0x0f: 0x33d8a825807d8037, 0x10: 0x6ecd93cb12168b92, 0x11: 0x6a81c9c0ce86e884,
0x1f: 0xa03e77aac8be79b, 0x20: 0x28591d0e7e486efa, 0x21: 0x716fa3bc398dec8,
0x3f: 0x4fd3bcfa72bce8b0,
// Block 0x1, offset 0x40
0x40: 0x3cbaef3db8ba5f12, 0x41: 0x2d262347c1f56357,
0x7f: 0x782caa2d25a418a9,
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
0xc0: 0x6bbd1f937b1ff5d2, 0xc1: 0x732e23088d2eb8a4,
// Block 0x4, offset 0x100
0x13f: 0x56f8c4c82f5962dc,
// Block 0x5, offset 0x140
0x140: 0x57dc4544729a5da2, 0x141: 0x2f62f9cd307ffa0d,
// Block 0x6, offset 0x180
0x1bf: 0x7bf4d0ebf302a088,
// Block 0x7, offset 0x1c0
0x1c0: 0x1f0d67f249e59931, 0x1c1: 0x3011def73aa550c7,
// Block 0x8, offset 0x200
0x23f: 0x5de81c1dff6bf29d,
// Block 0x9, offset 0x240
0x240: 0x752c035737b825e8, 0x241: 0x1e793399081e3bb3,
// Block 0xa, offset 0x280
0x2bf: 0x6a28f01979cbf059,
// Block 0xb, offset 0x2c0
0x2c0: 0x373a4b0f2cbd4c74, 0x2c1: 0x4fd2c288683b767c,
// Block 0xc, offset 0x300
0x33f: 0x5a10ffa9e29184fb,
// Block 0xd, offset 0x340
0x340: 0x700f9bdb53fff6a5, 0x341: 0xcde93df0427eb79,
// Block 0xe, offset 0x380
0x3bf: 0x74071288fff39c76,
// Block 0xf, offset 0x3c0
0x3c0: 0x481fc2f510e5268a, 0x3c1: 0x7565c28164204849,
// Block 0x10, offset 0x400
0x43f: 0x5676a62fd49c6bec,
// Block 0x11, offset 0x440
0x440: 0x2f2d15776cbafc6b, 0x441: 0x4c55e8dc0ff11a3f,
// Block 0x12, offset 0x480
0x4bf: 0x69d6f0fe711fafc9,
// Block 0x13, offset 0x4c0
0x4c0: 0x33181de28cfb062d, 0x4c1: 0x2ef3adc6bb2f2d02,
// Block 0x14, offset 0x500
0x53f: 0xe03b31814c95f8b,
// Block 0x15, offset 0x540
0x540: 0x3bf6dc9a1c115603, 0x541: 0x6984ec9b7f51f7fc,
// Block 0x16, offset 0x580
0x5bf: 0x3c02ea92fb168559,
// Block 0x17, offset 0x5c0
0x5c0: 0x1badfe42e7629494, 0x5c1: 0x6dc4a554005f7645,
// Block 0x18, offset 0x600
0x63f: 0x3bb2ed2a72748f4b,
// Block 0x19, offset 0x640
0x640: 0x291354cd6767ec10, 0x641: 0x2c3a4715e3c070d6,
// Block 0x1a, offset 0x680
0x6bf: 0x352711cfb7236418,
// Block 0x1b, offset 0x6c0
0x6c0: 0x3a59d34fb8bceda, 0x6c1: 0x5e90d8ebedd64fa1,
// Block 0x1c, offset 0x700
0x73f: 0x7191a77b28d23110,
// Block 0x1d, offset 0x740
0x740: 0x4ca7f0c1623423d8, 0x741: 0x4f7156d996e2d0de,
// Block 0x1e, offset 0x780
// Block 0x1f, offset 0x7c0
}
// multiIndex: 29 blocks, 1856 entries, 1856 bytes
// Block 0 is the zero block.
var multiIndex = [1856]uint8{
// Block 0x0, offset 0x0
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
0xc2: 0x01, 0xc3: 0x02, 0xc4: 0x03, 0xc7: 0x04,
0xc8: 0x05, 0xcf: 0x06,
0xd0: 0x07,
0xdf: 0x08,
0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe7: 0x07,
0xe8: 0x08, 0xef: 0x09,
0xf0: 0x0e, 0xf1: 0x11, 0xf2: 0x13, 0xf3: 0x15, 0xf4: 0x17,
// Block 0x4, offset 0x100
0x120: 0x09,
0x13f: 0x0a,
// Block 0x5, offset 0x140
0x140: 0x0b,
0x17f: 0x0c,
// Block 0x6, offset 0x180
0x180: 0x0d,
// Block 0x7, offset 0x1c0
0x1ff: 0x0e,
// Block 0x8, offset 0x200
0x200: 0x0f,
// Block 0x9, offset 0x240
0x27f: 0x10,
// Block 0xa, offset 0x280
0x280: 0x11,
// Block 0xb, offset 0x2c0
0x2ff: 0x12,
// Block 0xc, offset 0x300
0x300: 0x13,
// Block 0xd, offset 0x340
0x37f: 0x14,
// Block 0xe, offset 0x380
0x380: 0x15,
// Block 0xf, offset 0x3c0
0x3ff: 0x16,
// Block 0x10, offset 0x400
0x410: 0x0a,
0x41f: 0x0b,
0x420: 0x0c,
0x43f: 0x0d,
// Block 0x11, offset 0x440
0x440: 0x17,
// Block 0x12, offset 0x480
0x4bf: 0x18,
// Block 0x13, offset 0x4c0
0x4c0: 0x0f,
0x4ff: 0x10,
// Block 0x14, offset 0x500
0x500: 0x19,
// Block 0x15, offset 0x540
0x540: 0x12,
// Block 0x16, offset 0x580
0x5bf: 0x1a,
// Block 0x17, offset 0x5c0
0x5ff: 0x14,
// Block 0x18, offset 0x600
0x600: 0x1b,
// Block 0x19, offset 0x640
0x640: 0x16,
// Block 0x1a, offset 0x680
// Block 0x1b, offset 0x6c0
0x6c2: 0x01, 0x6c3: 0x02, 0x6c4: 0x03, 0x6c7: 0x04,
0x6c8: 0x05, 0x6cf: 0x06,
0x6d0: 0x07,
0x6df: 0x08,
0x6e0: 0x02, 0x6e1: 0x03, 0x6e2: 0x04, 0x6e3: 0x05, 0x6e4: 0x06, 0x6e7: 0x07,
0x6e8: 0x08, 0x6ef: 0x09,
// Block 0x1c, offset 0x700
0x730: 0x0e, 0x731: 0x11, 0x732: 0x13, 0x733: 0x15, 0x734: 0x17,
}

View file

@ -0,0 +1,71 @@
// Copyright 2014 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 triegen_test
import (
"fmt"
"io"
"io/ioutil"
"golang.org/x/text/internal/triegen"
)
func ExampleCompacter() {
t := triegen.NewTrie("root")
for r := rune(0); r < 10000; r += 64 {
t.Insert(r, 0x9015BADA55^uint64(r))
}
sz, _ := t.Gen(ioutil.Discard)
fmt.Printf("Size normal: %5d\n", sz)
var c myCompacter
sz, _ = t.Gen(ioutil.Discard, triegen.Compact(&c))
fmt.Printf("Size compacted: %5d\n", sz)
// Output:
// Size normal: 81344
// Size compacted: 3224
}
// A myCompacter accepts a block if only the first value is given.
type myCompacter []uint64
func (c *myCompacter) Size(values []uint64) (sz int, ok bool) {
for _, v := range values[1:] {
if v != 0 {
return 0, false
}
}
return 8, true // the size of a uint64
}
func (c *myCompacter) Store(v []uint64) uint32 {
x := uint32(len(*c))
*c = append(*c, v[0])
return x
}
func (c *myCompacter) Print(w io.Writer) error {
fmt.Fprintln(w, "var firstValue = []uint64{")
for _, v := range *c {
fmt.Fprintf(w, "\t%#x,\n", v)
}
fmt.Fprintln(w, "}")
return nil
}
func (c *myCompacter) Handler() string {
return "getFirstValue"
// Where getFirstValue is included along with the generated code:
// func getFirstValue(n uint32, b byte) uint64 {
// if b == 0x80 { // the first continuation byte
// return firstValue[n]
// }
// return 0
// }
}

View file

@ -0,0 +1,148 @@
// Copyright 2014 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 triegen_test
import (
"fmt"
"io/ioutil"
"math/rand"
"unicode"
"golang.org/x/text/internal/triegen"
)
const seed = 0x12345
var genWriter = ioutil.Discard
func randomRunes() map[rune]uint8 {
rnd := rand.New(rand.NewSource(seed))
m := map[rune]uint8{}
for len(m) < 100 {
// Only set our random rune if it is a valid Unicode code point.
if r := rune(rnd.Int31n(unicode.MaxRune + 1)); []rune(string(r))[0] == r {
m[r] = 1
}
}
return m
}
// Example_build shows how to build a simple trie. It assigns the value 1 to
// 100 random runes generated by randomRunes.
func Example_build() {
t := triegen.NewTrie("rand")
for r, _ := range randomRunes() {
t.Insert(r, 1)
}
sz, err := t.Gen(genWriter)
fmt.Printf("Trie size: %d bytes\n", sz)
fmt.Printf("Error: %v\n", err)
// Output:
// Trie size: 9280 bytes
// Error: <nil>
}
// Example_lookup demonstrates how to use the trie generated by Example_build.
func Example_lookup() {
trie := newRandTrie(0)
// The same set of runes used by Example_build.
runes := randomRunes()
// Verify the right value is returned for all runes.
for r := rune(0); r <= unicode.MaxRune; r++ {
// Note that the return type of lookup is uint8.
if v, _ := trie.lookupString(string(r)); v != runes[r] {
fmt.Println("FAILURE")
return
}
}
fmt.Println("SUCCESS")
// Output:
// SUCCESS
}
// runeValues generates some random values for a set of interesting runes.
func runeValues() map[rune]uint64 {
rnd := rand.New(rand.NewSource(seed))
m := map[rune]uint64{}
for p := 4; p <= unicode.MaxRune; p <<= 1 {
for d := -1; d <= 1; d++ {
m[rune(p+d)] = uint64(rnd.Int63())
}
}
return m
}
// ExampleGen_build demonstrates the creation of multiple tries sharing common
// blocks. ExampleGen_lookup demonstrates how to use the generated tries.
func ExampleGen_build() {
var tries []*triegen.Trie
rv := runeValues()
for _, c := range []struct {
include func(rune) bool
name string
}{
{func(r rune) bool { return true }, "all"},
{func(r rune) bool { return r < 0x80 }, "ASCII only"},
{func(r rune) bool { return r < 0x80 }, "ASCII only 2"},
{func(r rune) bool { return r <= 0xFFFF }, "BMP only"},
{func(r rune) bool { return r > 0xFFFF }, "No BMP"},
} {
t := triegen.NewTrie(c.name)
tries = append(tries, t)
for r, v := range rv {
if c.include(r) {
t.Insert(r, v)
}
}
}
sz, err := triegen.Gen(genWriter, "multi", tries)
fmt.Printf("Trie size: %d bytes\n", sz)
fmt.Printf("Error: %v\n", err)
// Output:
// Trie size: 18250 bytes
// Error: <nil>
}
// ExampleGen_lookup shows how to look up values in the trie generated by
// ExampleGen_build.
func ExampleGen_lookup() {
rv := runeValues()
for i, include := range []func(rune) bool{
func(r rune) bool { return true }, // all
func(r rune) bool { return r < 0x80 }, // ASCII only
func(r rune) bool { return r < 0x80 }, // ASCII only 2
func(r rune) bool { return r <= 0xFFFF }, // BMP only
func(r rune) bool { return r > 0xFFFF }, // No BMP
} {
t := newMultiTrie(i)
for r := rune(0); r <= unicode.MaxRune; r++ {
x := uint64(0)
if include(r) {
x = rv[r]
}
// As we convert from a valid rune, we know it is safe to use
// lookupStringUnsafe.
if v := t.lookupStringUnsafe(string(r)); x != v {
fmt.Println("FAILURE")
return
}
}
}
fmt.Println("SUCCESS")
// Output:
// SUCCESS
}

68
vendor/golang.org/x/text/internal/triegen/gen_test.go generated vendored Normal file
View file

@ -0,0 +1,68 @@
// Copyright 2014 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 generate
package triegen_test
// The code in this file generates captures and writes the tries generated in
// the examples to data_test.go. To invoke it, run:
// go test -tags=generate
//
// Making the generation code a "test" allows us to link in the necessary test
// code.
import (
"log"
"os"
"os/exec"
)
func init() {
const tmpfile = "tmpout"
const dstfile = "data_test.go"
f, err := os.Create(tmpfile)
if err != nil {
log.Fatalf("Could not create output file: %v", err)
}
defer os.Remove(tmpfile)
defer f.Close()
// We exit before this function returns, regardless of success or failure,
// so there's no need to save (and later restore) the existing genWriter
// value.
genWriter = f
f.Write([]byte(header))
Example_build()
ExampleGen_build()
if err := exec.Command("gofmt", "-w", tmpfile).Run(); err != nil {
log.Fatal(err)
}
os.Remove(dstfile)
os.Rename(tmpfile, dstfile)
os.Exit(0)
}
const header = `// This file is generated with "go test -tags generate". DO NOT EDIT!
// +build !generate
package triegen_test
`
// Stubs for generated tries. These are needed as we exclude data_test.go if
// the generate flag is set. This will clearly make the tests fail, but that
// is okay. It allows us to bootstrap.
type trie struct{}
func (t *trie) lookupString(string) (uint8, int) { return 0, 1 }
func (t *trie) lookupStringUnsafe(string) uint64 { return 0 }
func newRandTrie(i int) *trie { return &trie{} }
func newMultiTrie(i int) *trie { return &trie{} }

251
vendor/golang.org/x/text/internal/triegen/print.go generated vendored Normal file
View file

@ -0,0 +1,251 @@
// Copyright 2014 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 triegen
import (
"bytes"
"fmt"
"io"
"strings"
"text/template"
)
// print writes all the data structures as well as the code necessary to use the
// trie to w.
func (b *builder) print(w io.Writer) error {
b.Stats.NValueEntries = len(b.ValueBlocks) * blockSize
b.Stats.NValueBytes = len(b.ValueBlocks) * blockSize * b.ValueSize
b.Stats.NIndexEntries = len(b.IndexBlocks) * blockSize
b.Stats.NIndexBytes = len(b.IndexBlocks) * blockSize * b.IndexSize
b.Stats.NHandleBytes = len(b.Trie) * 2 * b.IndexSize
// If we only have one root trie, all starter blocks are at position 0 and
// we can access the arrays directly.
if len(b.Trie) == 1 {
// At this point we cannot refer to the generated tables directly.
b.ASCIIBlock = b.Name + "Values"
b.StarterBlock = b.Name + "Index"
} else {
// Otherwise we need to have explicit starter indexes in the trie
// structure.
b.ASCIIBlock = "t.ascii"
b.StarterBlock = "t.utf8Start"
}
b.SourceType = "[]byte"
if err := lookupGen.Execute(w, b); err != nil {
return err
}
b.SourceType = "string"
if err := lookupGen.Execute(w, b); err != nil {
return err
}
if err := trieGen.Execute(w, b); err != nil {
return err
}
for _, c := range b.Compactions {
if err := c.c.Print(w); err != nil {
return err
}
}
return nil
}
func printValues(n int, values []uint64) string {
w := &bytes.Buffer{}
boff := n * blockSize
fmt.Fprintf(w, "\t// Block %#x, offset %#x", n, boff)
var newline bool
for i, v := range values {
if i%6 == 0 {
newline = true
}
if v != 0 {
if newline {
fmt.Fprintf(w, "\n")
newline = false
}
fmt.Fprintf(w, "\t%#02x:%#04x, ", boff+i, v)
}
}
return w.String()
}
func printIndex(b *builder, nr int, n *node) string {
w := &bytes.Buffer{}
boff := nr * blockSize
fmt.Fprintf(w, "\t// Block %#x, offset %#x", nr, boff)
var newline bool
for i, c := range n.children {
if i%8 == 0 {
newline = true
}
if c != nil {
v := b.Compactions[c.index.compaction].Offset + uint32(c.index.index)
if v != 0 {
if newline {
fmt.Fprintf(w, "\n")
newline = false
}
fmt.Fprintf(w, "\t%#02x:%#02x, ", boff+i, v)
}
}
}
return w.String()
}
var (
trieGen = template.Must(template.New("trie").Funcs(template.FuncMap{
"printValues": printValues,
"printIndex": printIndex,
"title": strings.Title,
"dec": func(x int) int { return x - 1 },
"psize": func(n int) string {
return fmt.Sprintf("%d bytes (%.2f KiB)", n, float64(n)/1024)
},
}).Parse(trieTemplate))
lookupGen = template.Must(template.New("lookup").Parse(lookupTemplate))
)
// TODO: consider the return type of lookup. It could be uint64, even if the
// internal value type is smaller. We will have to verify this with the
// performance of unicode/norm, which is very sensitive to such changes.
const trieTemplate = `{{$b := .}}{{$multi := gt (len .Trie) 1}}
// {{.Name}}Trie. Total size: {{psize .Size}}. Checksum: {{printf "%08x" .Checksum}}.
type {{.Name}}Trie struct { {{if $multi}}
ascii []{{.ValueType}} // index for ASCII bytes
utf8Start []{{.IndexType}} // index for UTF-8 bytes >= 0xC0
{{end}}}
func new{{title .Name}}Trie(i int) *{{.Name}}Trie { {{if $multi}}
h := {{.Name}}TrieHandles[i]
return &{{.Name}}Trie{ {{.Name}}Values[uint32(h.ascii)<<6:], {{.Name}}Index[uint32(h.multi)<<6:] }
}
type {{.Name}}TrieHandle struct {
ascii, multi {{.IndexType}}
}
// {{.Name}}TrieHandles: {{len .Trie}} handles, {{.Stats.NHandleBytes}} bytes
var {{.Name}}TrieHandles = [{{len .Trie}}]{{.Name}}TrieHandle{
{{range .Trie}} { {{.ASCIIIndex}}, {{.StarterIndex}} }, // {{printf "%08x" .Checksum}}: {{.Name}}
{{end}}}{{else}}
return &{{.Name}}Trie{}
}
{{end}}
// lookupValue determines the type of block n and looks up the value for b.
func (t *{{.Name}}Trie) lookupValue(n uint32, b byte) {{.ValueType}}{{$last := dec (len .Compactions)}} {
switch { {{range $i, $c := .Compactions}}
{{if eq $i $last}}default{{else}}case n < {{$c.Cutoff}}{{end}}:{{if ne $i 0}}
n -= {{$c.Offset}}{{end}}
return {{print $b.ValueType}}({{$c.Handler}}){{end}}
}
}
// {{.Name}}Values: {{len .ValueBlocks}} blocks, {{.Stats.NValueEntries}} entries, {{.Stats.NValueBytes}} bytes
// The third block is the zero block.
var {{.Name}}Values = [{{.Stats.NValueEntries}}]{{.ValueType}} {
{{range $i, $v := .ValueBlocks}}{{printValues $i $v}}
{{end}}}
// {{.Name}}Index: {{len .IndexBlocks}} blocks, {{.Stats.NIndexEntries}} entries, {{.Stats.NIndexBytes}} bytes
// Block 0 is the zero block.
var {{.Name}}Index = [{{.Stats.NIndexEntries}}]{{.IndexType}} {
{{range $i, $v := .IndexBlocks}}{{printIndex $b $i $v}}
{{end}}}
`
// TODO: consider allowing zero-length strings after evaluating performance with
// unicode/norm.
const lookupTemplate = `
// lookup{{if eq .SourceType "string"}}String{{end}} returns the trie value for the first UTF-8 encoding in s and
// the width in bytes of this encoding. The size will be 0 if s does not
// hold enough bytes to complete the encoding. len(s) must be greater than 0.
func (t *{{.Name}}Trie) lookup{{if eq .SourceType "string"}}String{{end}}(s {{.SourceType}}) (v {{.ValueType}}, sz int) {
c0 := s[0]
switch {
case c0 < 0x80: // is ASCII
return {{.ASCIIBlock}}[c0], 1
case c0 < 0xC2:
return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
case c0 < 0xE0: // 2-byte UTF-8
if len(s) < 2 {
return 0, 0
}
i := {{.StarterBlock}}[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c1), 2
case c0 < 0xF0: // 3-byte UTF-8
if len(s) < 3 {
return 0, 0
}
i := {{.StarterBlock}}[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = {{.Name}}Index[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c2), 3
case c0 < 0xF8: // 4-byte UTF-8
if len(s) < 4 {
return 0, 0
}
i := {{.StarterBlock}}[c0]
c1 := s[1]
if c1 < 0x80 || 0xC0 <= c1 {
return 0, 1 // Illegal UTF-8: not a continuation byte.
}
o := uint32(i)<<6 + uint32(c1)
i = {{.Name}}Index[o]
c2 := s[2]
if c2 < 0x80 || 0xC0 <= c2 {
return 0, 2 // Illegal UTF-8: not a continuation byte.
}
o = uint32(i)<<6 + uint32(c2)
i = {{.Name}}Index[o]
c3 := s[3]
if c3 < 0x80 || 0xC0 <= c3 {
return 0, 3 // Illegal UTF-8: not a continuation byte.
}
return t.lookupValue(uint32(i), c3), 4
}
// Illegal rune
return 0, 1
}
// lookup{{if eq .SourceType "string"}}String{{end}}Unsafe returns the trie value for the first UTF-8 encoding in s.
// s must start with a full and valid UTF-8 encoded rune.
func (t *{{.Name}}Trie) lookup{{if eq .SourceType "string"}}String{{end}}Unsafe(s {{.SourceType}}) {{.ValueType}} {
c0 := s[0]
if c0 < 0x80 { // is ASCII
return {{.ASCIIBlock}}[c0]
}
i := {{.StarterBlock}}[c0]
if c0 < 0xE0 { // 2-byte UTF-8
return t.lookupValue(uint32(i), s[1])
}
i = {{.Name}}Index[uint32(i)<<6+uint32(s[1])]
if c0 < 0xF0 { // 3-byte UTF-8
return t.lookupValue(uint32(i), s[2])
}
i = {{.Name}}Index[uint32(i)<<6+uint32(s[2])]
if c0 < 0xF8 { // 4-byte UTF-8
return t.lookupValue(uint32(i), s[3])
}
return 0
}
`

494
vendor/golang.org/x/text/internal/triegen/triegen.go generated vendored Normal file
View file

@ -0,0 +1,494 @@
// Copyright 2014 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 triegen implements a code generator for a trie for associating
// unsigned integer values with UTF-8 encoded runes.
//
// Many of the go.text packages use tries for storing per-rune information. A
// trie is especially useful if many of the runes have the same value. If this
// is the case, many blocks can be expected to be shared allowing for
// information on many runes to be stored in little space.
//
// As most of the lookups are done directly on []byte slices, the tries use the
// UTF-8 bytes directly for the lookup. This saves a conversion from UTF-8 to
// runes and contributes a little bit to better performance. It also naturally
// provides a fast path for ASCII.
//
// Space is also an issue. There are many code points defined in Unicode and as
// a result tables can get quite large. So every byte counts. The triegen
// package automatically chooses the smallest integer values to represent the
// tables. Compacters allow further compression of the trie by allowing for
// alternative representations of individual trie blocks.
//
// triegen allows generating multiple tries as a single structure. This is
// useful when, for example, one wants to generate tries for several languages
// that have a lot of values in common. Some existing libraries for
// internationalization store all per-language data as a dynamically loadable
// chunk. The go.text packages are designed with the assumption that the user
// typically wants to compile in support for all supported languages, in line
// with the approach common to Go to create a single standalone binary. The
// multi-root trie approach can give significant storage savings in this
// scenario.
//
// triegen generates both tables and code. The code is optimized to use the
// automatically chosen data types. The following code is generated for a Trie
// or multiple Tries named "foo":
// - type fooTrie
// The trie type.
//
// - func newFooTrie(x int) *fooTrie
// Trie constructor, where x is the index of the trie passed to Gen.
//
// - func (t *fooTrie) lookup(s []byte) (v uintX, sz int)
// The lookup method, where uintX is automatically chosen.
//
// - func lookupString, lookupUnsafe and lookupStringUnsafe
// Variants of the above.
//
// - var fooValues and fooIndex and any tables generated by Compacters.
// The core trie data.
//
// - var fooTrieHandles
// Indexes of starter blocks in case of multiple trie roots.
//
// It is recommended that users test the generated trie by checking the returned
// value for every rune. Such exhaustive tests are possible as the the number of
// runes in Unicode is limited.
package triegen // import "golang.org/x/text/internal/triegen"
// TODO: Arguably, the internally optimized data types would not have to be
// exposed in the generated API. We could also investigate not generating the
// code, but using it through a package. We would have to investigate the impact
// on performance of making such change, though. For packages like unicode/norm,
// small changes like this could tank performance.
import (
"encoding/binary"
"fmt"
"hash/crc64"
"io"
"log"
"unicode/utf8"
)
// builder builds a set of tries for associating values with runes. The set of
// tries can share common index and value blocks.
type builder struct {
Name string
// ValueType is the type of the trie values looked up.
ValueType string
// ValueSize is the byte size of the ValueType.
ValueSize int
// IndexType is the type of trie index values used for all UTF-8 bytes of
// a rune except the last one.
IndexType string
// IndexSize is the byte size of the IndexType.
IndexSize int
// SourceType is used when generating the lookup functions. If the user
// requests StringSupport, all lookup functions will be generated for
// string input as well.
SourceType string
Trie []*Trie
IndexBlocks []*node
ValueBlocks [][]uint64
Compactions []compaction
Checksum uint64
ASCIIBlock string
StarterBlock string
indexBlockIdx map[uint64]int
valueBlockIdx map[uint64]nodeIndex
asciiBlockIdx map[uint64]int
// Stats are used to fill out the template.
Stats struct {
NValueEntries int
NValueBytes int
NIndexEntries int
NIndexBytes int
NHandleBytes int
}
err error
}
// A nodeIndex encodes the index of a node, which is defined by the compaction
// which stores it and an index within the compaction. For internal nodes, the
// compaction is always 0.
type nodeIndex struct {
compaction int
index int
}
// compaction keeps track of stats used for the compaction.
type compaction struct {
c Compacter
blocks []*node
maxHandle uint32
totalSize int
// Used by template-based generator and thus exported.
Cutoff uint32
Offset uint32
Handler string
}
func (b *builder) setError(err error) {
if b.err == nil {
b.err = err
}
}
// An Option can be passed to Gen.
type Option func(b *builder) error
// Compact configures the trie generator to use the given Compacter.
func Compact(c Compacter) Option {
return func(b *builder) error {
b.Compactions = append(b.Compactions, compaction{
c: c,
Handler: c.Handler() + "(n, b)"})
return nil
}
}
// Gen writes Go code for a shared trie lookup structure to w for the given
// Tries. The generated trie type will be called nameTrie. newNameTrie(x) will
// return the *nameTrie for tries[x]. A value can be looked up by using one of
// the various lookup methods defined on nameTrie. It returns the table size of
// the generated trie.
func Gen(w io.Writer, name string, tries []*Trie, opts ...Option) (sz int, err error) {
// The index contains two dummy blocks, followed by the zero block. The zero
// block is at offset 0x80, so that the offset for the zero block for
// continuation bytes is 0.
b := &builder{
Name: name,
Trie: tries,
IndexBlocks: []*node{{}, {}, {}},
Compactions: []compaction{{
Handler: name + "Values[n<<6+uint32(b)]",
}},
// The 0 key in indexBlockIdx and valueBlockIdx is the hash of the zero
// block.
indexBlockIdx: map[uint64]int{0: 0},
valueBlockIdx: map[uint64]nodeIndex{0: {}},
asciiBlockIdx: map[uint64]int{},
}
b.Compactions[0].c = (*simpleCompacter)(b)
for _, f := range opts {
if err := f(b); err != nil {
return 0, err
}
}
b.build()
if b.err != nil {
return 0, b.err
}
if err = b.print(w); err != nil {
return 0, err
}
return b.Size(), nil
}
// A Trie represents a single root node of a trie. A builder may build several
// overlapping tries at once.
type Trie struct {
root *node
hiddenTrie
}
// hiddenTrie contains values we want to be visible to the template generator,
// but hidden from the API documentation.
type hiddenTrie struct {
Name string
Checksum uint64
ASCIIIndex int
StarterIndex int
}
// NewTrie returns a new trie root.
func NewTrie(name string) *Trie {
return &Trie{
&node{
children: make([]*node, blockSize),
values: make([]uint64, utf8.RuneSelf),
},
hiddenTrie{Name: name},
}
}
// Gen is a convenience wrapper around the Gen func passing t as the only trie
// and uses the name passed to NewTrie. It returns the size of the generated
// tables.
func (t *Trie) Gen(w io.Writer, opts ...Option) (sz int, err error) {
return Gen(w, t.Name, []*Trie{t}, opts...)
}
// node is a node of the intermediate trie structure.
type node struct {
// children holds this node's children. It is always of length 64.
// A child node may be nil.
children []*node
// values contains the values of this node. If it is non-nil, this node is
// either a root or leaf node:
// For root nodes, len(values) == 128 and it maps the bytes in [0x00, 0x7F].
// For leaf nodes, len(values) == 64 and it maps the bytes in [0x80, 0xBF].
values []uint64
index nodeIndex
}
// Insert associates value with the given rune. Insert will panic if a non-zero
// value is passed for an invalid rune.
func (t *Trie) Insert(r rune, value uint64) {
if value == 0 {
return
}
s := string(r)
if []rune(s)[0] != r && value != 0 {
// Note: The UCD tables will always assign what amounts to a zero value
// to a surrogate. Allowing a zero value for an illegal rune allows
// users to iterate over [0..MaxRune] without having to explicitly
// exclude surrogates, which would be tedious.
panic(fmt.Sprintf("triegen: non-zero value for invalid rune %U", r))
}
if len(s) == 1 {
// It is a root node value (ASCII).
t.root.values[s[0]] = value
return
}
n := t.root
for ; len(s) > 1; s = s[1:] {
if n.children == nil {
n.children = make([]*node, blockSize)
}
p := s[0] % blockSize
c := n.children[p]
if c == nil {
c = &node{}
n.children[p] = c
}
if len(s) > 2 && c.values != nil {
log.Fatalf("triegen: insert(%U): found internal node with values", r)
}
n = c
}
if n.values == nil {
n.values = make([]uint64, blockSize)
}
if n.children != nil {
log.Fatalf("triegen: insert(%U): found leaf node that also has child nodes", r)
}
n.values[s[0]-0x80] = value
}
// Size returns the number of bytes the generated trie will take to store. It
// needs to be exported as it is used in the templates.
func (b *builder) Size() int {
// Index blocks.
sz := len(b.IndexBlocks) * blockSize * b.IndexSize
// Skip the first compaction, which represents the normal value blocks, as
// its totalSize does not account for the ASCII blocks, which are managed
// separately.
sz += len(b.ValueBlocks) * blockSize * b.ValueSize
for _, c := range b.Compactions[1:] {
sz += c.totalSize
}
// TODO: this computation does not account for the fixed overhead of a using
// a compaction, either code or data. As for data, though, the typical
// overhead of data is in the order of bytes (2 bytes for cases). Further,
// the savings of using a compaction should anyway be substantial for it to
// be worth it.
// For multi-root tries, we also need to account for the handles.
if len(b.Trie) > 1 {
sz += 2 * b.IndexSize * len(b.Trie)
}
return sz
}
func (b *builder) build() {
// Compute the sizes of the values.
var vmax uint64
for _, t := range b.Trie {
vmax = maxValue(t.root, vmax)
}
b.ValueType, b.ValueSize = getIntType(vmax)
// Compute all block allocations.
// TODO: first compute the ASCII blocks for all tries and then the other
// nodes. ASCII blocks are more restricted in placement, as they require two
// blocks to be placed consecutively. Processing them first may improve
// sharing (at least one zero block can be expected to be saved.)
for _, t := range b.Trie {
b.Checksum += b.buildTrie(t)
}
// Compute the offsets for all the Compacters.
offset := uint32(0)
for i := range b.Compactions {
c := &b.Compactions[i]
c.Offset = offset
offset += c.maxHandle + 1
c.Cutoff = offset
}
// Compute the sizes of indexes.
// TODO: different byte positions could have different sizes. So far we have
// not found a case where this is beneficial.
imax := uint64(b.Compactions[len(b.Compactions)-1].Cutoff)
for _, ib := range b.IndexBlocks {
if x := uint64(ib.index.index); x > imax {
imax = x
}
}
b.IndexType, b.IndexSize = getIntType(imax)
}
func maxValue(n *node, max uint64) uint64 {
if n == nil {
return max
}
for _, c := range n.children {
max = maxValue(c, max)
}
for _, v := range n.values {
if max < v {
max = v
}
}
return max
}
func getIntType(v uint64) (string, int) {
switch {
case v < 1<<8:
return "uint8", 1
case v < 1<<16:
return "uint16", 2
case v < 1<<32:
return "uint32", 4
}
return "uint64", 8
}
const (
blockSize = 64
// Subtract two blocks to offset 0x80, the first continuation byte.
blockOffset = 2
// Subtract three blocks to offset 0xC0, the first non-ASCII starter.
rootBlockOffset = 3
)
var crcTable = crc64.MakeTable(crc64.ISO)
func (b *builder) buildTrie(t *Trie) uint64 {
n := t.root
// Get the ASCII offset. For the first trie, the ASCII block will be at
// position 0.
hasher := crc64.New(crcTable)
binary.Write(hasher, binary.BigEndian, n.values)
hash := hasher.Sum64()
v, ok := b.asciiBlockIdx[hash]
if !ok {
v = len(b.ValueBlocks)
b.asciiBlockIdx[hash] = v
b.ValueBlocks = append(b.ValueBlocks, n.values[:blockSize], n.values[blockSize:])
if v == 0 {
// Add the zero block at position 2 so that it will be assigned a
// zero reference in the lookup blocks.
// TODO: always do this? This would allow us to remove a check from
// the trie lookup, but at the expense of extra space. Analyze
// performance for unicode/norm.
b.ValueBlocks = append(b.ValueBlocks, make([]uint64, blockSize))
}
}
t.ASCIIIndex = v
// Compute remaining offsets.
t.Checksum = b.computeOffsets(n, true)
// We already subtracted the normal blockOffset from the index. Subtract the
// difference for starter bytes.
t.StarterIndex = n.index.index - (rootBlockOffset - blockOffset)
return t.Checksum
}
func (b *builder) computeOffsets(n *node, root bool) uint64 {
// For the first trie, the root lookup block will be at position 3, which is
// the offset for UTF-8 non-ASCII starter bytes.
first := len(b.IndexBlocks) == rootBlockOffset
if first {
b.IndexBlocks = append(b.IndexBlocks, n)
}
// We special-case the cases where all values recursively are 0. This allows
// for the use of a zero block to which all such values can be directed.
hash := uint64(0)
if n.children != nil || n.values != nil {
hasher := crc64.New(crcTable)
for _, c := range n.children {
var v uint64
if c != nil {
v = b.computeOffsets(c, false)
}
binary.Write(hasher, binary.BigEndian, v)
}
binary.Write(hasher, binary.BigEndian, n.values)
hash = hasher.Sum64()
}
if first {
b.indexBlockIdx[hash] = rootBlockOffset - blockOffset
}
// Compacters don't apply to internal nodes.
if n.children != nil {
v, ok := b.indexBlockIdx[hash]
if !ok {
v = len(b.IndexBlocks) - blockOffset
b.IndexBlocks = append(b.IndexBlocks, n)
b.indexBlockIdx[hash] = v
}
n.index = nodeIndex{0, v}
} else {
h, ok := b.valueBlockIdx[hash]
if !ok {
bestI, bestSize := 0, blockSize*b.ValueSize
for i, c := range b.Compactions[1:] {
if sz, ok := c.c.Size(n.values); ok && bestSize > sz {
bestI, bestSize = i+1, sz
}
}
c := &b.Compactions[bestI]
c.totalSize += bestSize
v := c.c.Store(n.values)
if c.maxHandle < v {
c.maxHandle = v
}
h = nodeIndex{bestI, int(v)}
b.valueBlockIdx[hash] = h
}
n.index = h
}
return hash
}

81
vendor/golang.org/x/text/internal/ucd/example_test.go generated vendored Normal file
View file

@ -0,0 +1,81 @@
// Copyright 2014 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 ucd_test
import (
"fmt"
"strings"
"golang.org/x/text/internal/ucd"
)
func Example() {
// Read rune-by-rune from UnicodeData.
var count int
p := ucd.New(strings.NewReader(unicodeData))
for p.Next() {
count++
if lower := p.Runes(ucd.SimpleLowercaseMapping); lower != nil {
fmt.Printf("lower(%U) -> %U\n", p.Rune(0), lower[0])
}
}
if err := p.Err(); err != nil {
fmt.Println(err)
}
fmt.Println("Number of runes visited:", count)
// Read raw ranges from Scripts.
p = ucd.New(strings.NewReader(scripts), ucd.KeepRanges)
for p.Next() {
start, end := p.Range(0)
fmt.Printf("%04X..%04X: %s\n", start, end, p.String(1))
}
if err := p.Err(); err != nil {
fmt.Println(err)
}
// Output:
// lower(U+00C0) -> U+00E0
// lower(U+00C1) -> U+00E1
// lower(U+00C2) -> U+00E2
// lower(U+00C3) -> U+00E3
// lower(U+00C4) -> U+00E4
// Number of runes visited: 6594
// 0000..001F: Common
// 0020..0020: Common
// 0021..0023: Common
// 0024..0024: Common
}
// Excerpt from UnicodeData.txt
const unicodeData = `
00B9;SUPERSCRIPT ONE;No;0;EN;<super> 0031;;1;1;N;SUPERSCRIPT DIGIT ONE;;;;
00BA;MASCULINE ORDINAL INDICATOR;Lo;0;L;<super> 006F;;;;N;;;;;
00BB;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK;Pf;0;ON;;;;;Y;RIGHT POINTING GUILLEMET;;;;
00BC;VULGAR FRACTION ONE QUARTER;No;0;ON;<fraction> 0031 2044 0034;;;1/4;N;FRACTION ONE QUARTER;;;;
00BD;VULGAR FRACTION ONE HALF;No;0;ON;<fraction> 0031 2044 0032;;;1/2;N;FRACTION ONE HALF;;;;
00BE;VULGAR FRACTION THREE QUARTERS;No;0;ON;<fraction> 0033 2044 0034;;;3/4;N;FRACTION THREE QUARTERS;;;;
00BF;INVERTED QUESTION MARK;Po;0;ON;;;;;N;;;;;
00C0;LATIN CAPITAL LETTER A WITH GRAVE;Lu;0;L;0041 0300;;;;N;LATIN CAPITAL LETTER A GRAVE;;;00E0;
00C1;LATIN CAPITAL LETTER A WITH ACUTE;Lu;0;L;0041 0301;;;;N;LATIN CAPITAL LETTER A ACUTE;;;00E1;
00C2;LATIN CAPITAL LETTER A WITH CIRCUMFLEX;Lu;0;L;0041 0302;;;;N;LATIN CAPITAL LETTER A CIRCUMFLEX;;;00E2;
00C3;LATIN CAPITAL LETTER A WITH TILDE;Lu;0;L;0041 0303;;;;N;LATIN CAPITAL LETTER A TILDE;;;00E3;
00C4;LATIN CAPITAL LETTER A WITH DIAERESIS;Lu;0;L;0041 0308;;;;N;LATIN CAPITAL LETTER A DIAERESIS;;;00E4;
# A legacy rune range.
3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
`
// Excerpt from Scripts.txt
const scripts = `
# Property: Script
# ================================================
0000..001F ; Common # Cc [32] <control-0000>..<control-001F>
0020 ; Common # Zs SPACE
0021..0023 ; Common # Po [3] EXCLAMATION MARK..NUMBER SIGN
0024 ; Common # Sc DOLLAR SIGN
`

363
vendor/golang.org/x/text/internal/ucd/ucd.go generated vendored Normal file
View file

@ -0,0 +1,363 @@
// Copyright 2014 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 ucd provides a parser for Unicode Character Database files, the
// format of which is defined in http://www.unicode.org/reports/tr44/. See
// http://www.unicode.org/Public/UCD/latest/ucd/ for example files.
//
// It currently does not support substitutions of missing fields.
package ucd // import "golang.org/x/text/internal/ucd"
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"log"
"regexp"
"strconv"
"strings"
)
// UnicodeData.txt fields.
const (
CodePoint = iota
Name
GeneralCategory
CanonicalCombiningClass
BidiClass
DecompMapping
DecimalValue
DigitValue
NumericValue
BidiMirrored
Unicode1Name
ISOComment
SimpleUppercaseMapping
SimpleLowercaseMapping
SimpleTitlecaseMapping
)
// Parse calls f for each entry in the given reader of a UCD file. It will close
// the reader upon return. It will call log.Fatal if any error occurred.
//
// This implements the most common usage pattern of using Parser.
func Parse(r io.ReadCloser, f func(p *Parser)) {
defer r.Close()
p := New(r)
for p.Next() {
f(p)
}
if err := p.Err(); err != nil {
r.Close() // os.Exit will cause defers not to be called.
log.Fatal(err)
}
}
// An Option is used to configure a Parser.
type Option func(p *Parser)
func keepRanges(p *Parser) {
p.keepRanges = true
}
var (
// KeepRanges prevents the expansion of ranges. The raw ranges can be
// obtained by calling Range(0) on the parser.
KeepRanges Option = keepRanges
)
// The Part option register a handler for lines starting with a '@'. The text
// after a '@' is available as the first field. Comments are handled as usual.
func Part(f func(p *Parser)) Option {
return func(p *Parser) {
p.partHandler = f
}
}
// A Parser parses Unicode Character Database (UCD) files.
type Parser struct {
scanner *bufio.Scanner
keepRanges bool // Don't expand rune ranges in field 0.
err error
comment []byte
field [][]byte
// parsedRange is needed in case Range(0) is called more than once for one
// field. In some cases this requires scanning ahead.
parsedRange bool
rangeStart, rangeEnd rune
partHandler func(p *Parser)
}
func (p *Parser) setError(err error) {
if p.err == nil {
p.err = err
}
}
func (p *Parser) getField(i int) []byte {
if i >= len(p.field) {
p.setError(fmt.Errorf("ucd: index of field %d out of bounds", i))
return nil
}
return p.field[i]
}
// Err returns a non-nil error if any error occurred during parsing.
func (p *Parser) Err() error {
return p.err
}
// New returns a Parser for the given Reader.
func New(r io.Reader, o ...Option) *Parser {
p := &Parser{
scanner: bufio.NewScanner(r),
}
for _, f := range o {
f(p)
}
return p
}
// Next parses the next line in the file. It returns true if a line was parsed
// and false if it reached the end of the file.
func (p *Parser) Next() bool {
if !p.keepRanges && p.rangeStart < p.rangeEnd {
p.rangeStart++
return true
}
p.comment = nil
p.field = p.field[:0]
p.parsedRange = false
for p.scanner.Scan() {
b := p.scanner.Bytes()
if len(b) == 0 || b[0] == '#' {
continue
}
// Parse line
if i := bytes.IndexByte(b, '#'); i != -1 {
p.comment = bytes.TrimSpace(b[i+1:])
b = b[:i]
}
if b[0] == '@' {
if p.partHandler != nil {
p.field = append(p.field, bytes.TrimSpace(b[1:]))
p.partHandler(p)
p.field = p.field[:0]
}
p.comment = nil
continue
}
for {
i := bytes.IndexByte(b, ';')
if i == -1 {
p.field = append(p.field, bytes.TrimSpace(b))
break
}
p.field = append(p.field, bytes.TrimSpace(b[:i]))
b = b[i+1:]
}
if !p.keepRanges {
p.rangeStart, p.rangeEnd = p.getRange(0)
}
return true
}
p.setError(p.scanner.Err())
return false
}
func parseRune(b []byte) (rune, error) {
if len(b) > 2 && b[0] == 'U' && b[1] == '+' {
b = b[2:]
}
x, err := strconv.ParseUint(string(b), 16, 32)
return rune(x), err
}
func (p *Parser) parseRune(b []byte) rune {
x, err := parseRune(b)
p.setError(err)
return x
}
// Rune parses and returns field i as a rune.
func (p *Parser) Rune(i int) rune {
if i > 0 || p.keepRanges {
return p.parseRune(p.getField(i))
}
return p.rangeStart
}
// Runes interprets and returns field i as a sequence of runes.
func (p *Parser) Runes(i int) (runes []rune) {
add := func(b []byte) {
if b = bytes.TrimSpace(b); len(b) > 0 {
runes = append(runes, p.parseRune(b))
}
}
for b := p.getField(i); ; {
i := bytes.IndexByte(b, ' ')
if i == -1 {
add(b)
break
}
add(b[:i])
b = b[i+1:]
}
return
}
var (
errIncorrectLegacyRange = errors.New("ucd: unmatched <* First>")
// reRange matches one line of a legacy rune range.
reRange = regexp.MustCompile("^([0-9A-F]*);<([^,]*), ([^>]*)>(.*)$")
)
// Range parses and returns field i as a rune range. A range is inclusive at
// both ends. If the field only has one rune, first and last will be identical.
// It supports the legacy format for ranges used in UnicodeData.txt.
func (p *Parser) Range(i int) (first, last rune) {
if !p.keepRanges {
return p.rangeStart, p.rangeStart
}
return p.getRange(i)
}
func (p *Parser) getRange(i int) (first, last rune) {
b := p.getField(i)
if k := bytes.Index(b, []byte("..")); k != -1 {
return p.parseRune(b[:k]), p.parseRune(b[k+2:])
}
// The first field may not be a rune, in which case we may ignore any error
// and set the range as 0..0.
x, err := parseRune(b)
if err != nil {
// Disable range parsing henceforth. This ensures that an error will be
// returned if the user subsequently will try to parse this field as
// a Rune.
p.keepRanges = true
}
// Special case for UnicodeData that was retained for backwards compatibility.
if i == 0 && len(p.field) > 1 && bytes.HasSuffix(p.field[1], []byte("First>")) {
if p.parsedRange {
return p.rangeStart, p.rangeEnd
}
mf := reRange.FindStringSubmatch(p.scanner.Text())
if mf == nil || !p.scanner.Scan() {
p.setError(errIncorrectLegacyRange)
return x, x
}
// Using Bytes would be more efficient here, but Text is a lot easier
// and this is not a frequent case.
ml := reRange.FindStringSubmatch(p.scanner.Text())
if ml == nil || mf[2] != ml[2] || ml[3] != "Last" || mf[4] != ml[4] {
p.setError(errIncorrectLegacyRange)
return x, x
}
p.rangeStart, p.rangeEnd = x, p.parseRune(p.scanner.Bytes()[:len(ml[1])])
p.parsedRange = true
return p.rangeStart, p.rangeEnd
}
return x, x
}
// bools recognizes all valid UCD boolean values.
var bools = map[string]bool{
"": false,
"N": false,
"No": false,
"F": false,
"False": false,
"Y": true,
"Yes": true,
"T": true,
"True": true,
}
// Bool parses and returns field i as a boolean value.
func (p *Parser) Bool(i int) bool {
b := p.getField(i)
for s, v := range bools {
if bstrEq(b, s) {
return v
}
}
p.setError(strconv.ErrSyntax)
return false
}
// Int parses and returns field i as an integer value.
func (p *Parser) Int(i int) int {
x, err := strconv.ParseInt(string(p.getField(i)), 10, 64)
p.setError(err)
return int(x)
}
// Uint parses and returns field i as an unsigned integer value.
func (p *Parser) Uint(i int) uint {
x, err := strconv.ParseUint(string(p.getField(i)), 10, 64)
p.setError(err)
return uint(x)
}
// Float parses and returns field i as a decimal value.
func (p *Parser) Float(i int) float64 {
x, err := strconv.ParseFloat(string(p.getField(i)), 64)
p.setError(err)
return x
}
// String parses and returns field i as a string value.
func (p *Parser) String(i int) string {
return string(p.getField(i))
}
// Strings parses and returns field i as a space-separated list of strings.
func (p *Parser) Strings(i int) []string {
ss := strings.Split(string(p.getField(i)), " ")
for i, s := range ss {
ss[i] = strings.TrimSpace(s)
}
return ss
}
// Comment returns the comments for the current line.
func (p *Parser) Comment() string {
return string(p.comment)
}
var errUndefinedEnum = errors.New("ucd: undefined enum value")
// Enum interprets and returns field i as a value that must be one of the values
// in enum.
func (p *Parser) Enum(i int, enum ...string) string {
b := p.getField(i)
for _, s := range enum {
if bstrEq(b, s) {
return s
}
}
p.setError(errUndefinedEnum)
return ""
}
func bstrEq(b []byte, s string) bool {
if len(b) != len(s) {
return false
}
for i, c := range b {
if c != s[i] {
return false
}
}
return true
}

105
vendor/golang.org/x/text/internal/ucd/ucd_test.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
package ucd
import (
"strings"
"testing"
)
const file = `
# Comments should be skipped
# rune; bool; uint; int; float; runes; # Y
0..0005; Y; 0; 2; -5.25 ; 0 1 2 3 4 5;
6..0007; Yes ; 6; 1; -4.25 ; 0006 0007;
8; T ; 8 ; 0 ;-3.25 ;;# T
9; True ;9 ; -1;-2.25 ; 0009;
# more comments to be ignored
@Part0
A; N; 10 ; -2; -1.25; ;# N
B; No; 11 ; -3; -0.25;
C; False;12; -4; 0.75;
D; ;13;-5;1.75;
@Part1 # Another part.
# We test part comments get removed by not commenting the the next line.
E..10FFFF; F; 14 ; -6; 2.75;
`
var want = []struct {
start, end rune
}{
{0x00, 0x05},
{0x06, 0x07},
{0x08, 0x08},
{0x09, 0x09},
{0x0A, 0x0A},
{0x0B, 0x0B},
{0x0C, 0x0C},
{0x0D, 0x0D},
{0x0E, 0x10FFFF},
}
func TestGetters(t *testing.T) {
parts := [][2]string{
{"Part0", ""},
{"Part1", "Another part."},
}
handler := func(p *Parser) {
if len(parts) == 0 {
t.Error("Part handler invoked too many times.")
return
}
want := parts[0]
parts = parts[1:]
if got0, got1 := p.String(0), p.Comment(); got0 != want[0] || got1 != want[1] {
t.Errorf(`part: got %q, %q; want %q"`, got0, got1, want)
}
}
p := New(strings.NewReader(file), KeepRanges, Part(handler))
for i := 0; p.Next(); i++ {
start, end := p.Range(0)
w := want[i]
if start != w.start || end != w.end {
t.Fatalf("%d:Range(0); got %#x..%#x; want %#x..%#x", i, start, end, w.start, w.end)
}
if w.start == w.end && p.Rune(0) != w.start {
t.Errorf("%d:Range(0).start: got %U; want %U", i, p.Rune(0), w.start)
}
if got, want := p.Bool(1), w.start <= 9; got != want {
t.Errorf("%d:Bool(1): got %v; want %v", i, got, want)
}
if got := p.Rune(4); got != 0 || p.Err() == nil {
t.Errorf("%d:Rune(%q): got no error; want error", i, p.String(1))
}
p.err = nil
if got := p.Uint(2); rune(got) != start {
t.Errorf("%d:Uint(2): got %v; want %v", i, got, start)
}
if got, want := p.Int(3), 2-i; got != want {
t.Errorf("%d:Int(3): got %v; want %v", i, got, want)
}
if got, want := p.Float(4), -5.25+float64(i); got != want {
t.Errorf("%d:Int(3): got %v; want %v", i, got, want)
}
if got := p.Runes(5); got == nil {
if p.String(5) != "" {
t.Errorf("%d:Runes(5): expected non-empty list", i)
}
} else {
if got[0] != start || got[len(got)-1] != end {
t.Errorf("%d:Runes(5): got %#x; want %#x..%#x", i, got, start, end)
}
}
if got := p.Comment(); got != "" && got != p.String(1) {
t.Errorf("%d:Comment(): got %v; want %v", i, got, p.String(1))
}
}
if err := p.Err(); err != nil {
t.Errorf("Parser error: %v", err)
}
if len(parts) != 0 {
t.Errorf("expected %d more invocations of part handler", len(parts))
}
}

View file

@ -0,0 +1,87 @@
// 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.
// Package utf8internal contains low-level utf8-related constants, tables, etc.
// that are used internally by the text package.
package utf8internal
// The default lowest and highest continuation byte.
const (
LoCB = 0x80 // 1000 0000
HiCB = 0xBF // 1011 1111
)
// Constants related to getting information of first bytes of UTF-8 sequences.
const (
// ASCII identifies a UTF-8 byte as ASCII.
ASCII = as
// FirstInvalid indicates a byte is invalid as a first byte of a UTF-8
// sequence.
FirstInvalid = xx
// SizeMask is a mask for the size bits. Use use x&SizeMask to get the size.
SizeMask = 7
// AcceptShift is the right-shift count for the first byte info byte to get
// the index into the AcceptRanges table. See AcceptRanges.
AcceptShift = 4
// The names of these constants are chosen to give nice alignment in the
// table below. The first nibble is an index into acceptRanges or F for
// special one-byte cases. The second nibble is the Rune length or the
// Status for the special one-byte case.
xx = 0xF1 // invalid: size 1
as = 0xF0 // ASCII: size 1
s1 = 0x02 // accept 0, size 2
s2 = 0x13 // accept 1, size 3
s3 = 0x03 // accept 0, size 3
s4 = 0x23 // accept 2, size 3
s5 = 0x34 // accept 3, size 4
s6 = 0x04 // accept 0, size 4
s7 = 0x44 // accept 4, size 4
)
// First is information about the first byte in a UTF-8 sequence.
var First = [256]uint8{
// 1 2 3 4 5 6 7 8 9 A B C D E F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
// 1 2 3 4 5 6 7 8 9 A B C D E F
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
}
// AcceptRange gives the range of valid values for the second byte in a UTF-8
// sequence for any value for First that is not ASCII or FirstInvalid.
type AcceptRange struct {
Lo uint8 // lowest value for second byte.
Hi uint8 // highest value for second byte.
}
// AcceptRanges is a slice of AcceptRange values. For a given byte sequence b
//
// AcceptRanges[First[b[0]]>>AcceptShift]
//
// will give the value of AcceptRange for the multi-byte UTF-8 sequence starting
// at b[0].
var AcceptRanges = [...]AcceptRange{
0: {LoCB, HiCB},
1: {0xA0, HiCB},
2: {LoCB, 0x9F},
3: {0x90, HiCB},
4: {LoCB, 0x8F},
}