github.com/go-xe2/third@v1.0.3/golang.org/x/text/internal/number/number.go (about) 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 "github.com/go-xe2/third/golang.org/x/text/internal" 14 "github.com/go-xe2/third/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 }