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  }