1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3
4 #include "unicode/utypes.h"
5
6 #if !UCONFIG_NO_FORMATTING
7
8 // Allow implicit conversion from char16_t* to UnicodeString for this file:
9 // Helpful in toString methods and elsewhere.
10 #define UNISTR_FROM_STRING_EXPLICIT
11
12 #include "numparse_types.h"
13 #include "number_currencysymbols.h"
14
15 using namespace icu;
16 using namespace icu::number;
17 using namespace icu::number::impl;
18
19
CurrencySymbols(CurrencyUnit currency,const Locale & locale,UErrorCode & status)20 CurrencySymbols::CurrencySymbols(CurrencyUnit currency, const Locale& locale, UErrorCode& status)
21 : fCurrency(currency), fLocaleName(locale.getName(), status) {
22 fCurrencySymbol.setToBogus();
23 fIntlCurrencySymbol.setToBogus();
24 }
25
CurrencySymbols(CurrencyUnit currency,const Locale & locale,const DecimalFormatSymbols & symbols,UErrorCode & status)26 CurrencySymbols::CurrencySymbols(CurrencyUnit currency, const Locale& locale,
27 const DecimalFormatSymbols& symbols, UErrorCode& status)
28 : CurrencySymbols(currency, locale, status) {
29 // If either of the overrides is present, save it in the local UnicodeString.
30 if (symbols.isCustomCurrencySymbol()) {
31 fCurrencySymbol = symbols.getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
32 }
33 if (symbols.isCustomIntlCurrencySymbol()) {
34 fIntlCurrencySymbol = symbols.getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
35 }
36 }
37
getIsoCode() const38 const char16_t* CurrencySymbols::getIsoCode() const {
39 return fCurrency.getISOCurrency();
40 }
41
getNarrowCurrencySymbol(UErrorCode & status) const42 UnicodeString CurrencySymbols::getNarrowCurrencySymbol(UErrorCode& status) const {
43 // Note: currently no override is available for narrow currency symbol
44 return loadSymbol(UCURR_NARROW_SYMBOL_NAME, status);
45 }
46
getFormalCurrencySymbol(UErrorCode & status) const47 UnicodeString CurrencySymbols::getFormalCurrencySymbol(UErrorCode& status) const {
48 // Note: currently no override is available for formal currency symbol
49 return loadSymbol(UCURR_FORMAL_SYMBOL_NAME, status);
50 }
51
getVariantCurrencySymbol(UErrorCode & status) const52 UnicodeString CurrencySymbols::getVariantCurrencySymbol(UErrorCode& status) const {
53 // Note: currently no override is available for variant currency symbol
54 return loadSymbol(UCURR_VARIANT_SYMBOL_NAME, status);
55 }
56
getCurrencySymbol(UErrorCode & status) const57 UnicodeString CurrencySymbols::getCurrencySymbol(UErrorCode& status) const {
58 if (!fCurrencySymbol.isBogus()) {
59 return fCurrencySymbol;
60 }
61 return loadSymbol(UCURR_SYMBOL_NAME, status);
62 }
63
loadSymbol(UCurrNameStyle selector,UErrorCode & status) const64 UnicodeString CurrencySymbols::loadSymbol(UCurrNameStyle selector, UErrorCode& status) const {
65 const char16_t* isoCode = fCurrency.getISOCurrency();
66 int32_t symbolLen = 0;
67 const char16_t* symbol = ucurr_getName(
68 isoCode,
69 fLocaleName.data(),
70 selector,
71 nullptr /* isChoiceFormat */,
72 &symbolLen,
73 &status);
74 // If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely!
75 // Otherwise, symbol points to a resource bundle, and we can use readonly-aliasing constructor.
76 if (symbol == isoCode) {
77 return UnicodeString(isoCode, 3);
78 } else {
79 return UnicodeString(true, symbol, symbolLen);
80 }
81 }
82
getIntlCurrencySymbol(UErrorCode &) const83 UnicodeString CurrencySymbols::getIntlCurrencySymbol(UErrorCode&) const {
84 if (!fIntlCurrencySymbol.isBogus()) {
85 return fIntlCurrencySymbol;
86 }
87 // Note: Not safe to use readonly-aliasing constructor here because the buffer belongs to this object,
88 // which could be destructed or moved during the lifetime of the return value.
89 return UnicodeString(fCurrency.getISOCurrency(), 3);
90 }
91
getPluralName(StandardPlural::Form plural,UErrorCode & status) const92 UnicodeString CurrencySymbols::getPluralName(StandardPlural::Form plural, UErrorCode& status) const {
93 const char16_t* isoCode = fCurrency.getISOCurrency();
94 int32_t symbolLen = 0;
95 const char16_t* symbol = ucurr_getPluralName(
96 isoCode,
97 fLocaleName.data(),
98 nullptr /* isChoiceFormat */,
99 StandardPlural::getKeyword(plural),
100 &symbolLen,
101 &status);
102 // If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely!
103 // Otherwise, symbol points to a resource bundle, and we can use readonly-aliasing constructor.
104 if (symbol == isoCode) {
105 return UnicodeString(isoCode, 3);
106 } else {
107 return UnicodeString(true, symbol, symbolLen);
108 }
109 }
110
hasEmptyCurrencySymbol() const111 bool CurrencySymbols::hasEmptyCurrencySymbol() const {
112 return !fCurrencySymbol.isBogus() && fCurrencySymbol.isEmpty();
113 }
114
115
116 CurrencyUnit
resolveCurrency(const DecimalFormatProperties & properties,const Locale & locale,UErrorCode & status)117 icu::number::impl::resolveCurrency(const DecimalFormatProperties& properties, const Locale& locale,
118 UErrorCode& status) {
119 if (!properties.currency.isNull()) {
120 return properties.currency.getNoError();
121 } else {
122 UErrorCode localStatus = U_ZERO_ERROR;
123 char16_t buf[4] = {};
124 ucurr_forLocale(locale.getName(), buf, 4, &localStatus);
125 if (U_SUCCESS(localStatus)) {
126 return CurrencyUnit(buf, status);
127 } else {
128 // Default currency (XXX)
129 return CurrencyUnit();
130 }
131 }
132 }
133
134
135 #endif /* #if !UCONFIG_NO_FORMATTING */
136