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  }