ICU-13634 Fixing more assorted currency parsing issues.

X-SVN-Rev: 41214
This commit is contained in:
Shane Carr 2018-04-11 02:18:13 +00:00
parent b9925e084e
commit a901b5c04a
7 changed files with 78 additions and 32 deletions

View File

@ -52,17 +52,23 @@ UnicodeString CurrencySymbols::getCurrencySymbol(UErrorCode& status) const {
}
UnicodeString CurrencySymbols::loadSymbol(UCurrNameStyle selector, UErrorCode& status) const {
const char16_t* isoCode = fCurrency.getISOCurrency();
UBool ignoredIsChoiceFormatFillIn = FALSE;
int32_t symbolLen = 0;
const char16_t* symbol = ucurr_getName(
fCurrency.getISOCurrency(),
isoCode,
fLocaleName.data(),
selector,
&ignoredIsChoiceFormatFillIn,
&symbolLen,
&status);
// Readonly-aliasing char16_t* constructor, which points to a resource bundle:
return UnicodeString(TRUE, symbol, symbolLen);
// If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely!
// Otherwise, symbol points to a resource bundle, and we can use readonly-aliasing constructor.
if (symbol == isoCode) {
return UnicodeString(isoCode, 3);
} else {
return UnicodeString(TRUE, symbol, symbolLen);
}
}
UnicodeString CurrencySymbols::getIntlCurrencySymbol(UErrorCode&) const {
@ -75,17 +81,23 @@ UnicodeString CurrencySymbols::getIntlCurrencySymbol(UErrorCode&) const {
}
UnicodeString CurrencySymbols::getPluralName(StandardPlural::Form plural, UErrorCode& status) const {
const char16_t* isoCode = fCurrency.getISOCurrency();
UBool isChoiceFormat = FALSE;
int32_t symbolLen = 0;
const char16_t* symbol = ucurr_getPluralName(
fCurrency.getISOCurrency(),
isoCode,
fLocaleName.data(),
&isChoiceFormat,
StandardPlural::getKeyword(plural),
&symbolLen,
&status);
// Readonly-aliasing char16_t* constructor, which points to a resource bundle:
return UnicodeString(TRUE, symbol, symbolLen);
// If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely!
// Otherwise, symbol points to a resource bundle, and we can use readonly-aliasing constructor.
if (symbol == isoCode) {
return UnicodeString(isoCode, 3);
} else {
return UnicodeString(TRUE, symbol, symbolLen);
}
}

View File

@ -81,7 +81,7 @@ bool CombinedCurrencyMatcher::match(StringSegment& segment, ParsedNumber& result
bool CombinedCurrencyMatcher::matchCurrency(StringSegment& segment, ParsedNumber& result,
UErrorCode& status) const {
int32_t overlap1 = segment.getCommonPrefixLength(fCurrency1);
int32_t overlap1 = segment.getCaseSensitivePrefixLength(fCurrency1);
if (overlap1 == fCurrency1.length()) {
utils::copyCurrencyCode(result.currencyCode, fCurrencyCode);
segment.adjustOffset(overlap1);
@ -89,7 +89,7 @@ bool CombinedCurrencyMatcher::matchCurrency(StringSegment& segment, ParsedNumber
return segment.length() == 0;
}
int32_t overlap2 = segment.getCommonPrefixLength(fCurrency2);
int32_t overlap2 = segment.getCaseSensitivePrefixLength(fCurrency2);
if (overlap2 == fCurrency2.length()) {
utils::copyCurrencyCode(result.currencyCode, fCurrencyCode);
segment.adjustOffset(overlap2);

View File

@ -4082,24 +4082,24 @@ NumberFormatTest::TestCurrencyParsing() {
// format result using CURRENCYSTYLE,
// format result using ISOCURRENCYSTYLE,
// format result using PLURALCURRENCYSTYLE,
{"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
{"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollar"},
{"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
{"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
{"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
{"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
{"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
{"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 Ameri\\u010dki dolar"},
{"id_ID", "1", "USD", "US$1,00", "USD1,00", "1,00 Dolar Amerika Serikat"},
{"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
{"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 Dollaro Statunitense"},
{"ko_KR", "1", "USD", "US$1.00", "USD1.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
{"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00\\u7c73\\u30c9\\u30eb"},
{"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
{"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
{"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
{"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u5713"},
{"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
{"ja_JP", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
{"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"}
{"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
{"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
{"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
{"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
{"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
{"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1.00 \\u65e5\\u5713"},
{"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1.00\\u00A0\\u65e5\\u672c\\u5186"},
{"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1.00\\u00A0\\u65e5\\u672c\\u5186"},
{"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"}
};
static const UNumberFormatStyle currencyStyles[] = {
UNUM_CURRENCY,
@ -4158,7 +4158,9 @@ for (;;) {
}
*/
// test parsing, and test parsing for all currency formats.
for (int j = 3; j < 6; ++j) {
// NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
//for (int j = 3; j < 6; ++j) {
for (int j = 3 + kIndex; j <= 3 + kIndex; j++) {
// DATA[i][3] is the currency format result using
// CURRENCYSTYLE formatter.
// DATA[i][4] is the currency format result using
@ -6744,6 +6746,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
UnicodeString formatted = ctou(DATA[i]);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
numFmt->setLenient(TRUE); // ICU 62 PATCH
if (numFmt != NULL && U_SUCCESS(status)) {
ParsePosition parsePos;
LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));

View File

@ -109,7 +109,7 @@ public class CombinedCurrencyMatcher implements NumberParseMatcher {
/** Matches the currency string without concern for currency spacing. */
private boolean matchCurrency(StringSegment segment, ParsedNumber result) {
int overlap1 = segment.getCommonPrefixLength(currency1);
int overlap1 = segment.getCaseSensitivePrefixLength(currency1);
if (overlap1 == currency1.length()) {
result.currencyCode = isoCode;
segment.adjustOffset(overlap1);
@ -117,7 +117,7 @@ public class CombinedCurrencyMatcher implements NumberParseMatcher {
return segment.length() == 0;
}
int overlap2 = segment.getCommonPrefixLength(currency2);
int overlap2 = segment.getCaseSensitivePrefixLength(currency2);
if (overlap2 == currency2.length()) {
result.currencyCode = isoCode;
segment.adjustOffset(overlap2);

View File

@ -1023,7 +1023,7 @@ begin
parse output outputCurrency breaks
53.45 fail GBP
£53.45 53.45 GBP
$53.45 fail USD J
$53.45 fail USD JP
53.45 USD 53.45 USD
53.45 GBP 53.45 GBP
USD 53.45 53.45 USD J
@ -1041,7 +1041,7 @@ USD(7.92) -7.92 USD CJ
(8) USD -8 USD
-8 USD -8 USD C
67 USD 67 USD
53.45$ fail USD
53.45$ fail USD P
US Dollars 53.45 53.45 USD J
53.45 US Dollars 53.45 USD
US Dollar 53.45 53.45 USD J
@ -1070,7 +1070,7 @@ begin
parse output outputCurrency breaks
53.45 fail GBP
£53.45 53.45 GBP
$53.45 fail USD J
$53.45 fail USD JP
53.45 USD 53.45 USD
53.45 GBP 53.45 GBP
USD 53.45 53.45 USD J
@ -1084,7 +1084,7 @@ USD -7.926 -7.926 USD CJ
USD-7.92 -7.92 USD CJ
-8 USD -8 USD
67 USD 67 USD
53.45$ fail USD
53.45$ fail USD P
US Dollars 53.45 53.45 USD J
53.45 US Dollars 53.45 USD
US Dollar 53.45 53.45 USD J
@ -1104,7 +1104,7 @@ parse output outputCurrency breaks
// J throws a NullPointerException on the first case
53.45 fail GBP
£53.45 53.45 GBP
$53.45 fail USD J
$53.45 fail USD JP
53.45 USD 53.45 USD
53.45 GBP 53.45 GBP
USD 53.45 53.45 USD J
@ -1123,7 +1123,7 @@ USD(7.92) -7.92 USD CJ
-8 USD -8 USD C
67 USD 67 USD
// J throws a NullPointerException on the next case
53.45$ fail USD
53.45$ fail USD P
US Dollars 53.45 53.45 USD J
53.45 US Dollars 53.45 USD
US Dollar 53.45 53.45 USD J
@ -1142,7 +1142,7 @@ begin
parse output outputCurrency breaks
53.45 fail GBP
£53.45 53.45 GBP
$53.45 fail USD J
$53.45 fail USD JP
53.45 USD 53.45 USD
53.45 GBP 53.45 GBP
USD 53.45 53.45 USD J
@ -1160,7 +1160,7 @@ USD(7.92) -7.92 USD CJ
(8) USD -8 USD
-8 USD -8 USD C
67 USD 67 USD
53.45$ fail USD
53.45$ fail USD P
US Dollars 53.45 53.45 USD J
53.45 US Dollars 53.45 USD
US Dollar 53.45 53.45 USD J
@ -1179,7 +1179,7 @@ begin
parse output outputCurrency breaks
53.45 fail GBP
£53.45 53.45 GBP
$53.45 fail USD J
$53.45 fail USD JP
53.45 USD 53.45 USD C
53.45 GBP 53.45 GBP C
USD 53.45 53.45 USD J
@ -1198,7 +1198,7 @@ USD(7.92) -7.92 USD CJP
(8) USD -8 USD CJP
-8 USD -8 USD C
67 USD 67 USD C
53.45$ fail USD
53.45$ fail USD P
US Dollars 53.45 53.45 USD J
53.45 US Dollars 53.45 USD
US Dollar 53.45 53.45 USD J
@ -1604,6 +1604,24 @@ lenient parse output breaks
0 0 fail CJK
0 +0 0 CJK
test parse lowercase currency
set locale en
set pattern ¤¤0
set currency USD
begin
parse output outputCurrency breaks
USD123 123 USD
USD 123 123 USD J
usd123 123 USD
usd 123 123 USD J
Usd123 123 USD
Usd 123 123 USD J
US$123 123 USD
us$123 fail fail
Us$123 fail fail
123 US dollars 123 USD
123 US DOLLARS 123 USD
123 us dollars 123 USD

View File

@ -663,6 +663,9 @@ public class NumberFormatDataDrivenTest {
if (ppos.getIndex() == 0 || actual.getCurrency().getCurrencyCode().equals("XXX")) {
return "Parse failed; got " + actual + ", but expected " + tuple.output;
}
if (tuple.output.equals("fail")) {
return null;
}
BigDecimal expectedNumber = new BigDecimal(tuple.output);
if (expectedNumber.compareTo(new BigDecimal(actual.getNumber().toString())) != 0) {
return "Wrong number: Expected: " + expectedNumber + ", got: " + actual;

View File

@ -6017,4 +6017,14 @@ public class NumberFormatTest extends TestFmwk {
df.setParseStrict(true);
expect2(df, -51.42, "-US$ 51.42");
}
@Test
public void testCaseSensitiveCustomIsoCurrency() {
DecimalFormat df = new DecimalFormat("¤¤0", DecimalFormatSymbols.getInstance(ULocale.ENGLISH));
df.setCurrency(Currency.getInstance("ICU"));
ParsePosition ppos = new ParsePosition(0);
df.parseCurrency("icu123", ppos);
assertEquals("Should fail to parse", 0, ppos.getIndex());
assertEquals("Should fail to parse", 0, ppos.getErrorIndex());
}
}