OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / internal / number / number.go
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:generate go run gen.go gen_common.go
6
7 // Package number contains tools and data for formatting numbers.
8 package number
9
10 import (
11         "unicode/utf8"
12
13         "golang.org/x/text/internal"
14         "golang.org/x/text/language"
15 )
16
17 // Info holds number formatting configuration data.
18 type Info struct {
19         system   systemData // numbering system information
20         symIndex byte       // index to symbols
21 }
22
23 // InfoFromLangID returns a Info for the given compact language identifier and
24 // numbering system identifier. If system is the empty string, the default
25 // numbering system will be taken for that language.
26 func InfoFromLangID(compactIndex int, numberSystem string) Info {
27         p := langToDefaults[compactIndex]
28         // Lookup the entry for the language.
29         pSymIndex := byte(0) // Default: Latin, default symbols
30         system, ok := systemMap[numberSystem]
31         if !ok {
32                 // Take the value for the default numbering system. This is by far the
33                 // most common case as an alternative numbering system is hardly used.
34                 if p&0x80 == 0 {
35                         pSymIndex = p
36                 } else {
37                         // Take the first entry from the alternatives list.
38                         data := langToAlt[p&^0x80]
39                         pSymIndex = data.symIndex
40                         system = data.system
41                 }
42         } else {
43                 langIndex := compactIndex
44                 ns := system
45         outerLoop:
46                 for {
47                         if p&0x80 == 0 {
48                                 if ns == 0 {
49                                         // The index directly points to the symbol data.
50                                         pSymIndex = p
51                                         break
52                                 }
53                                 // Move to the parent and retry.
54                                 langIndex = int(internal.Parent[langIndex])
55                         }
56                         // The index points to a list of symbol data indexes.
57                         for _, e := range langToAlt[p&^0x80:] {
58                                 if int(e.compactTag) != langIndex {
59                                         if langIndex == 0 {
60                                                 // The CLDR root defines full symbol information for all
61                                                 // numbering systems (even though mostly by means of
62                                                 // aliases). This means that we will never fall back to
63                                                 // the default of the language. Also, the loop is
64                                                 // guaranteed to terminate as a consequence.
65                                                 ns = numLatn
66                                                 // Fall back to Latin and start from the original
67                                                 // language. See
68                                                 // http://unicode.org/reports/tr35/#Locale_Inheritance.
69                                                 langIndex = compactIndex
70                                         } else {
71                                                 // Fall back to parent.
72                                                 langIndex = int(internal.Parent[langIndex])
73                                         }
74                                         break
75                                 }
76                                 if e.system == ns {
77                                         pSymIndex = e.symIndex
78                                         break outerLoop
79                                 }
80                         }
81                 }
82         }
83         if int(system) >= len(numSysData) { // algorithmic
84                 // Will generate ASCII digits in case the user inadvertently calls
85                 // WriteDigit or Digit on it.
86                 d := numSysData[0]
87                 d.id = system
88                 return Info{
89                         system:   d,
90                         symIndex: pSymIndex,
91                 }
92         }
93         return Info{
94                 system:   numSysData[system],
95                 symIndex: pSymIndex,
96         }
97 }
98
99 // InfoFromTag returns a Info for the given language tag.
100 func InfoFromTag(t language.Tag) Info {
101         for {
102                 if index, ok := language.CompactIndex(t); ok {
103                         return InfoFromLangID(index, t.TypeForKey("nu"))
104                 }
105                 t = t.Parent()
106         }
107 }
108
109 // IsDecimal reports if the numbering system can convert decimal to native
110 // symbols one-to-one.
111 func (n Info) IsDecimal() bool {
112         return int(n.system.id) < len(numSysData)
113 }
114
115 // WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII
116 // digit to dst and reports the number of bytes written. dst must be large
117 // enough to hold the rune (can be up to utf8.UTFMax bytes).
118 func (n Info) WriteDigit(dst []byte, asciiDigit rune) int {
119         copy(dst, n.system.zero[:n.system.digitSize])
120         dst[n.system.digitSize-1] += byte(asciiDigit - '0')
121         return int(n.system.digitSize)
122 }
123
124 // AppendDigit appends the UTF-8 sequence for n corresponding to the given digit
125 // to dst and reports the number of bytes written. dst must be large enough to
126 // hold the rune (can be up to utf8.UTFMax bytes).
127 func (n Info) AppendDigit(dst []byte, digit byte) []byte {
128         dst = append(dst, n.system.zero[:n.system.digitSize]...)
129         dst[len(dst)-1] += digit
130         return dst
131 }
132
133 // Digit returns the digit for the numbering system for the corresponding ASCII
134 // value. For example, ni.Digit('3') could return 'δΈ‰'. Note that the argument
135 // is the rune constant '3', which equals 51, not the integer constant 3.
136 func (n Info) Digit(asciiDigit rune) rune {
137         var x [utf8.UTFMax]byte
138         n.WriteDigit(x[:], asciiDigit)
139         r, _ := utf8.DecodeRune(x[:])
140         return r
141 }
142
143 // Symbol returns the string for the given symbol type.
144 func (n Info) Symbol(t SymbolType) string {
145         return symData.Elem(int(symIndex[n.symIndex][t]))
146 }
147
148 func formatForLang(t language.Tag, index []byte) *Pattern {
149         for ; ; t = t.Parent() {
150                 if x, ok := language.CompactIndex(t); ok {
151                         return &formats[index[x]]
152                 }
153         }
154 }