github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/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 "golang.org/x/text/internal/language/compact" 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 symOffset // 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 compact.ID, numberSystem string) Info { 27 p := langToDefaults[compactIndex] 28 // Lookup the entry for the language. 29 pSymIndex := symOffset(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&hasNonLatnMask == 0 { // Latn digits. 35 pSymIndex = p 36 } else { // Non-Latn or multiple numbering systems. 37 // Take the first entry from the alternatives list. 38 data := langToAlt[p&^hasNonLatnMask] 39 pSymIndex = data.symIndex 40 system = data.system 41 } 42 } else { 43 langIndex := compactIndex 44 ns := system 45 outerLoop: 46 for ; ; p = langToDefaults[langIndex] { 47 if p&hasNonLatnMask == 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 = langIndex.Parent() 55 } else { 56 // The index points to a list of symbol data indexes. 57 for _, e := range langToAlt[p&^hasNonLatnMask:] { 58 if e.compactTag != langIndex { 59 if langIndex == 0 { 60 // The CLDR root defines full symbol information for 61 // all numbering systems (even though mostly by 62 // means of aliases). Fall back to the default entry 63 // for Latn if there is no data for the numbering 64 // system of this language. 65 if ns == 0 { 66 break 67 } 68 // Fall back to Latin and start from the original 69 // language. See 70 // https://unicode.org/reports/tr35/#Locale_Inheritance. 71 ns = numLatn 72 langIndex = compactIndex 73 continue outerLoop 74 } 75 // Fall back to parent. 76 langIndex = langIndex.Parent() 77 } else if e.system == ns { 78 pSymIndex = e.symIndex 79 break outerLoop 80 } 81 } 82 } 83 } 84 } 85 if int(system) >= len(numSysData) { // algorithmic 86 // Will generate ASCII digits in case the user inadvertently calls 87 // WriteDigit or Digit on it. 88 d := numSysData[0] 89 d.id = system 90 return Info{ 91 system: d, 92 symIndex: pSymIndex, 93 } 94 } 95 return Info{ 96 system: numSysData[system], 97 symIndex: pSymIndex, 98 } 99 } 100 101 // InfoFromTag returns a Info for the given language tag. 102 func InfoFromTag(t language.Tag) Info { 103 return InfoFromLangID(tagToID(t), t.TypeForKey("nu")) 104 } 105 106 // IsDecimal reports if the numbering system can convert decimal to native 107 // symbols one-to-one. 108 func (n Info) IsDecimal() bool { 109 return int(n.system.id) < len(numSysData) 110 } 111 112 // WriteDigit writes the UTF-8 sequence for n corresponding to the given ASCII 113 // digit to dst and reports the number of bytes written. dst must be large 114 // enough to hold the rune (can be up to utf8.UTFMax bytes). 115 func (n Info) WriteDigit(dst []byte, asciiDigit rune) int { 116 copy(dst, n.system.zero[:n.system.digitSize]) 117 dst[n.system.digitSize-1] += byte(asciiDigit - '0') 118 return int(n.system.digitSize) 119 } 120 121 // AppendDigit appends the UTF-8 sequence for n corresponding to the given digit 122 // to dst and reports the number of bytes written. dst must be large enough to 123 // hold the rune (can be up to utf8.UTFMax bytes). 124 func (n Info) AppendDigit(dst []byte, digit byte) []byte { 125 dst = append(dst, n.system.zero[:n.system.digitSize]...) 126 dst[len(dst)-1] += digit 127 return dst 128 } 129 130 // Digit returns the digit for the numbering system for the corresponding ASCII 131 // value. For example, ni.Digit('3') could return 'δΈ‰'. Note that the argument 132 // is the rune constant '3', which equals 51, not the integer constant 3. 133 func (n Info) Digit(asciiDigit rune) rune { 134 var x [utf8.UTFMax]byte 135 n.WriteDigit(x[:], asciiDigit) 136 r, _ := utf8.DecodeRune(x[:]) 137 return r 138 } 139 140 // Symbol returns the string for the given symbol type. 141 func (n Info) Symbol(t SymbolType) string { 142 return symData.Elem(int(symIndex[n.symIndex][t])) 143 } 144 145 func formatForLang(t language.Tag, index []byte) *Pattern { 146 return &formats[index[tagToID(t)]] 147 } 148 149 func tagToID(t language.Tag) compact.ID { 150 id, _ := compact.RegionalID(compact.Tag(t)) 151 return id 152 }