|  | // Copyright 2015 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | //go:generate go run gen.go gen_common.go -output tables.go | 
|  |  | 
|  | // Package currency contains currency-related functionality. | 
|  | // | 
|  | // NOTE: the formatting functionality is currently under development and may | 
|  | // change without notice. | 
|  | package currency // import "golang.org/x/text/currency" | 
|  |  | 
|  | import ( | 
|  | "errors" | 
|  | "sort" | 
|  |  | 
|  | "golang.org/x/text/internal/tag" | 
|  | "golang.org/x/text/language" | 
|  | ) | 
|  |  | 
|  | // TODO: | 
|  | // - language-specific currency names. | 
|  | // - currency formatting. | 
|  | // - currency information per region | 
|  | // - register currency code (there are no private use area) | 
|  |  | 
|  | // TODO: remove Currency type from package language. | 
|  |  | 
|  | // Kind determines the rounding and rendering properties of a currency value. | 
|  | type Kind struct { | 
|  | rounding rounding | 
|  | // TODO: formatting type: standard, accounting. See CLDR. | 
|  | } | 
|  |  | 
|  | type rounding byte | 
|  |  | 
|  | const ( | 
|  | standard rounding = iota | 
|  | cash | 
|  | ) | 
|  |  | 
|  | var ( | 
|  | // Standard defines standard rounding and formatting for currencies. | 
|  | Standard Kind = Kind{rounding: standard} | 
|  |  | 
|  | // Cash defines rounding and formatting standards for cash transactions. | 
|  | Cash Kind = Kind{rounding: cash} | 
|  |  | 
|  | // Accounting defines rounding and formatting standards for accounting. | 
|  | Accounting Kind = Kind{rounding: standard} | 
|  | ) | 
|  |  | 
|  | // Rounding reports the rounding characteristics for the given currency, where | 
|  | // scale is the number of fractional decimals and increment is the number of | 
|  | // units in terms of 10^(-scale) to which to round to. | 
|  | func (k Kind) Rounding(cur Unit) (scale, increment int) { | 
|  | info := currency.Elem(int(cur.index))[3] | 
|  | switch k.rounding { | 
|  | case standard: | 
|  | info &= roundMask | 
|  | case cash: | 
|  | info >>= cashShift | 
|  | } | 
|  | return int(roundings[info].scale), int(roundings[info].increment) | 
|  | } | 
|  |  | 
|  | // Unit is an ISO 4217 currency designator. | 
|  | type Unit struct { | 
|  | index uint16 | 
|  | } | 
|  |  | 
|  | // String returns the ISO code of u. | 
|  | func (u Unit) String() string { | 
|  | if u.index == 0 { | 
|  | return "XXX" | 
|  | } | 
|  | return currency.Elem(int(u.index))[:3] | 
|  | } | 
|  |  | 
|  | // Amount creates an Amount for the given currency unit and amount. | 
|  | func (u Unit) Amount(amount interface{}) Amount { | 
|  | // TODO: verify amount is a supported number type | 
|  | return Amount{amount: amount, currency: u} | 
|  | } | 
|  |  | 
|  | var ( | 
|  | errSyntax = errors.New("currency: tag is not well-formed") | 
|  | errValue  = errors.New("currency: tag is not a recognized currency") | 
|  | ) | 
|  |  | 
|  | // ParseISO parses a 3-letter ISO 4217 currency code. It returns an error if s | 
|  | // is not well-formed or not a recognized currency code. | 
|  | func ParseISO(s string) (Unit, error) { | 
|  | var buf [4]byte // Take one byte more to detect oversize keys. | 
|  | key := buf[:copy(buf[:], s)] | 
|  | if !tag.FixCase("XXX", key) { | 
|  | return Unit{}, errSyntax | 
|  | } | 
|  | if i := currency.Index(key); i >= 0 { | 
|  | if i == xxx { | 
|  | return Unit{}, nil | 
|  | } | 
|  | return Unit{uint16(i)}, nil | 
|  | } | 
|  | return Unit{}, errValue | 
|  | } | 
|  |  | 
|  | // MustParseISO is like ParseISO, but panics if the given currency unit | 
|  | // cannot be parsed. It simplifies safe initialization of Unit values. | 
|  | func MustParseISO(s string) Unit { | 
|  | c, err := ParseISO(s) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  | return c | 
|  | } | 
|  |  | 
|  | // FromRegion reports the currency unit that is currently legal tender in the | 
|  | // given region according to CLDR. It will return false if region currently does | 
|  | // not have a legal tender. | 
|  | func FromRegion(r language.Region) (currency Unit, ok bool) { | 
|  | x := regionToCode(r) | 
|  | i := sort.Search(len(regionToCurrency), func(i int) bool { | 
|  | return regionToCurrency[i].region >= x | 
|  | }) | 
|  | if i < len(regionToCurrency) && regionToCurrency[i].region == x { | 
|  | return Unit{regionToCurrency[i].code}, true | 
|  | } | 
|  | return Unit{}, false | 
|  | } | 
|  |  | 
|  | // FromTag reports the most likely currency for the given tag. It considers the | 
|  | // currency defined in the -u extension and infers the region if necessary. | 
|  | func FromTag(t language.Tag) (Unit, language.Confidence) { | 
|  | if cur := t.TypeForKey("cu"); len(cur) == 3 { | 
|  | c, _ := ParseISO(cur) | 
|  | return c, language.Exact | 
|  | } | 
|  | r, conf := t.Region() | 
|  | if cur, ok := FromRegion(r); ok { | 
|  | return cur, conf | 
|  | } | 
|  | return Unit{}, language.No | 
|  | } | 
|  |  | 
|  | var ( | 
|  | // Undefined and testing. | 
|  | XXX Unit = Unit{} | 
|  | XTS Unit = Unit{xts} | 
|  |  | 
|  | // G10 currencies https://en.wikipedia.org/wiki/G10_currencies. | 
|  | USD Unit = Unit{usd} | 
|  | EUR Unit = Unit{eur} | 
|  | JPY Unit = Unit{jpy} | 
|  | GBP Unit = Unit{gbp} | 
|  | CHF Unit = Unit{chf} | 
|  | AUD Unit = Unit{aud} | 
|  | NZD Unit = Unit{nzd} | 
|  | CAD Unit = Unit{cad} | 
|  | SEK Unit = Unit{sek} | 
|  | NOK Unit = Unit{nok} | 
|  |  | 
|  | // Additional common currencies as defined by CLDR. | 
|  | BRL Unit = Unit{brl} | 
|  | CNY Unit = Unit{cny} | 
|  | DKK Unit = Unit{dkk} | 
|  | INR Unit = Unit{inr} | 
|  | RUB Unit = Unit{rub} | 
|  | HKD Unit = Unit{hkd} | 
|  | IDR Unit = Unit{idr} | 
|  | KRW Unit = Unit{krw} | 
|  | MXN Unit = Unit{mxn} | 
|  | PLN Unit = Unit{pln} | 
|  | SAR Unit = Unit{sar} | 
|  | THB Unit = Unit{thb} | 
|  | TRY Unit = Unit{try} | 
|  | TWD Unit = Unit{twd} | 
|  | ZAR Unit = Unit{zar} | 
|  |  | 
|  | // Precious metals. | 
|  | XAG Unit = Unit{xag} | 
|  | XAU Unit = Unit{xau} | 
|  | XPT Unit = Unit{xpt} | 
|  | XPD Unit = Unit{xpd} | 
|  | ) |