+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2012, International Business Machines Corporation and
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/* Modification History:
#if !UCONFIG_NO_FORMATTING
#include "numfmtst.h"
+#include "unicode/currpinf.h"
#include "unicode/dcfmtsym.h"
#include "unicode/decimfmt.h"
#include "unicode/localpointer.h"
#include "unicode/ustring.h"
#include "unicode/measfmt.h"
#include "unicode/curramt.h"
-#include "digitlst.h"
+#include "unicode/strenum.h"
#include "textfile.h"
#include "tokiter.h"
#include "charstr.h"
+#include "cstr.h"
#include "putilimp.h"
#include "winnmtst.h"
+#include <cmath>
#include <float.h>
#include <string.h>
#include <stdlib.h>
+#include "cmemory.h"
#include "cstring.h"
#include "unicode/numsys.h"
+#include "fmtableimp.h"
+#include "numberformattesttuple.h"
+#include "unicode/msgfmt.h"
+#include "number_decimalquantity.h"
+#include "unicode/numberformatter.h"
+
+#if (U_PLATFORM == U_PF_AIX) || (U_PLATFORM == U_PF_OS390)
+// These should not be macros. If they are,
+// replace them with std::isnan and std::isinf
+#if defined(isnan)
+#undef isnan
+namespace std {
+ bool isnan(double x) {
+ return _isnan(x);
+ }
+}
+#endif
+#if defined(isinf)
+#undef isinf
+namespace std {
+ bool isinf(double x) {
+ return _isinf(x);
+ }
+}
+#endif
+#endif
+
+using icu::number::impl::DecimalQuantity;
+using namespace icu::number;
//#define NUMFMTST_CACHE_DEBUG 1
#include "stdio.h" /* for sprintf */
//#define NUMFMTST_DEBUG 1
-#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof(array[0]))
-
static const UChar EUR[] = {69,85,82,0}; // "EUR"
static const UChar ISO_CURRENCY_USD[] = {0x55, 0x53, 0x44, 0}; // "USD"
+
// *****************************************************************************
// class NumberFormatTest
// *****************************************************************************
-#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
-
#define CHECK(status,str) if (U_FAILURE(status)) { errcheckln(status, UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); return; }
#define CHECK_DATA(status,str) if (U_FAILURE(status)) { dataerrln(UnicodeString("FAIL: ") + str + " - " + u_errorName(status)); return; }
void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
{
- // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
- switch (index) {
- CASE(0,TestCurrencySign);
- CASE(1,TestCurrency);
- CASE(2,TestParse);
- CASE(3,TestRounding487);
- CASE(4,TestQuotes);
- CASE(5,TestExponential);
- CASE(6,TestPatterns);
-
- // Upgrade to alphaWorks - liu 5/99
- CASE(7,TestExponent);
- CASE(8,TestScientific);
- CASE(9,TestPad);
- CASE(10,TestPatterns2);
- CASE(11,TestSecondaryGrouping);
- CASE(12,TestSurrogateSupport);
- CASE(13,TestAPI);
-
- CASE(14,TestCurrencyObject);
- CASE(15,TestCurrencyPatterns);
- //CASE(16,TestDigitList);
- CASE(16,TestWhiteSpaceParsing);
- CASE(17,TestComplexCurrency); // This test removed because CLDR no longer uses choice formats in currency symbols.
- CASE(18,TestRegCurrency);
- CASE(19,TestSymbolsWithBadLocale);
- CASE(20,TestAdoptDecimalFormatSymbols);
-
- CASE(21,TestScientific2);
- CASE(22,TestScientificGrouping);
- CASE(23,TestInt64);
-
- CASE(24,TestPerMill);
- CASE(25,TestIllegalPatterns);
- CASE(26,TestCases);
-
- CASE(27,TestCurrencyNames);
- CASE(28,TestCurrencyAmount);
- CASE(29,TestCurrencyUnit);
- CASE(30,TestCoverage);
- CASE(31,TestJB3832);
- CASE(32,TestHost);
- CASE(33,TestHostClone);
- CASE(34,TestCurrencyFormat);
- CASE(35,TestRounding);
- CASE(36,TestNonpositiveMultiplier);
- CASE(37,TestNumberingSystems);
- CASE(38,TestSpaceParsing);
- CASE(39,TestMultiCurrencySign);
- CASE(40,TestCurrencyFormatForMixParsing);
- CASE(41,TestDecimalFormatCurrencyParse);
- CASE(42,TestCurrencyIsoPluralFormat);
- CASE(43,TestCurrencyParsing);
- CASE(44,TestParseCurrencyInUCurr);
- CASE(45,TestFormatAttributes);
- CASE(46,TestFieldPositionIterator);
- CASE(47,TestDecimal);
- CASE(48,TestCurrencyFractionDigits);
- CASE(49,TestExponentParse);
- CASE(50,TestExplicitParents);
- CASE(51,TestLenientParse);
- CASE(52,TestAvailableNumberingSystems);
- CASE(53,TestRoundingPattern);
- CASE(54,Test9087);
- default: name = ""; break;
- }
+ TESTCASE_AUTO_BEGIN;
+ TESTCASE_AUTO(TestCurrencySign);
+ TESTCASE_AUTO(TestCurrency);
+ TESTCASE_AUTO(TestParse);
+ TESTCASE_AUTO(TestRounding487);
+ TESTCASE_AUTO(TestQuotes);
+ TESTCASE_AUTO(TestExponential);
+ TESTCASE_AUTO(TestPatterns);
+
+ // Upgrade to alphaWorks - liu 5/99
+ TESTCASE_AUTO(TestExponent);
+ TESTCASE_AUTO(TestScientific);
+ TESTCASE_AUTO(TestPad);
+ TESTCASE_AUTO(TestPatterns2);
+ TESTCASE_AUTO(TestSecondaryGrouping);
+ TESTCASE_AUTO(TestSurrogateSupport);
+ TESTCASE_AUTO(TestAPI);
+
+ TESTCASE_AUTO(TestCurrencyObject);
+ TESTCASE_AUTO(TestCurrencyPatterns);
+ //TESTCASE_AUTO(TestDigitList);
+ TESTCASE_AUTO(TestWhiteSpaceParsing);
+ TESTCASE_AUTO(TestComplexCurrency); // This test removed because CLDR no longer uses choice formats in currency symbols.
+ TESTCASE_AUTO(TestRegCurrency);
+ TESTCASE_AUTO(TestSymbolsWithBadLocale);
+ TESTCASE_AUTO(TestAdoptDecimalFormatSymbols);
+
+ TESTCASE_AUTO(TestScientific2);
+ TESTCASE_AUTO(TestScientificGrouping);
+ TESTCASE_AUTO(TestInt64);
+
+ TESTCASE_AUTO(TestPerMill);
+ TESTCASE_AUTO(TestIllegalPatterns);
+ TESTCASE_AUTO(TestCases);
+
+ TESTCASE_AUTO(TestCurrencyNames);
+ TESTCASE_AUTO(TestCurrencyAmount);
+ TESTCASE_AUTO(TestCurrencyUnit);
+ TESTCASE_AUTO(TestCoverage);
+ //TESTCASE_AUTO(TestLocalizedPatternSymbolCoverage);
+ TESTCASE_AUTO(TestJB3832);
+ TESTCASE_AUTO(TestHost);
+ TESTCASE_AUTO(TestHostClone);
+ TESTCASE_AUTO(TestCurrencyFormat);
+ TESTCASE_AUTO(TestRounding);
+ TESTCASE_AUTO(TestNonpositiveMultiplier);
+ TESTCASE_AUTO(TestNumberingSystems);
+ TESTCASE_AUTO(TestSpaceParsing);
+ TESTCASE_AUTO(TestMultiCurrencySign);
+ TESTCASE_AUTO(TestCurrencyFormatForMixParsing);
+ //TESTCASE_AUTO(TestMismatchedCurrencyFormatFail);
+ TESTCASE_AUTO(TestDecimalFormatCurrencyParse);
+ TESTCASE_AUTO(TestCurrencyIsoPluralFormat);
+ TESTCASE_AUTO(TestCurrencyParsing);
+ TESTCASE_AUTO(TestParseCurrencyInUCurr);
+ TESTCASE_AUTO(TestFormatAttributes);
+ TESTCASE_AUTO(TestFieldPositionIterator);
+ TESTCASE_AUTO(TestDecimal);
+ TESTCASE_AUTO(TestCurrencyFractionDigits);
+ TESTCASE_AUTO(TestExponentParse);
+ TESTCASE_AUTO(TestExplicitParents);
+ TESTCASE_AUTO(TestLenientParse);
+ TESTCASE_AUTO(TestAvailableNumberingSystems);
+ TESTCASE_AUTO(TestRoundingPattern);
+ TESTCASE_AUTO(Test9087);
+ TESTCASE_AUTO(TestFormatFastpaths);
+ TESTCASE_AUTO(TestFormattableSize);
+ TESTCASE_AUTO(TestUFormattable);
+ TESTCASE_AUTO(TestSignificantDigits);
+ TESTCASE_AUTO(TestShowZero);
+ TESTCASE_AUTO(TestCompatibleCurrencies);
+ TESTCASE_AUTO(TestBug9936);
+ TESTCASE_AUTO(TestParseNegativeWithFaLocale);
+ TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
+ TESTCASE_AUTO(TestCustomCurrencySignAndSeparator);
+ TESTCASE_AUTO(TestParseSignsAndMarks);
+ TESTCASE_AUTO(Test10419RoundingWith0FractionDigits);
+ TESTCASE_AUTO(Test10468ApplyPattern);
+ TESTCASE_AUTO(TestRoundingScientific10542);
+ TESTCASE_AUTO(TestZeroScientific10547);
+ TESTCASE_AUTO(TestAccountingCurrency);
+ TESTCASE_AUTO(TestEquality);
+ TESTCASE_AUTO(TestCurrencyUsage);
+ TESTCASE_AUTO(TestDoubleLimit11439);
+ TESTCASE_AUTO(TestGetAffixes);
+ TESTCASE_AUTO(TestToPatternScientific11648);
+ TESTCASE_AUTO(TestBenchmark);
+ TESTCASE_AUTO(TestCtorApplyPatternDifference);
+ TESTCASE_AUTO(TestFractionalDigitsForCurrency);
+ TESTCASE_AUTO(TestFormatCurrencyPlural);
+ TESTCASE_AUTO(Test11868);
+ TESTCASE_AUTO(Test11739_ParseLongCurrency);
+ //TESTCASE_AUTO(Test13035_MultiCodePointPaddingInPattern);
+ TESTCASE_AUTO(Test13737_ParseScientificStrict);
+ TESTCASE_AUTO(Test10727_RoundingZero);
+ TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
+ TESTCASE_AUTO(Test11475_signRecognition);
+ TESTCASE_AUTO(Test11640_getAffixes);
+ TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
+ TESTCASE_AUTO(Test13327_numberingSystemBufferOverflow);
+ TESTCASE_AUTO(Test13391_chakmaParsing);
+ TESTCASE_AUTO(Test11735_ExceptionIssue);
+ TESTCASE_AUTO(Test11035_FormatCurrencyAmount);
+ TESTCASE_AUTO(Test11318_DoubleConversion);
+ TESTCASE_AUTO(TestParsePercentRegression);
+ TESTCASE_AUTO(TestMultiplierWithScale);
+ TESTCASE_AUTO(TestFastFormatInt32);
+ TESTCASE_AUTO(Test11646_Equality);
+ TESTCASE_AUTO(TestParseNaN);
+ TESTCASE_AUTO(Test11897_LocalizedPatternSeparator);
+ TESTCASE_AUTO(Test13055_PercentageRounding);
+ TESTCASE_AUTO(Test11839);
+ TESTCASE_AUTO(Test10354);
+ TESTCASE_AUTO(Test11645_ApplyPatternEquality);
+ TESTCASE_AUTO(Test12567);
+ TESTCASE_AUTO(Test11626_CustomizeCurrencyPluralInfo);
+ TESTCASE_AUTO(Test13056_GroupingSize);
+ TESTCASE_AUTO(Test11025_CurrencyPadding);
+ TESTCASE_AUTO(Test11648_ExpDecFormatMalPattern);
+ //TESTCASE_AUTO(Test11649_DecFmtCurrencies);
+ TESTCASE_AUTO(Test13148_ParseGroupingSeparators);
+ TESTCASE_AUTO(Test12753_PatternDecimalPoint);
+ TESTCASE_AUTO(Test11647_PatternCurrencySymbols);
+ TESTCASE_AUTO(Test11913_BigDecimal);
+ TESTCASE_AUTO(Test11020_RoundingInScientificNotation);
+ TESTCASE_AUTO(Test11640_TripleCurrencySymbol);
+ TESTCASE_AUTO(Test13763_FieldPositionIteratorOffset);
+ TESTCASE_AUTO(Test13777_ParseLongNameNonCurrencyMode);
+ TESTCASE_AUTO(Test13804_EmptyStringsWhenParsing);
+ TESTCASE_AUTO_END;
}
// -------------------------------------
}
if(test != NULL) {
test->setMinimumIntegerDigits(10);
- test->setMaximumIntegerDigits(2);
+ test->setMaximumIntegerDigits(1);
test->setMinimumFractionDigits(10);
- test->setMaximumFractionDigits(2);
+ test->setMaximumFractionDigits(1);
UnicodeString result;
FieldPosition pos;
result.remove();
int64_t ll = 12;
test->format(ll, result);
- if (result != "12.00"){
- errln("format int64_t error");
- }
+ assertEquals("format int64_t error", u"2.0", result);
+
+ test->setMinimumIntegerDigits(4);
+ test->setMinimumFractionDigits(4);
+
+ result.remove();
+ test->format(ll, result);
+ assertEquals("format int64_t error", u"0,012.0000", result);
ParsePosition ppos;
LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
}
}
-class StubNumberForamt :public NumberFormat{
+class StubNumberFormat :public NumberFormat{
public:
- StubNumberForamt(){};
+ StubNumberFormat(){};
virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
return appendTo;
}
void
NumberFormatTest::TestCoverage(void){
- StubNumberForamt stub;
+ StubNumberFormat stub;
UnicodeString agent("agent");
FieldPosition pos;
int64_t num = 4;
};
}
+void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
+ IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
+ // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
+ DecimalFormatSymbols dfs(errorCode);
+ dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
+ dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
+ dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
+ dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
+ dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
+ dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
+ dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
+ dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
+ dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
+ dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
+ dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
+ dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');
+
+ {
+ UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
+ UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");
+
+ DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
+ df1.applyPattern(standardPattern, errorCode);
+ DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
+ df2.applyLocalizedPattern(localizedPattern, errorCode);
+ assertTrue("DecimalFormat instances should be equal", df1 == df2);
+ UnicodeString p2;
+ assertEquals("toPattern should match on localizedPattern instance",
+ standardPattern, df2.toPattern(p2));
+ UnicodeString lp1;
+ assertEquals("toLocalizedPattern should match on standardPattern instance",
+ localizedPattern, df1.toLocalizedPattern(lp1));
+ }
+
+ {
+ UnicodeString standardPattern(u"* @@@E0‰");
+ UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");
+
+ DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
+ df1.applyPattern(standardPattern, errorCode);
+ DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
+ df2.applyLocalizedPattern(localizedPattern, errorCode);
+ assertTrue("DecimalFormat instances should be equal", df1 == df2);
+ UnicodeString p2;
+ assertEquals("toPattern should match on localizedPattern instance",
+ standardPattern, df2.toPattern(p2));
+ UnicodeString lp1;
+ assertEquals("toLocalizedPattern should match on standardPattern instance",
+ localizedPattern, df1.toLocalizedPattern(lp1));
+ }
+}
+
// Test various patterns
void
NumberFormatTest::TestPatterns(void)
if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }
const char* pat[] = { "#.#", "#.", ".#", "#" };
- int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
- const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
+ int32_t pat_length = UPRV_LENGTHOF(pat);
+ const char* newpat[] = { "#0.#", "#0.", "#.0", "#" }; // use ICU 61 behavior
const char* num[] = { "0", "0.", ".0", "0" };
for (int32_t i=0; i<pat_length; ++i)
{
DecimalFormatSymbols sym(Locale::getUS(), status);
if (U_FAILURE(status)) { errcheckln(status, "FAIL: Bad status returned by DecimalFormatSymbols ct - %s", u_errorName(status)); return; }
const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
- int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
+ int32_t pat_length = UPRV_LENGTHOF(pat);
// The following #if statements allow this test to be built and run on
// platforms that do not have standard IEEE numerics. For example,
#if DBL_MAX_10_EXP > 300
double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
- int32_t val_length = (int32_t)(sizeof(val) / sizeof(val[0]));
+ int32_t val_length = UPRV_LENGTHOF(val);
const char* valFormat[] =
{
// 0.####E0
};
#elif DBL_MAX_10_EXP > 70
double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
- int32_t val_length = sizeof(val) / sizeof(val[0]);
+ int32_t val_length = UPRV_LENGTHOF(val);
char* valFormat[] =
{
// 0.####E0
#endif
int32_t lval[] = { 0, -1, 1, 123456789 };
- int32_t lval_length = (int32_t)(sizeof(lval) / sizeof(lval[0]));
+ int32_t lval_length = UPRV_LENGTHOF(lval);
const char* lvalFormat[] =
{
// 0.####E0
#endif
}
else {
- errln((UnicodeString)"FAIL: Non-numeric Formattable returned");
+ errln(UnicodeString("FAIL: Non-numeric Formattable returned: ") + pattern + " " + s);
continue;
}
if (pos.getIndex() == s.length())
(uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
(!useEpsilon && a != valParse[v+ival]))
{
- errln((UnicodeString)"FAIL: Expected " + valParse[v+ival]);
+ errln((UnicodeString)"FAIL: Expected " + valParse[v+ival] + " but got " + a
+ + " on input " + s);
}
}
else {
{
logln((UnicodeString)" -parse-> " + a);
if (a != lvalParse[v+ilval])
- errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval]);
+ errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval] + " but got " + a);
}
else
errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
// jb 2552
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("##0.00E0",status);
- if (U_SUCCESS(status)) {
+ if (assertSuccess("", status, true, __FILE__, __LINE__)) {
expect(fmt, .01234, "12.3E-3");
expect(fmt, .1234, "123E-3");
expect(fmt, 1.234, "1.23E0");
NumberFormatTest::TestInt64() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormat fmt("#.#E0",status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
fmt.setMaximumFractionDigits(20);
if (U_SUCCESS(status)) {
expect(fmt, (Formattable)(int64_t)0, "0E0");
// -------------------------------------
static const char* testCases[][2]= {
/* locale ID */ /* expected */
- {"ca_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+ {"ca_ES_PREEURO", "\\u20A7\\u00A01.150" },
{"de_LU_PREEURO", "1,150\\u00A0F" },
{"el_GR_PREEURO", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
{"en_BE_PREEURO", "1.150,50\\u00A0BEF" },
{"es_ES_PREEURO", "1.150\\u00A0\\u20A7" },
- {"eu_ES_PREEURO", "1.150\\u00A0\\u20A7" },
+ {"eu_ES_PREEURO", "\\u20A7\\u00A01.150" },
{"gl_ES_PREEURO", "1.150\\u00A0\\u20A7" },
{"it_IT_PREEURO", "ITL\\u00A01.150" },
- {"pt_PT_PREEURO", "1,150$50\\u00A0Esc."},
+ {"pt_PT_PREEURO", "1,150$50\\u00A0\\u200B"}, // per cldrbug 7670
{"en_US@currency=JPY", "\\u00A51,150"},
{"en_US@currency=jpy", "\\u00A51,150"},
{"en-US-u-cu-jpy", "\\u00A51,150"}
UnicodeString s; currencyFmt->format(1.50, s);
logln((UnicodeString)"Un pauvre ici a..........." + s);
if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
- errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$");
+ errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
delete currencyFmt;
s.truncate(0);
char loc[256]={0};
int len = uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
+ (void)len; // Suppress unused variable warning.
currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
currencyFmt->format(1.50, s);
logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
- if (!(s==CharsToUnicodeString("1,50\\u00A0DEM")))
- errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DEM");
+ if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
+ errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
delete currencyFmt;
s.truncate(0);
len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
if (U_FAILURE(status))
errln((UnicodeString)"FAIL: Status " + (int32_t)status);
- for(int i=0; i < (int)(sizeof(testCases)/sizeof(testCases[i])); i++){
+ for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
status = U_ZERO_ERROR;
const char *localeID = testCases[i][0];
UnicodeString expected(testCases[i][1], -1, US_INV);
1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
expectCurrency(*fmt, Locale("fr", "CH", ""),
- 1234.56, "CHF1,234.55"); // 0.05 rounding
+ 1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548 // use ICU 61 behavior
expectCurrency(*fmt, Locale::getUS(),
1234.56, "$1,234.56");
expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
expectCurrency(*fmt, Locale::getJapan(),
- 1234.56, CharsToUnicodeString("1 235 \\u00A5JP")); // Yen
+ 1234.56, CharsToUnicodeString("1 235 JPY")); // Yen
expectCurrency(*fmt, Locale("fr", "CH", ""),
- 1234.56, "1 234,55 CHF"); // 0.05 rounding
+ 1234.56, "1 234,56 CHF"); // no more 0.05 rounding here, see cldrbug 5548
expectCurrency(*fmt, Locale::getUS(),
1234.56, "1 234,56 $US");
static const char *lenientMinusTestCases[] = {
"-5",
"\\u22125",
- "\\u20105"
+ "\\u27965"
};
static const char *lenientCurrencyTestCases[] = {
"1000.00"
};
+// changed from () to - per cldrbug 5674
static const char *lenientNegativeCurrencyTestCases[] = {
- "($1,000)",
- "($ 1,000)",
- "($1000)",
- "($ 1000)",
- "($1 000.00)",
- "($ 1 000.00)",
- "( $ 1,000.00 )",
- "($ 1\\u00A0000.00)",
- "(1000.00)"
+ "-$1,000",
+ "-$ 1,000",
+ "-$1000",
+ "-$ 1000",
+ "-$1 000.00",
+ "-$ 1 000.00",
+ "- $ 1,000.00 ",
+ "-$ 1\\u00A0000.00",
+ "-1000.00"
};
static const char *lenientPercentTestCases[] = {
"1,000,.0"
};
-#define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
-
/**
* Test lenient parsing.
*/
dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
} else {
format->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE (lenientAffixTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
UnicodeString testCase = ctou(lenientAffixTestCases[t]);
format->parse(testCase, n, status);
if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
n.getLong() != 1) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t] + (UnicodeString) "\"");
+ dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
Locale en_US("en_US");
Locale sv_SE("sv_SE");
-
+
NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);
-
+
if (mFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
} else {
mFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
UnicodeString testCase = ctou(lenientMinusTestCases[t]);
-
+
mFormat->parse(testCase, n, status);
logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-
+
if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
delete mFormat;
}
-
+
mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);
-
+
if (mFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
} else {
mFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
UnicodeString testCase = ctou(lenientMinusTestCases[t]);
-
+
mFormat->parse(testCase, n, status);
logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
-
+
if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
delete mFormat;
}
-
+
NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);
if (cFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
} else {
cFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
cFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
n.getLong() != 1000) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
- for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativeCurrencyTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
cFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
n.getLong() != -1000) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
} else {
pFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
UnicodeString testCase = ctou(lenientPercentTestCases[t]);
pFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
n.getDouble() != 0.25) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status)
+ + "; got: " + n.getDouble(status));
status = U_ZERO_ERROR;
}
}
- for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativePercentTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
pFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
n.getDouble() != -0.25) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status)
+ + "; got: " + n.getDouble(status));
status = U_ZERO_ERROR;
}
}
// Test cases that should fail with a strict parse and pass with a
// lenient parse.
NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
-
+
if (nFormat == NULL || U_FAILURE(status)) {
dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
- } else {
+ } else {
// first, make sure that they fail with a strict parse
- for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
UnicodeString testCase = ctou(strictFailureTestCases[t]);
nFormat->parse(testCase, n, status);
logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
if (! U_FAILURE(status)) {
- errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
}
status = U_ZERO_ERROR;
// then, make sure that they pass with a lenient parse
nFormat->setLenient(TRUE);
- for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
+ for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
UnicodeString testCase = ctou(strictFailureTestCases[t]);
nFormat->parse(testCase, n, status);
if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
n.getLong() != 1000) {
- errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
+ errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
+ + (UnicodeString) "\"; error code = " + u_errorName(status));
status = U_ZERO_ERROR;
}
}
CHECK(status, "DecimalFormat ct");
expect2(f, (int32_t)123456789L, "12,34,56,789");
- expectPat(f, "#,##,###");
+ expectPat(f, "#,##,###"); // use ICU 61 behavior
f.applyPattern("#,###", status);
CHECK(status, "applyPattern");
f.setSecondaryGroupingSize(4);
expect2(f, (int32_t)123456789L, "12,3456,789");
- expectPat(f, "#,####,###");
+ expectPat(f, "#,####,###"); // use ICU 61 behavior
NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
CHECK_DATA(status, "createInstance(hi_IN)");
errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
return;
}
+ // From ICU 62, flexible whitespace needs lenient mode
+ fmt.setLenient(TRUE);
int32_t n = 1234;
expect(fmt, "a b1234c ", n);
expect(fmt, "a b1234c ", n);
// Test pattern round-trip
const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
"0.###E0;[0.###E0]" };
- int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
+ int32_t PAT_length = UPRV_LENGTHOF(PAT);
int32_t DIGITS[] = {
// min int, max int, min frac, max frac
- 0, 1, 0, 0, // "#E0"
+ 0, 1, 0, 0, // "#E0" // expect ICU 61 behavior
1, 1, 0, 4, // "0.####E0"
2, 2, 3, 3, // "00.000E00"
1, 3, 0, 4, // "##0.####E000"
fmt.setFormatWidth(16);
// 12 34567890123456
- expectPat(fmt, "AA*^#,###,##0.00ZZ");
+ expectPat(fmt, "AA*^#,###,##0.00ZZ"); // use ICU 61 behavior
}
void NumberFormatTest::TestSurrogateSupport(void) {
const UBool possibleDataError = TRUE;
// Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
// THE LOCALE DATA before diving into the code.
- assertEquals("USD.getName(SYMBOL_NAME)",
+ assertEquals("USD.getName(SYMBOL_NAME, en)",
UnicodeString("$"),
UnicodeString(ucurr_getName(USD, "en",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("USD.getName(LONG_NAME)",
+ assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
+ UnicodeString("$"),
+ UnicodeString(ucurr_getName(USD, "en",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USD.getName(LONG_NAME, en)",
UnicodeString("US Dollar"),
UnicodeString(ucurr_getName(USD, "en",
UCURR_LONG_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("CAD.getName(SYMBOL_NAME)",
+ assertEquals("CAD.getName(SYMBOL_NAME, en)",
UnicodeString("CA$"),
UnicodeString(ucurr_getName(CAD, "en",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("CAD.getName(SYMBOL_NAME)",
+ assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
+ UnicodeString("$"),
+ UnicodeString(ucurr_getName(CAD, "en",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
UnicodeString("$"),
UnicodeString(ucurr_getName(CAD, "en_CA",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("USD.getName(SYMBOL_NAME) in en_AU",
+ assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
UnicodeString("US$"),
- UnicodeString(ucurr_getName(USD, "en_AU",
+ UnicodeString(ucurr_getName(USD, "en_CA",
+ UCURR_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
+ UnicodeString("$"),
+ UnicodeString(ucurr_getName(USD, "en_CA",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
+ UnicodeString("US$"),
+ UnicodeString(ucurr_getName(USD, "en_NZ",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
assertEquals("CAD.getName(SYMBOL_NAME)",
UnicodeString("CA$"),
- UnicodeString(ucurr_getName(CAD, "en_AU",
+ UnicodeString(ucurr_getName(CAD, "en_NZ",
+ UCURR_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
+ assertEquals("USX.getName(SYMBOL_NAME)",
+ UnicodeString("USX"),
+ UnicodeString(ucurr_getName(USX, "en_US",
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
+ assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
+ UnicodeString("USX"),
+ UnicodeString(ucurr_getName(USX, "en_US",
+ UCURR_NARROW_SYMBOL_NAME,
+ &isChoiceFormat, &len, &ec)),
+ possibleDataError);
assertEquals("USX.getName(LONG_NAME)",
UnicodeString("USX"),
UnicodeString(ucurr_getName(USX, "en_US",
void NumberFormatTest::TestCurrencyUnit(void){
UErrorCode ec = U_ZERO_ERROR;
- static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
+ static const UChar USD[] = u"USD";
+ static const char USD8[] = "USD";
+ static const UChar BAD[] = u"???";
+ static const UChar BAD2[] = u"??A";
+ static const UChar XXX[] = u"XXX";
+ static const char XXX8[] = "XXX";
CurrencyUnit cu(USD, ec);
assertSuccess("CurrencyUnit", ec);
- const UChar * r = cu.getISOCurrency(); // who is the buffer owner ?
- assertEquals("getISOCurrency()", USD, r);
+ assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
+ assertEquals("getSubtype()", USD8, cu.getSubtype());
CurrencyUnit cu2(cu);
if (!(cu2 == cu)){
if (!(*cu3 == cu)){
errln("CurrencyUnit cloned object should be same");
}
+ CurrencyUnit bad(BAD, ec);
+ assertSuccess("CurrencyUnit", ec);
+ if (cu.getIndex() == bad.getIndex()) {
+ errln("Indexes of different currencies should differ.");
+ }
+ CurrencyUnit bad2(BAD2, ec);
+ assertSuccess("CurrencyUnit", ec);
+ if (bad2.getIndex() != bad.getIndex()) {
+ errln("Indexes of unrecognized currencies should be the same.");
+ }
+ if (bad == bad2) {
+ errln("Different unrecognized currencies should not be equal.");
+ }
+ bad = bad2;
+ if (bad != bad2) {
+ errln("Currency unit assignment should be the same.");
+ }
delete cu3;
+
+ // Test default constructor
+ CurrencyUnit def;
+ assertEquals("Default currency", XXX, def.getISOCurrency());
+ assertEquals("Default currency as subtype", XXX8, def.getSubtype());
+
+ // Test slicing
+ MeasureUnit sliced1 = cu;
+ MeasureUnit sliced2 = cu;
+ assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
+ assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
+ CurrencyUnit restored1(sliced1, ec);
+ CurrencyUnit restored2(sliced2, ec);
+ assertSuccess("Restoring from MeasureUnit", ec);
+ assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
+ assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
+ assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
+ assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());
+
+ // Test copy constructor failure
+ LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
+ assertSuccess("Creating meter", ec);
+ CurrencyUnit failure(*meter, ec);
+ assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
+ assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
}
void NumberFormatTest::TestCurrencyAmount(void){
}; // expect U_USING_DEFAULT_WARNING for both
unsigned int i;
- for (i = 0; i < sizeof(badLocales) / sizeof(char*); i++) {
+ for (i = 0; i < UPRV_LENGTHOF(badLocales); i++) {
const char *localeName = badLocales[i];
Locale locBad(localeName);
+ TEST_ASSERT_TRUE(!locBad.isBogus());
UErrorCode status = U_ZERO_ERROR;
UnicodeString intlCurrencySymbol((UChar)0xa4);
DecimalFormat fmt(ctou("###.###\\u2030"), ec);
if (!assertSuccess("DecimalFormat ct", ec)) return;
assertEquals("0.4857 x ###.###\\u2030",
- ctou("485.7\\u2030"), fmt.format(0.4857, str));
+ ctou("485.7\\u2030"), fmt.format(0.4857, str), true);
DecimalFormatSymbols sym(Locale::getUS(), ec);
+ if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
+ return;
+ }
sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
DecimalFormat fmt2("", sym, ec);
+ if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
+ return;
+ }
fmt2.applyLocalizedPattern("###.###m", ec);
if (!assertSuccess("setup", ec)) return;
str.truncate(0);
if (!tokens.next(tok, ec)) goto error;
continue;
}
+ } else if (mfmt == NULL) {
+ errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
+ if (!tokens.next(tok, ec)) goto error;
+ if (!tokens.next(tok, ec)) goto error;
+ if (!tokens.next(tok, ec)) goto error;
+ continue;
}
// fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
if (!tokens.next(currAmt, ec)) goto error;
}
void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
- const UnicodeString& exp,
+ const UnicodeString& exp, UBool rt,
UErrorCode status) {
if (fmt == NULL || U_FAILURE(status)) {
dataerrln("FAIL: NumberFormat constructor");
} else {
- expect(*fmt, n, exp);
+ expect(*fmt, n, exp, rt);
}
delete fmt;
}
", expected " + pos + " " + width + " " + pad);
}
}
+
+// This test is flaky b/c the symbols for CNY and JPY are equivalent in this locale - FIXME
+void NumberFormatTest::TestCompatibleCurrencies() {
+/*
+ static const UChar JPY[] = {0x4A, 0x50, 0x59, 0};
+ static const UChar CNY[] = {0x43, 0x4E, 0x59, 0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createCurrencyInstance(Locale::getUS(), status));
+ if (U_FAILURE(status)) {
+ errln("Could not create number format instance.");
+ return;
+ }
+ logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmt, JPY, 1235, "\\u00A51,235");
+ logln("%s:%d - testing parse of fullwidth yen sign\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmt, JPY, 1235, "\\uFFE51,235");
+ logln("%s:%d - testing parse of halfwidth yen sign\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmt, CNY, 1235, "CN\\u00A51,235");
+
+ LocalPointer<NumberFormat> fmtTW(
+ NumberFormat::createCurrencyInstance(Locale::getTaiwan(), status));
+
+ logln("%s:%d - testing parse of halfwidth yen sign in TW\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmtTW, CNY, 1235, "\\u00A51,235");
+ logln("%s:%d - testing parse of fullwidth yen sign in TW\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmtTW, CNY, 1235, "\\uFFE51,235");
+
+ LocalPointer<NumberFormat> fmtJP(
+ NumberFormat::createCurrencyInstance(Locale::getJapan(), status));
+
+ logln("%s:%d - testing parse of halfwidth yen sign in JP\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmtJP, JPY, 1235, "\\u00A51,235");
+ logln("%s:%d - testing parse of fullwidth yen sign in JP\n", __FILE__, __LINE__);
+ expectParseCurrency(*fmtJP, JPY, 1235, "\\uFFE51,235");
+
+ // more..
+*/
+}
+
+void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
+ ParsePosition ppos;
+ UnicodeString utext = ctou(text);
+ LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
+ if (!ppos.getIndex()) {
+ errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
+ return;
+ }
+ UErrorCode status = U_ZERO_ERROR;
+
+ char theInfo[100];
+ sprintf(theInfo, "For locale %s, string \"%s\", currency ",
+ fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
+ text);
+ u_austrcpy(theInfo+uprv_strlen(theInfo), currency);
+
+ char theOperation[100];
+
+ uprv_strcpy(theOperation, theInfo);
+ uprv_strcat(theOperation, ", check amount:");
+ assertTrue(theOperation, amount == currencyAmount->getNumber().getDouble(status));
+
+ uprv_strcpy(theOperation, theInfo);
+ uprv_strcat(theOperation, ", check currency:");
+ assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
+}
+
+
void NumberFormatTest::TestJB3832(){
const char* localeID = "pt_PT@currency=PTE";
Locale loc(localeID);
UErrorCode status = U_ZERO_ERROR;
- UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0Esc."));
+ UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
UnicodeString s;
NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
if(U_FAILURE(status)){
UDate now = Calendar::getNow();
NumberFormat *full = NumberFormat::createInstance(loc, status);
if (full == NULL || U_FAILURE(status)) {
- dataerrln("FAIL: Can't create Relative date instance - %s", u_errorName(status));
+ dataerrln("FAIL: Can't create NumberFormat date instance - %s", u_errorName(status));
return;
}
UnicodeString result1;
}
MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
+ if (U_FAILURE(status)){
+ dataerrln("FAIL: MeasureFormat::createCurrencyFormat status %s", u_errorName(status));
+ return;
+ }
Locale::setDefault( saveDefaultLocale, status );
if (U_FAILURE(status)){
- dataerrln("FAIL: Status %s", u_errorName(status));
+ dataerrln("FAIL: Locale::setDefault status %s", u_errorName(status));
return;
}
cloneObj = (MeasureFormat *)measureObj->clone();
{ (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
{ (UnicodeString)"#50", 1230, (UnicodeString)"1250" }
};
- int32_t numOfTests = (sizeof(tests)/sizeof(tests[0]));
+ int32_t numOfTests = UPRV_LENGTHOF(tests);
UnicodeString result;
DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
delete foo;
return;
}
- for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
ParsePosition parsePosition(0);
UnicodeString stringToBeParsed = ctou(DATA[i].stringToParse);
int parsedPosition = DATA[i].parsedPos;
foo->setLenient(DATA[i].lenient);
Formattable result;
foo->parse(stringToBeParsed, result, parsePosition);
+ logln("Parsing: " + stringToBeParsed);
if (parsePosition.getIndex() != parsedPosition ||
parsePosition.getErrorIndex() != errorIndex) {
errln("FAILED parse " + stringToBeParsed + "; lenient: " + DATA[i].lenient + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
{ "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
{ "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
{ "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
- { "ar_EG", 1234.567, FALSE, "\\u0661\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
+ { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
{ "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
{ "ar_MA", 1234.567, FALSE, "1.234,567" },
{ "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
{ "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
{ "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
{ "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
- { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C4\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
+ { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
{ NULL, 0, FALSE, NULL }
};
for (item = DATA; item->localeName != NULL; item++) {
ec = U_ZERO_ERROR;
Locale loc = Locale::createFromName(item->localeName);
- NumberFormat *fmt = NumberFormat::createInstance(loc,ec);
+ NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
if (U_FAILURE(ec)) {
dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
continue;
}
-
+ // Clone to test ticket #10682
+ NumberFormat *fmt = (NumberFormat *) origFmt->clone();
+ delete origFmt;
+
+
if (item->isRBNF) {
expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
} else {
// for US locale
{"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"},
{"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
- {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollar1.00"},
+ {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"},
// for CHINA locale
- {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\uFFE51,234.56", "CNY1,234.56", "\\u4EBA\\u6C11\\u5E011,234.56"},
- {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\uFFE51,234.56)", "(CNY1,234.56)", "(\\u4EBA\\u6C11\\u5E011,234.56)"},
- {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\uFFE51.00", "CNY1.00", "\\u4EBA\\u6C11\\u5E011.00"}
+ {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\u00A51,234.56", "CNY1,234.56", "\\u4EBA\\u6C11\\u5E011,234.56"},
+ {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\u00A51,234.56)", "(CNY1,234.56)", "(\\u4EBA\\u6C11\\u5E011,234.56)"},
+ {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\u00A51.00", "CNY1.00", "\\u4EBA\\u6C11\\u5E011.00"}
};
const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
UnicodeString tripleCurrencyStr(tripleCurrencySign);
- for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
const char* locale = DATA[i][0];
UnicodeString pat = ctou(DATA[i][1]);
double numberToBeFormat = atof(DATA[i][2]);
"$1,234.56", // string to be parsed
"USD1,234.56",
"US dollars1,234.56",
- "1,234.56 US dollars"
+ // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
};
const CurrencyAmount* curramt = NULL;
- for (uint32_t i = 0; i < sizeof(formats)/sizeof(formats[0]); ++i) {
+ for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
UnicodeString stringToBeParsed = ctou(formats[i]);
logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
Formattable result;
}
+/** Starting in ICU 62, strict mode is actually strict with currency formats. */
+void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
+ IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
+ LocalPointer<DecimalFormat> df(
+ dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
+ if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
+ UnicodeString pattern;
+ assertEquals("Test assumes that currency sign is at the beginning",
+ u"\u00A4#,##0.00",
+ df->toPattern(pattern));
+ // Should round-trip on the correct currency format:
+ expect2(*df, 1.23, u"XXX\u00A01.23");
+ df->setCurrency(u"EUR", status);
+ expect2(*df, 1.23, u"\u20AC1.23");
+ // Should parse with currency in the wrong place in lenient mode
+ df->setLenient(TRUE);
+ expect(*df, u"1.23\u20AC", 1.23);
+ expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
+ // Should NOT parse with currency in the wrong place in STRICT mode
+ df->setLenient(FALSE);
+ {
+ Formattable result;
+ ErrorCode failStatus;
+ df->parse(u"1.23\u20AC", result, failStatus);
+ assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
+ }
+ {
+ ParsePosition ppos;
+ df->parseCurrency(u"1.23\u20AC", ppos);
+ assertEquals("Should fail to parse currency", 0, ppos.getIndex());
+ }
+}
+
+
void
NumberFormatTest::TestDecimalFormatCurrencyParse() {
// Locale.US
{"USD1,234.56", "1234.56"},
{"1,234.56 US dollar", "1234.56"},
};
- for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ fmt->setLenient(TRUE);
+ for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
UnicodeString stringToBeParsed = ctou(DATA[i][0]);
double parsedResult = atof(DATA[i][1]);
UErrorCode status = U_ZERO_ERROR;
Formattable result;
fmt->parse(stringToBeParsed, result, status);
+ logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
if (U_FAILURE(status) ||
(result.getType() == Formattable::kDouble &&
result.getDouble() != parsedResult) ||
// 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", "USD1.00", "1.00 US dollars"},
{"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
- {"en_US", "-1234.56", "USD", "($1,234.56)", "(USD1,234.56)", "-1,234.56 US dollars"},
- {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00 \\u7F8E\\u5143"},
- {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56 \\u7F8E\\u5143"},
- // wrong ISO code {"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "1.00 CHY"},
- // wrong ISO code {"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"},
- {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4EBA\\u6C11\\u5E01"},
- {"zh_CN", "1234.56", "CNY", "\\uFFE51,234.56", "CNY1,234.56", "1,234.56 \\u4EBA\\u6C11\\u5E01"},
- {"ru_RU", "1", "RUB", "1,00\\u00A0\\u0440\\u0443\\u0431.", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"},
- {"ru_RU", "2", "RUB", "2,00\\u00A0\\u0440\\u0443\\u0431.", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0445 \\u0440\\u0443\\u0431\\u043B\\u044F"},
- {"ru_RU", "5", "RUB", "5,00\\u00A0\\u0440\\u0443\\u0431.", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0445 \\u0440\\u0443\\u0431\\u043B\\u0435\\u0439"},
+ {"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
+ {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00\\u7F8E\\u5143"},
+ {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56\\u7F8E\\u5143"},
+ {"zh_CN", "1", "CNY", "\\u00A51.00", "CNY1.00", "1.00\\u4EBA\\u6C11\\u5E01"},
+ {"zh_CN", "1234.56", "CNY", "\\u00A51,234.56", "CNY1,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"},
+ {"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
+ {"ru_RU", "2", "RUB", "2,00\\u00A0\\u20BD", "2,00\\u00A0RUB", "2,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
+ {"ru_RU", "5", "RUB", "5,00\\u00A0\\u20BD", "5,00\\u00A0RUB", "5,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"},
// test locale without currency information
{"root", "-1.23", "USD", "-US$\\u00A01.23", "-USD\\u00A01.23", "-1.23 USD"},
// test choice format
- {"es_AR", "1", "INR", "\\u20B91,00", "INR1,00", "1,00 rupia india"},
+ {"es_AR", "1", "INR", "INR\\u00A01,00", "INR\\u00A01,00", "1,00 rupia india"},
};
static const UNumberFormatStyle currencyStyles[] = {
UNUM_CURRENCY,
UNUM_CURRENCY_PLURAL
};
- for (int32_t i=0; i<LENGTHOF(DATA); ++i) {
- for (int32_t kIndex = 0; kIndex < LENGTHOF(currencyStyles); ++kIndex) {
+ for (int32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
+ const char* localeString = DATA[i][0];
+ double numberToBeFormat = atof(DATA[i][1]);
+ const char* currencyISOCode = DATA[i][2];
+ logln(UnicodeString(u"Locale: ") + localeString + "; amount: " + numberToBeFormat);
+ Locale locale(localeString);
+ for (int32_t kIndex = 0; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
UNumberFormatStyle k = currencyStyles[kIndex];
- const char* localeString = DATA[i][0];
- double numberToBeFormat = atof(DATA[i][1]);
- const char* currencyISOCode = DATA[i][2];
- Locale locale(localeString);
+ logln(UnicodeString(u"UNumberFormatStyle: ") + k);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
if (U_FAILURE(status)) {
errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
}
// test parsing, and test parsing for all currency formats.
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ numFmt->setLenient(TRUE);
for (int j = 3; j < 6; ++j) {
// DATA[i][3] is the currency format result using
// CURRENCYSTYLE formatter.
// format result using CURRENCYSTYLE,
// format result using ISOCURRENCYSTYLE,
// format result using PLURALCURRENCYSTYLE,
- {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
- {"pa_IN", "1", "USD", "US$\\u00a0\\u0a67.\\u0a66\\u0a66", "USD\\u00a0\\u0a67.\\u0a66\\u0a66", "\\u0a67.\\u0a66\\u0a66 USD"},
- {"es_AR", "1", "USD", "US$1,00", "USD1,00", "1,00 d\\u00f3lar estadounidense"},
+ {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
+ {"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", "\\u06f1\\u066b\\u06f0\\u06f0\\u00a0US$", "\\u06f1\\u066b\\u06f0\\u06f0\\u00a0USD", "\\u06f1\\u066b\\u06f0\\u06f0\\u0020\\u062f\\u0644\\u0627\\u0631\\u0020\\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
- {"he_IL", "1", "USD", "1.00\\u00a0US$", "1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
- {"hr_HR", "1", "USD", "1,00\\u00a0$", "1,00\\u00a0USD", "1,00 Ameri\\u010dki dolar"},
- {"id_ID", "1", "USD", "US$1,00", "USD1,00", "1,00 Dolar Amerika Serikat"},
- {"it_IT", "1", "USD", "US$\\u00a01,00", "USD\\u00a01,00", "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", "CNY1.00", "1.00 \\u4EBA\\u6C11\\u5E01"},
- {"zh_TW", "1", "CNY", "\\uFFE51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
- {"ru_RU", "1", "RUB", "1,00\\u00A0\\u0440\\u0443\\u0431.", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"},
+ {"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\\u010Dkih dolara"},
+ {"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 dollari statunitensi"},
+ {"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\\u7c73\\u30c9\\u30eb"},
+ {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY\\u00A001.00", "1.00\\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 \\u65E5\\u5713"},
+ {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u5186"},
+ // ICU 62 requires #parseCurrency() to recognize variants when parsing
+ // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
+ {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
};
static const UNumberFormatStyle currencyStyles[] = {
UNUM_CURRENCY,
UNUM_CURRENCY_ISO,
UNUM_CURRENCY_PLURAL
};
+ static const char* currencyStyleNames[] = {
+ "UNUM_CURRENCY",
+ "UNUM_CURRENCY_ISO",
+ "UNUM_CURRENCY_PLURAL"
+ };
#ifdef NUMFMTST_CACHE_DEBUG
int deadloop = 0;
for (;;) {
printf("loop: %d\n", deadloop++);
#endif
- for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
- for (int32_t kIndex = 0; kIndex < LENGTHOF(currencyStyles); ++kIndex) {
- UNumberFormatStyle k = currencyStyles[kIndex];
+ for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) { /* i = test case # - should be i=0*/
+ for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
+ UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
const char* localeString = DATA[i][0];
double numberToBeFormat = atof(DATA[i][1]);
const char* currencyISOCode = DATA[i][2];
Locale locale(localeString);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
+ logln("#%d NumberFormat(%s, %s) Currency=%s\n",
+ i, localeString, currencyStyleNames[kIndex],
+ currencyISOCode);
+
if (U_FAILURE(status)) {
delete numFmt;
dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
continue;
}
- /*
UnicodeString strBuf;
numFmt->format(numberToBeFormat, strBuf);
int resultDataIndex = 3 + kIndex;
if (strBuf.compare(formatResult)) {
errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
}
- */
// test parsing, and test parsing for all currency formats.
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ numFmt->setLenient(TRUE);
for (int j = 3; j < 6; ++j) {
// DATA[i][3] is the currency format result using
// CURRENCYSTYLE formatter.
UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
UErrorCode status = U_ZERO_ERROR;
Formattable parseResult;
+ logln("parse(%s)", DATA[i][j]);
numFmt->parse(oneCurrencyFormatResult, parseResult, status);
if (U_FAILURE(status) ||
(parseResult.getType() == Formattable::kDouble &&
parseResult.getDouble() != numberToBeFormat) ||
(parseResult.getType() == Formattable::kLong &&
parseResult.getLong() != numberToBeFormat)) {
- errln((UnicodeString)"FAIL: getCurrencyFormat of locale " +
- localeString + " failed roundtripping the number" +
- "(i,k,j): " + i + ", " + k + ", " + j);
+ errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
+ "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+". Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
if (parseResult.getType() == Formattable::kDouble) {
- errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getDouble());
+ errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
} else {
- errln((UnicodeString)"expected: " + numberToBeFormat + "; actual: " +parseResult.getLong());
+ errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
}
+ errln((UnicodeString)" round-trip would be: " + strBuf);
}
}
delete numFmt;
"US dollar1.00",
"US dollars1.00",
"$1.00",
- "AU$1.00",
+ "A$1.00",
"ADP1.00",
"ADP1.00",
"AED1.00",
"AZM1.00",
"AZM1.00",
"AZN1.00",
- "Afghan Afghani (1927-2002)1.00",
- "Afghan afghani (1927-2002)1.00",
+ "Afghan Afghani (1927\\u20132002)1.00",
+ "Afghan afghani (1927\\u20132002)1.00",
"Afghan Afghani1.00",
"Afghan Afghanis1.00",
"Albanian Lek1.00",
"Andorran Peseta1.00",
"Andorran peseta1.00",
"Andorran pesetas1.00",
- "Angolan Kwanza (1977-1991)1.00",
- "Angolan Readjusted Kwanza (1995-1999)1.00",
+ "Angolan Kwanza (1977\\u20131991)1.00",
+ "Angolan Readjusted Kwanza (1995\\u20131999)1.00",
"Angolan Kwanza1.00",
- "Angolan New Kwanza (1990-2000)1.00",
- "Angolan kwanza (1977-1991)1.00",
- "Angolan readjusted kwanza (1995-1999)1.00",
+ "Angolan New Kwanza (1990\\u20132000)1.00",
+ "Angolan kwanza (1977\\u20131991)1.00",
+ "Angolan readjusted kwanza (1995\\u20131999)1.00",
"Angolan kwanza1.00",
- "Angolan kwanzas (1977-1991)1.00",
- "Angolan readjusted kwanzas (1995-1999)1.00",
+ "Angolan kwanzas (1977\\u20131991)1.00",
+ "Angolan readjusted kwanzas (1995\\u20131999)1.00",
"Angolan kwanzas1.00",
- "Angolan new kwanza (1990-2000)1.00",
- "Angolan new kwanzas (1990-2000)1.00",
+ "Angolan new kwanza (1990\\u20132000)1.00",
+ "Angolan new kwanzas (1990\\u20132000)1.00",
"Argentine Austral1.00",
- "Argentine Peso (1983-1985)1.00",
+ "Argentine Peso (1983\\u20131985)1.00",
"Argentine Peso1.00",
"Argentine austral1.00",
"Argentine australs1.00",
- "Argentine peso (1983-1985)1.00",
+ "Argentine peso (1983\\u20131985)1.00",
"Argentine peso1.00",
- "Argentine pesos (1983-1985)1.00",
+ "Argentine pesos (1983\\u20131985)1.00",
"Argentine pesos1.00",
"Armenian Dram1.00",
"Armenian dram1.00",
"Austrian Schilling1.00",
"Austrian schilling1.00",
"Austrian schillings1.00",
- "Azerbaijani Manat (1993-2006)1.00",
+ "Azerbaijani Manat (1993\\u20132006)1.00",
"Azerbaijani Manat1.00",
- "Azerbaijani manat (1993-2006)1.00",
+ "Azerbaijani manat (1993\\u20132006)1.00",
"Azerbaijani manat1.00",
- "Azerbaijani manats (1993-2006)1.00",
+ "Azerbaijani manats (1993\\u20132006)1.00",
"Azerbaijani manats1.00",
"BAD1.00",
"BAD1.00",
"Barbadian Dollar1.00",
"Barbadian dollar1.00",
"Barbadian dollars1.00",
- "Belarusian New Ruble (1994-1999)1.00",
+ "Belarusian Ruble (1994\\u20131999)1.00",
"Belarusian Ruble1.00",
- "Belarusian new ruble (1994-1999)1.00",
- "Belarusian new rubles (1994-1999)1.00",
+ "Belarusian ruble (1994\\u20131999)1.00",
+ "Belarusian rubles (1994\\u20131999)1.00",
"Belarusian ruble1.00",
"Belarusian rubles1.00",
"Belgian Franc (convertible)1.00",
"Bolivian Boliviano1.00",
"Bolivian Bolivianos1.00",
"Bosnia-Herzegovina Convertible Mark1.00",
- "Bosnia-Herzegovina Dinar (1992-1994)1.00",
+ "Bosnia-Herzegovina Dinar (1992\\u20131994)1.00",
"Bosnia-Herzegovina convertible mark1.00",
"Bosnia-Herzegovina convertible marks1.00",
- "Bosnia-Herzegovina dinar (1992-1994)1.00",
- "Bosnia-Herzegovina dinars (1992-1994)1.00",
+ "Bosnia-Herzegovina dinar (1992\\u20131994)1.00",
+ "Bosnia-Herzegovina dinars (1992\\u20131994)1.00",
"Botswanan Pula1.00",
"Botswanan pula1.00",
"Botswanan pulas1.00",
- "Brazilian New Cruzado (1989-1990)1.00",
- "Brazilian Cruzado (1986-1989)1.00",
- "Brazilian Cruzeiro (1990-1993)1.00",
- "Brazilian New Cruzeiro (1967-1986)1.00",
- "Brazilian Cruzeiro (1993-1994)1.00",
+ "Brazilian New Cruzado (1989\\u20131990)1.00",
+ "Brazilian Cruzado (1986\\u20131989)1.00",
+ "Brazilian Cruzeiro (1990\\u20131993)1.00",
+ "Brazilian New Cruzeiro (1967\\u20131986)1.00",
+ "Brazilian Cruzeiro (1993\\u20131994)1.00",
"Brazilian Real1.00",
- "Brazilian new cruzado (1989-1990)1.00",
- "Brazilian new cruzados (1989-1990)1.00",
- "Brazilian cruzado (1986-1989)1.00",
- "Brazilian cruzados (1986-1989)1.00",
- "Brazilian cruzeiro (1990-1993)1.00",
- "Brazilian new cruzeiro (1967-1986)1.00",
- "Brazilian cruzeiro (1993-1994)1.00",
- "Brazilian cruzeiros (1990-1993)1.00",
- "Brazilian new cruzeiros (1967-1986)1.00",
- "Brazilian cruzeiros (1993-1994)1.00",
+ "Brazilian new cruzado (1989\\u20131990)1.00",
+ "Brazilian new cruzados (1989\\u20131990)1.00",
+ "Brazilian cruzado (1986\\u20131989)1.00",
+ "Brazilian cruzados (1986\\u20131989)1.00",
+ "Brazilian cruzeiro (1990\\u20131993)1.00",
+ "Brazilian new cruzeiro (1967\\u20131986)1.00",
+ "Brazilian cruzeiro (1993\\u20131994)1.00",
+ "Brazilian cruzeiros (1990\\u20131993)1.00",
+ "Brazilian new cruzeiros (1967\\u20131986)1.00",
+ "Brazilian cruzeiros (1993\\u20131994)1.00",
"Brazilian real1.00",
"Brazilian reals1.00",
- "British Pound Sterling1.00",
- "British pound sterling1.00",
- "British pounds sterling1.00",
+ "British Pound1.00",
+ "British pound1.00",
+ "British pounds1.00",
"Brunei Dollar1.00",
"Brunei dollar1.00",
"Brunei dollars1.00",
"CAD1.00",
"CDF1.00",
"CDF1.00",
- "CFA Franc BCEAO1.00",
- "CFA Franc BEAC1.00",
- "CFA franc BCEAO1.00",
- "CFA franc BEAC1.00",
- "CFA francs BCEAO1.00",
- "CFA francs BEAC1.00",
+ "West African CFA Franc1.00",
+ "Central African CFA Franc1.00",
+ "West African CFA franc1.00",
+ "Central African CFA franc1.00",
+ "West African CFA francs1.00",
+ "Central African CFA francs1.00",
"CFP Franc1.00",
"CFP franc1.00",
"CFP francs1.00",
"Cypriot Pound1.00",
"Cypriot pound1.00",
"Cypriot pounds1.00",
- "Czech Republic Koruna1.00",
- "Czech Republic koruna1.00",
- "Czech Republic korunas1.00",
+ "Czech Koruna1.00",
+ "Czech koruna1.00",
+ "Czech korunas1.00",
"Czechoslovak Hard Koruna1.00",
"Czechoslovak hard koruna1.00",
"Czechoslovak hard korunas1.00",
"Georgian kupon larits1.00",
"Georgian lari1.00",
"Georgian laris1.00",
- "Ghanaian Cedi (1979-2007)1.00",
+ "Ghanaian Cedi (1979\\u20132007)1.00",
"Ghanaian Cedi1.00",
- "Ghanaian cedi (1979-2007)1.00",
+ "Ghanaian cedi (1979\\u20132007)1.00",
"Ghanaian cedi1.00",
- "Ghanaian cedis (1979-2007)1.00",
+ "Ghanaian cedis (1979\\u20132007)1.00",
"Ghanaian cedis1.00",
"Gibraltar Pound1.00",
"Gibraltar pound1.00",
"Irish pound1.00",
"Irish pounds1.00",
"Israeli Pound1.00",
- "Israeli new sheqel1.00",
+ "Israeli new shekel1.00",
"Israeli pound1.00",
"Israeli pounds1.00",
"Italian Lira1.00",
"Mauritian rupee1.00",
"Mauritian rupees1.00",
"Mexican Peso1.00",
- "Mexican Silver Peso (1861-1992)1.00",
+ "Mexican Silver Peso (1861\\u20131992)1.00",
"Mexican Investment Unit1.00",
"Mexican peso1.00",
"Mexican pesos1.00",
- "Mexican silver peso (1861-1992)1.00",
- "Mexican silver pesos (1861-1992)1.00",
+ "Mexican silver peso (1861\\u20131992)1.00",
+ "Mexican silver pesos (1861\\u20131992)1.00",
"Mexican investment unit1.00",
"Mexican investment units1.00",
"Moldovan Leu1.00",
"Mozambican escudos1.00",
"Mozambican metical1.00",
"Mozambican meticals1.00",
- "Myanma Kyat1.00",
- "Myanma kyat1.00",
- "Myanma kyats1.00",
+ "Myanmar Kyat1.00",
+ "Myanmar kyat1.00",
+ "Myanmar kyats1.00",
"NAD1.00",
"NGN1.00",
"NIC1.00",
"Dutch Guilder1.00",
"Dutch guilder1.00",
"Dutch guilders1.00",
- "Israeli New Sheqel1.00",
- "Israeli New Sheqels1.00",
+ "Israeli New Shekel1.00",
+ "Israeli New Shekels1.00",
"New Zealand Dollar1.00",
"New Zealand dollar1.00",
"New Zealand dollars1.00",
"Nicaraguan C\\u00f3rdoba1.00",
- "Nicaraguan C\\u00f3rdoba (1988-1991)1.00",
+ "Nicaraguan C\\u00f3rdoba (1988\\u20131991)1.00",
"Nicaraguan c\\u00f3rdoba1.00",
"Nicaraguan c\\u00f3rdobas1.00",
- "Nicaraguan c\\u00f3rdoba (1988-1991)1.00",
- "Nicaraguan c\\u00f3rdobas (1988-1991)1.00",
+ "Nicaraguan c\\u00f3rdoba (1988\\u20131991)1.00",
+ "Nicaraguan c\\u00f3rdobas (1988\\u20131991)1.00",
"Nigerian Naira1.00",
"Nigerian naira1.00",
"Nigerian nairas1.00",
"Norwegian krone1.00",
"Norwegian kroner1.00",
"OMR1.00",
- "Mozambican Metical (1980-2006)1.00",
- "Mozambican metical (1980-2006)1.00",
- "Mozambican meticals (1980-2006)1.00",
- "Romanian Lei (1952-2006)1.00",
- "Romanian Leu (1952-2006)1.00",
- "Romanian leu (1952-2006)1.00",
- "Serbian Dinar (2002-2006)1.00",
- "Serbian dinar (2002-2006)1.00",
- "Serbian dinars (2002-2006)1.00",
- "Sudanese Dinar (1992-2007)1.00",
- "Sudanese Pound (1957-1998)1.00",
- "Sudanese dinar (1992-2007)1.00",
- "Sudanese dinars (1992-2007)1.00",
- "Sudanese pound (1957-1998)1.00",
- "Sudanese pounds (1957-1998)1.00",
- "Turkish Lira (1922-2005)1.00",
- "Turkish Lira (1922-2005)1.00",
+ "Mozambican Metical (1980\\u20132006)1.00",
+ "Mozambican metical (1980\\u20132006)1.00",
+ "Mozambican meticals (1980\\u20132006)1.00",
+ "Romanian Lei (1952\\u20132006)1.00",
+ "Romanian Leu (1952\\u20132006)1.00",
+ "Romanian leu (1952\\u20132006)1.00",
+ "Serbian Dinar (2002\\u20132006)1.00",
+ "Serbian dinar (2002\\u20132006)1.00",
+ "Serbian dinars (2002\\u20132006)1.00",
+ "Sudanese Dinar (1992\\u20132007)1.00",
+ "Sudanese Pound (1957\\u20131998)1.00",
+ "Sudanese dinar (1992\\u20132007)1.00",
+ "Sudanese dinars (1992\\u20132007)1.00",
+ "Sudanese pound (1957\\u20131998)1.00",
+ "Sudanese pounds (1957\\u20131998)1.00",
+ "Turkish Lira (1922\\u20132005)1.00",
+ "Turkish Lira (1922\\u20132005)1.00",
"Omani Rial1.00",
"Omani rial1.00",
"Omani rials1.00",
"Paraguayan guarani1.00",
"Paraguayan guaranis1.00",
"Peruvian Inti1.00",
- "Peruvian Nuevo Sol1.00",
- "Peruvian Sol (1863-1965)1.00",
+ "Peruvian Sol1.00",
+ "Peruvian Sol (1863\\u20131965)1.00",
"Peruvian inti1.00",
"Peruvian intis1.00",
- "Peruvian nuevo sol1.00",
- "Peruvian nuevos soles1.00",
- "Peruvian sol (1863-1965)1.00",
- "Peruvian soles (1863-1965)1.00",
- "Philippine Peso1.00",
- "Philippine peso1.00",
- "Philippine pesos1.00",
+ "Peruvian sol1.00",
+ "Peruvian soles1.00",
+ "Peruvian sol (1863\\u20131965)1.00",
+ "Peruvian soles (1863\\u20131965)1.00",
+ "Philippine Piso1.00",
+ "Philippine piso1.00",
+ "Philippine pisos1.00",
"Platinum1.00",
"Platinum1.00",
- "Polish Zloty (1950-1995)1.00",
+ "Polish Zloty (1950\\u20131995)1.00",
"Polish Zloty1.00",
"Polish zlotys1.00",
"Polish zloty (PLZ)1.00",
"RSD1.00",
"RSD1.00",
"RUB1.00",
- "RUB1.00",
"RUR1.00",
"RUR1.00",
"RWF1.00",
"Romanian Leu1.00",
"Romanian lei1.00",
"Romanian leu1.00",
- "Russian Ruble (1991-1998)1.00",
+ "Russian Ruble (1991\\u20131998)1.00",
"Russian Ruble1.00",
- "Russian ruble (1991-1998)1.00",
+ "Russian ruble (1991\\u20131998)1.00",
"Russian ruble1.00",
- "Russian rubles (1991-1998)1.00",
+ "Russian rubles (1991\\u20131998)1.00",
"Russian rubles1.00",
"Rwandan Franc1.00",
"Rwandan franc1.00",
"SVC1.00",
"SYP1.00",
"SZL1.00",
- "Saint Helena Pound1.00",
- "Saint Helena pound1.00",
- "Saint Helena pounds1.00",
- "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe Dobra1.00",
- "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobra1.00",
- "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobras1.00",
+ "St. Helena Pound1.00",
+ "St. Helena pound1.00",
+ "St. Helena pounds1.00",
+ "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra1.00",
+ "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra1.00",
+ "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras1.00",
"Saudi Riyal1.00",
"Saudi riyal1.00",
"Saudi riyals1.00",
"Tongan Pa\\u02bbanga1.00",
"Tongan pa\\u02bbanga1.00",
"Tongan pa\\u02bbanga1.00",
- "Trinidad and Tobago Dollar1.00",
- "Trinidad and Tobago dollar1.00",
- "Trinidad and Tobago dollars1.00",
+ "Trinidad & Tobago Dollar1.00",
+ "Trinidad & Tobago dollar1.00",
+ "Trinidad & Tobago dollars1.00",
"Tunisian Dinar1.00",
"Tunisian dinar1.00",
"Tunisian dinars1.00",
"UYU1.00",
"UZS1.00",
"UZS1.00",
- "Ugandan Shilling (1966-1987)1.00",
+ "Ugandan Shilling (1966\\u20131987)1.00",
"Ugandan Shilling1.00",
- "Ugandan shilling (1966-1987)1.00",
+ "Ugandan shilling (1966\\u20131987)1.00",
"Ugandan shilling1.00",
- "Ugandan shillings (1966-1987)1.00",
+ "Ugandan shillings (1966\\u20131987)1.00",
"Ugandan shillings1.00",
"Ukrainian Hryvnia1.00",
"Ukrainian Karbovanets1.00",
"Colombian Real Value Unit1.00",
"United Arab Emirates Dirham1.00",
"Unknown Currency1.00",
- "Uruguayan Peso (1975-1993)1.00",
+ "Uruguayan Peso (1975\\u20131993)1.00",
"Uruguayan Peso1.00",
"Uruguayan Peso (Indexed Units)1.00",
- "Uruguayan peso (1975-1993)1.00",
+ "Uruguayan peso (1975\\u20131993)1.00",
"Uruguayan peso (indexed units)1.00",
"Uruguayan peso1.00",
- "Uruguayan pesos (1975-1993)1.00",
+ "Uruguayan pesos (1975\\u20131993)1.00",
"Uruguayan pesos (indexed units)1.00",
"Uruguayan pesos1.00",
- "Uzbekistan Som1.00",
- "Uzbekistan som1.00",
- "Uzbekistan som1.00",
+ "Uzbekistani Som1.00",
+ "Uzbekistani som1.00",
+ "Uzbekistani som1.00",
"VEB1.00",
"VEF1.00",
"VND1.00",
"Vanuatu vatu1.00",
"Vanuatu vatus1.00",
"Venezuelan Bol\\u00edvar1.00",
- "Venezuelan Bol\\u00edvar (1871-2008)1.00",
+ "Venezuelan Bol\\u00edvar (1871\\u20132008)1.00",
"Venezuelan bol\\u00edvar1.00",
"Venezuelan bol\\u00edvars1.00",
- "Venezuelan bol\\u00edvar (1871-2008)1.00",
- "Venezuelan bol\\u00edvars (1871-2008)1.00",
+ "Venezuelan bol\\u00edvar (1871\\u20132008)1.00",
+ "Venezuelan bol\\u00edvars (1871\\u20132008)1.00",
"Vietnamese Dong1.00",
"Vietnamese dong1.00",
"Vietnamese dong1.00",
"Yemeni dinars1.00",
"Yemeni rial1.00",
"Yemeni rials1.00",
- "Yugoslavian Convertible Dinar (1990-1992)1.00",
- "Yugoslavian Hard Dinar (1966-1990)1.00",
- "Yugoslavian New Dinar (1994-2002)1.00",
- "Yugoslavian convertible dinar (1990-1992)1.00",
- "Yugoslavian convertible dinars (1990-1992)1.00",
- "Yugoslavian hard dinar (1966-1990)1.00",
- "Yugoslavian hard dinars (1966-1990)1.00",
- "Yugoslavian new dinar (1994-2002)1.00",
- "Yugoslavian new dinars (1994-2002)1.00",
+ "Yugoslavian Convertible Dinar (1990\\u20131992)1.00",
+ "Yugoslavian Hard Dinar (1966\\u20131990)1.00",
+ "Yugoslavian New Dinar (1994\\u20132002)1.00",
+ "Yugoslavian convertible dinar (1990\\u20131992)1.00",
+ "Yugoslavian convertible dinars (1990\\u20131992)1.00",
+ "Yugoslavian hard dinar (1966\\u20131990)1.00",
+ "Yugoslavian hard dinars (1966\\u20131990)1.00",
+ "Yugoslavian new dinar (1994\\u20132002)1.00",
+ "Yugoslavian new dinars (1994\\u20132002)1.00",
"ZAL1.00",
"ZAL1.00",
"ZAR1.00",
"ZRZ1.00",
"ZRZ1.00",
"ZWD1.00",
- "Zairean New Zaire (1993-1998)1.00",
- "Zairean Zaire (1971-1993)1.00",
- "Zairean new zaire (1993-1998)1.00",
- "Zairean new zaires (1993-1998)1.00",
- "Zairean zaire (1971-1993)1.00",
- "Zairean zaires (1971-1993)1.00",
+ "Zairean New Zaire (1993\\u20131998)1.00",
+ "Zairean Zaire (1971\\u20131993)1.00",
+ "Zairean new zaire (1993\\u20131998)1.00",
+ "Zairean new zaires (1993\\u20131998)1.00",
+ "Zairean zaire (1971\\u20131993)1.00",
+ "Zairean zaires (1971\\u20131993)1.00",
"Zambian Kwacha1.00",
"Zambian kwacha1.00",
"Zambian kwachas1.00",
- "Zimbabwean Dollar (1980-2008)1.00",
- "Zimbabwean dollar (1980-2008)1.00",
- "Zimbabwean dollars (1980-2008)1.00",
+ "Zimbabwean Dollar (1980\\u20132008)1.00",
+ "Zimbabwean dollar (1980\\u20132008)1.00",
+ "Zimbabwean dollars (1980\\u20132008)1.00",
"euro1.00",
"euros1.00",
- "Turkish lira (1922-2005)1.00",
+ "Turkish lira (1922\\u20132005)1.00",
"special drawing rights1.00",
"Colombian real value unit1.00",
"Colombian real value units1.00",
"unknown currency1.00",
"\\u00a31.00",
"\\u00a51.00",
- "\\u0e3f1.00",
"\\u20ab1.00",
"\\u20aa1.00",
"\\u20ac1.00",
"1.00 US dollars random",
"1.00 Afghan Afghani random",
"1.00 Afghan Afghani random",
- "1.00 Afghan Afghanis (1927-1992) random",
+ "1.00 Afghan Afghanis (1927\\u20131992) random",
"1.00 Afghan Afghanis random",
"1.00 Albanian Lek random",
"1.00 Albanian lek random",
"1.00 Andorran Peseta random",
"1.00 Andorran peseta random",
"1.00 Andorran pesetas random",
- "1.00 Angolan Kwanza (1977-1990) random",
- "1.00 Angolan Readjusted Kwanza (1995-1999) random",
+ "1.00 Angolan Kwanza (1977\\u20131990) random",
+ "1.00 Angolan Readjusted Kwanza (1995\\u20131999) random",
"1.00 Angolan Kwanza random",
- "1.00 Angolan New Kwanza (1990-2000) random",
- "1.00 Angolan kwanza (1977-1991) random",
- "1.00 Angolan readjusted kwanza (1995-1999) random",
+ "1.00 Angolan New Kwanza (1990\\u20132000) random",
+ "1.00 Angolan kwanza (1977\\u20131991) random",
+ "1.00 Angolan readjusted kwanza (1995\\u20131999) random",
"1.00 Angolan kwanza random",
- "1.00 Angolan kwanzas (1977-1991) random",
- "1.00 Angolan readjusted kwanzas (1995-1999) random",
+ "1.00 Angolan kwanzas (1977\\u20131991) random",
+ "1.00 Angolan readjusted kwanzas (1995\\u20131999) random",
"1.00 Angolan kwanzas random",
- "1.00 Angolan new kwanza (1990-2000) random",
- "1.00 Angolan new kwanzas (1990-2000) random",
+ "1.00 Angolan new kwanza (1990\\u20132000) random",
+ "1.00 Angolan new kwanzas (1990\\u20132000) random",
"1.00 Argentine Austral random",
- "1.00 Argentine Peso (1983-1985) random",
+ "1.00 Argentine Peso (1983\\u20131985) random",
"1.00 Argentine Peso random",
"1.00 Argentine austral random",
"1.00 Argentine australs random",
- "1.00 Argentine peso (1983-1985) random",
+ "1.00 Argentine peso (1983\\u20131985) random",
"1.00 Argentine peso random",
- "1.00 Argentine pesos (1983-1985) random",
+ "1.00 Argentine pesos (1983\\u20131985) random",
"1.00 Argentine pesos random",
"1.00 Armenian Dram random",
"1.00 Armenian dram random",
"1.00 Austrian Schilling random",
"1.00 Austrian schilling random",
"1.00 Austrian schillings random",
- "1.00 Azerbaijani Manat (1993-2006) random",
+ "1.00 Azerbaijani Manat (1993\\u20132006) random",
"1.00 Azerbaijani Manat random",
- "1.00 Azerbaijani manat (1993-2006) random",
+ "1.00 Azerbaijani manat (1993\\u20132006) random",
"1.00 Azerbaijani manat random",
- "1.00 Azerbaijani manats (1993-2006) random",
+ "1.00 Azerbaijani manats (1993\\u20132006) random",
"1.00 Azerbaijani manats random",
"1.00 Bahamian Dollar random",
"1.00 Bahamian dollar random",
"1.00 Barbadian Dollar random",
"1.00 Barbadian dollar random",
"1.00 Barbadian dollars random",
- "1.00 Belarusian New Ruble (1994-1999) random",
+ "1.00 Belarusian Ruble (1994\\u20131999) random",
"1.00 Belarusian Ruble random",
- "1.00 Belarusian new ruble (1994-1999) random",
- "1.00 Belarusian new rubles (1994-1999) random",
+ "1.00 Belarusian ruble (1994\\u20131999) random",
+ "1.00 Belarusian rubles (1994\\u20131999) random",
"1.00 Belarusian ruble random",
"1.00 Belarusian rubles random",
"1.00 Belgian Franc (convertible) random",
"1.00 Bolivian Boliviano random",
"1.00 Bolivian Bolivianos random",
"1.00 Bosnia-Herzegovina Convertible Mark random",
- "1.00 Bosnia-Herzegovina Dinar (1992-1994) random",
+ "1.00 Bosnia-Herzegovina Dinar (1992\\u20131994) random",
"1.00 Bosnia-Herzegovina convertible mark random",
"1.00 Bosnia-Herzegovina convertible marks random",
- "1.00 Bosnia-Herzegovina dinar (1992-1994) random",
- "1.00 Bosnia-Herzegovina dinars (1992-1994) random",
+ "1.00 Bosnia-Herzegovina dinar (1992\\u20131994) random",
+ "1.00 Bosnia-Herzegovina dinars (1992\\u20131994) random",
"1.00 Botswanan Pula random",
"1.00 Botswanan pula random",
"1.00 Botswanan pulas random",
- "1.00 Brazilian New Cruzado (1989-1990) random",
- "1.00 Brazilian Cruzado (1986-1989) random",
- "1.00 Brazilian Cruzeiro (1990-1993) random",
- "1.00 Brazilian New Cruzeiro (1967-1986) random",
- "1.00 Brazilian Cruzeiro (1993-1994) random",
+ "1.00 Brazilian New Cruzado (1989\\u20131990) random",
+ "1.00 Brazilian Cruzado (1986\\u20131989) random",
+ "1.00 Brazilian Cruzeiro (1990\\u20131993) random",
+ "1.00 Brazilian New Cruzeiro (1967\\u20131986) random",
+ "1.00 Brazilian Cruzeiro (1993\\u20131994) random",
"1.00 Brazilian Real random",
- "1.00 Brazilian new cruzado (1989-1990) random",
- "1.00 Brazilian new cruzados (1989-1990) random",
- "1.00 Brazilian cruzado (1986-1989) random",
- "1.00 Brazilian cruzados (1986-1989) random",
- "1.00 Brazilian cruzeiro (1990-1993) random",
- "1.00 Brazilian new cruzeiro (1967-1986) random",
- "1.00 Brazilian cruzeiro (1993-1994) random",
- "1.00 Brazilian cruzeiros (1990-1993) random",
- "1.00 Brazilian new cruzeiros (1967-1986) random",
- "1.00 Brazilian cruzeiros (1993-1994) random",
+ "1.00 Brazilian new cruzado (1989\\u20131990) random",
+ "1.00 Brazilian new cruzados (1989\\u20131990) random",
+ "1.00 Brazilian cruzado (1986\\u20131989) random",
+ "1.00 Brazilian cruzados (1986\\u20131989) random",
+ "1.00 Brazilian cruzeiro (1990\\u20131993) random",
+ "1.00 Brazilian new cruzeiro (1967\\u20131986) random",
+ "1.00 Brazilian cruzeiro (1993\\u20131994) random",
+ "1.00 Brazilian cruzeiros (1990\\u20131993) random",
+ "1.00 Brazilian new cruzeiros (1967\\u20131986) random",
+ "1.00 Brazilian cruzeiros (1993\\u20131994) random",
"1.00 Brazilian real random",
"1.00 Brazilian reals random",
- "1.00 British Pound Sterling random",
- "1.00 British pound sterling random",
- "1.00 British pounds sterling random",
+ "1.00 British Pound random",
+ "1.00 British pound random",
+ "1.00 British pounds random",
"1.00 Brunei Dollar random",
"1.00 Brunei dollar random",
"1.00 Brunei dollars random",
"1.00 Cypriot Pound random",
"1.00 Cypriot pound random",
"1.00 Cypriot pounds random",
- "1.00 Czech Republic Koruna random",
- "1.00 Czech Republic koruna random",
- "1.00 Czech Republic korunas random",
+ "1.00 Czech Koruna random",
+ "1.00 Czech koruna random",
+ "1.00 Czech korunas random",
"1.00 Czechoslovak Hard Koruna random",
"1.00 Czechoslovak hard koruna random",
"1.00 Czechoslovak hard korunas random",
"1.00 Georgian kupon larits random",
"1.00 Georgian lari random",
"1.00 Georgian laris random",
- "1.00 Ghanaian Cedi (1979-2007) random",
+ "1.00 Ghanaian Cedi (1979\\u20132007) random",
"1.00 Ghanaian Cedi random",
- "1.00 Ghanaian cedi (1979-2007) random",
+ "1.00 Ghanaian cedi (1979\\u20132007) random",
"1.00 Ghanaian cedi random",
- "1.00 Ghanaian cedis (1979-2007) random",
+ "1.00 Ghanaian cedis (1979\\u20132007) random",
"1.00 Ghanaian cedis random",
"1.00 Gibraltar Pound random",
"1.00 Gibraltar pound random",
"1.00 Irish pound random",
"1.00 Irish pounds random",
"1.00 Israeli Pound random",
- "1.00 Israeli new sheqel random",
+ "1.00 Israeli new shekel random",
"1.00 Israeli pound random",
"1.00 Israeli pounds random",
"1.00 Italian Lira random",
"1.00 Mauritian rupee random",
"1.00 Mauritian rupees random",
"1.00 Mexican Peso random",
- "1.00 Mexican Silver Peso (1861-1992) random",
+ "1.00 Mexican Silver Peso (1861\\u20131992) random",
"1.00 Mexican Investment Unit random",
"1.00 Mexican peso random",
"1.00 Mexican pesos random",
- "1.00 Mexican silver peso (1861-1992) random",
- "1.00 Mexican silver pesos (1861-1992) random",
+ "1.00 Mexican silver peso (1861\\u20131992) random",
+ "1.00 Mexican silver pesos (1861\\u20131992) random",
"1.00 Mexican investment unit random",
"1.00 Mexican investment units random",
"1.00 Moldovan Leu random",
"1.00 Mozambican escudos random",
"1.00 Mozambican metical random",
"1.00 Mozambican meticals random",
- "1.00 Myanma Kyat random",
- "1.00 Myanma kyat random",
- "1.00 Myanma kyats random",
+ "1.00 Myanmar Kyat random",
+ "1.00 Myanmar kyat random",
+ "1.00 Myanmar kyats random",
"1.00 Namibian Dollar random",
"1.00 Namibian dollar random",
"1.00 Namibian dollars random",
"1.00 Dutch Guilder random",
"1.00 Dutch guilder random",
"1.00 Dutch guilders random",
- "1.00 Israeli New Sheqel random",
- "1.00 Israeli new sheqels random",
+ "1.00 Israeli New Shekel random",
+ "1.00 Israeli new shekels random",
"1.00 New Zealand Dollar random",
"1.00 New Zealand dollar random",
"1.00 New Zealand dollars random",
"1.00 Nicaraguan C\\u00f3rdoba random",
- "1.00 Nicaraguan C\\u00f3rdoba (1988-1991) random",
+ "1.00 Nicaraguan C\\u00f3rdoba (1988\\u20131991) random",
"1.00 Nicaraguan c\\u00f3rdoba random",
"1.00 Nicaraguan c\\u00f3rdoba random",
- "1.00 Nicaraguan c\\u00f3rdoba (1988-1991) random",
- "1.00 Nicaraguan c\\u00f3rdobas (1988-1991) random",
+ "1.00 Nicaraguan c\\u00f3rdoba (1988\\u20131991) random",
+ "1.00 Nicaraguan c\\u00f3rdobas (1988\\u20131991) random",
"1.00 Nigerian Naira random",
"1.00 Nigerian naira random",
"1.00 Nigerian nairas random",
"1.00 Norwegian Krone random",
"1.00 Norwegian krone random",
"1.00 Norwegian kroner random",
- "1.00 Mozambican Metical (1980-2006) random",
- "1.00 Mozambican metical (1980-2006) random",
- "1.00 Mozambican meticals (1980-2006) random",
- "1.00 Romanian Lei (1952-2006) random",
- "1.00 Romanian Leu (1952-2006) random",
- "1.00 Romanian leu (1952-2006) random",
- "1.00 Serbian Dinar (2002-2006) random",
- "1.00 Serbian dinar (2002-2006) random",
- "1.00 Serbian dinars (2002-2006) random",
- "1.00 Sudanese Dinar (1992-2007) random",
- "1.00 Sudanese Pound (1957-1998) random",
- "1.00 Sudanese dinar (1992-2007) random",
- "1.00 Sudanese dinars (1992-2007) random",
- "1.00 Sudanese pound (1957-1998) random",
- "1.00 Sudanese pounds (1957-1998) random",
- "1.00 Turkish Lira (1922-2005) random",
- "1.00 Turkish Lira (1922-2005) random",
+ "1.00 Mozambican Metical (1980\\u20132006) random",
+ "1.00 Mozambican metical (1980\\u20132006) random",
+ "1.00 Mozambican meticals (1980\\u20132006) random",
+ "1.00 Romanian Lei (1952\\u20132006) random",
+ "1.00 Romanian Leu (1952\\u20132006) random",
+ "1.00 Romanian leu (1952\\u20132006) random",
+ "1.00 Serbian Dinar (2002\\u20132006) random",
+ "1.00 Serbian dinar (2002\\u20132006) random",
+ "1.00 Serbian dinars (2002\\u20132006) random",
+ "1.00 Sudanese Dinar (1992\\u20132007) random",
+ "1.00 Sudanese Pound (1957\\u20131998) random",
+ "1.00 Sudanese dinar (1992\\u20132007) random",
+ "1.00 Sudanese dinars (1992\\u20132007) random",
+ "1.00 Sudanese pound (1957\\u20131998) random",
+ "1.00 Sudanese pounds (1957\\u20131998) random",
+ "1.00 Turkish Lira (1922\\u20132005) random",
+ "1.00 Turkish Lira (1922\\u20132005) random",
"1.00 Omani Rial random",
"1.00 Omani rial random",
"1.00 Omani rials random",
"1.00 Paraguayan guarani random",
"1.00 Paraguayan guaranis random",
"1.00 Peruvian Inti random",
- "1.00 Peruvian Nuevo Sol random",
- "1.00 Peruvian Sol (1863-1965) random",
+ "1.00 Peruvian Sol random",
+ "1.00 Peruvian Sol (1863\\u20131965) random",
"1.00 Peruvian inti random",
"1.00 Peruvian intis random",
- "1.00 Peruvian nuevo sol random",
- "1.00 Peruvian nuevos soles random",
- "1.00 Peruvian sol (1863-1965) random",
- "1.00 Peruvian soles (1863-1965) random",
- "1.00 Philippine Peso random",
- "1.00 Philippine peso random",
- "1.00 Philippine pesos random",
+ "1.00 Peruvian sol random",
+ "1.00 Peruvian soles random",
+ "1.00 Peruvian sol (1863\\u20131965) random",
+ "1.00 Peruvian soles (1863\\u20131965) random",
+ "1.00 Philippine Piso random",
+ "1.00 Philippine piso random",
+ "1.00 Philippine pisos random",
"1.00 Platinum random",
"1.00 Platinum random",
- "1.00 Polish Zloty (1950-1995) random",
+ "1.00 Polish Zloty (1950\\u20131995) random",
"1.00 Polish Zloty random",
"1.00 Polish zlotys random",
"1.00 Polish zloty (PLZ) random",
"1.00 Romanian Leu random",
"1.00 Romanian lei random",
"1.00 Romanian leu random",
- "1.00 Russian Ruble (1991-1998) random",
+ "1.00 Russian Ruble (1991\\u20131998) random",
"1.00 Russian Ruble random",
- "1.00 Russian ruble (1991-1998) random",
+ "1.00 Russian ruble (1991\\u20131998) random",
"1.00 Russian ruble random",
- "1.00 Russian rubles (1991-1998) random",
+ "1.00 Russian rubles (1991\\u20131998) random",
"1.00 Russian rubles random",
"1.00 Rwandan Franc random",
"1.00 Rwandan franc random",
"1.00 Rwandan francs random",
- "1.00 Saint Helena Pound random",
- "1.00 Saint Helena pound random",
- "1.00 Saint Helena pounds random",
- "1.00 S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe Dobra random",
- "1.00 S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobra random",
- "1.00 S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe dobras random",
+ "1.00 St. Helena Pound random",
+ "1.00 St. Helena pound random",
+ "1.00 St. Helena pounds random",
+ "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobra random",
+ "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobra random",
+ "1.00 S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe dobras random",
"1.00 Saudi Riyal random",
"1.00 Saudi riyal random",
"1.00 Saudi riyals random",
"1.00 Timorese Escudo random",
"1.00 Timorese escudo random",
"1.00 Timorese escudos random",
- "1.00 Trinidad and Tobago Dollar random",
- "1.00 Trinidad and Tobago dollar random",
- "1.00 Trinidad and Tobago dollars random",
+ "1.00 Trinidad & Tobago Dollar random",
+ "1.00 Trinidad & Tobago dollar random",
+ "1.00 Trinidad & Tobago dollars random",
"1.00 Tunisian Dinar random",
"1.00 Tunisian dinar random",
"1.00 Tunisian dinars random",
"1.00 US dollars (next day) random",
"1.00 US dollars (same day) random",
"1.00 US dollars random",
- "1.00 Ugandan Shilling (1966-1987) random",
+ "1.00 Ugandan Shilling (1966\\u20131987) random",
"1.00 Ugandan Shilling random",
- "1.00 Ugandan shilling (1966-1987) random",
+ "1.00 Ugandan shilling (1966\\u20131987) random",
"1.00 Ugandan shilling random",
- "1.00 Ugandan shillings (1966-1987) random",
+ "1.00 Ugandan shillings (1966\\u20131987) random",
"1.00 Ugandan shillings random",
"1.00 Ukrainian Hryvnia random",
"1.00 Ukrainian Karbovanets random",
"1.00 Colombian Real Value Unit random",
"1.00 United Arab Emirates Dirham random",
"1.00 Unknown Currency random",
- "1.00 Uruguayan Peso (1975-1993) random",
+ "1.00 Uruguayan Peso (1975\\u20131993) random",
"1.00 Uruguayan Peso random",
"1.00 Uruguayan Peso (Indexed Units) random",
- "1.00 Uruguayan peso (1975-1993) random",
+ "1.00 Uruguayan peso (1975\\u20131993) random",
"1.00 Uruguayan peso (indexed units) random",
"1.00 Uruguayan peso random",
- "1.00 Uruguayan pesos (1975-1993) random",
+ "1.00 Uruguayan pesos (1975\\u20131993) random",
"1.00 Uruguayan pesos (indexed units) random",
- "1.00 Uzbekistan Som random",
- "1.00 Uzbekistan som random",
- "1.00 Uzbekistan som random",
+ "1.00 Uzbekistani Som random",
+ "1.00 Uzbekistani som random",
+ "1.00 Uzbekistani som random",
"1.00 Vanuatu Vatu random",
"1.00 Vanuatu vatu random",
"1.00 Vanuatu vatus random",
"1.00 Venezuelan Bol\\u00edvar random",
- "1.00 Venezuelan Bol\\u00edvar (1871-2008) random",
+ "1.00 Venezuelan Bol\\u00edvar (1871\\u20132008) random",
"1.00 Venezuelan bol\\u00edvar random",
"1.00 Venezuelan bol\\u00edvars random",
- "1.00 Venezuelan bol\\u00edvar (1871-2008) random",
- "1.00 Venezuelan bol\\u00edvars (1871-2008) random",
+ "1.00 Venezuelan bol\\u00edvar (1871\\u20132008) random",
+ "1.00 Venezuelan bol\\u00edvars (1871\\u20132008) random",
"1.00 Vietnamese Dong random",
"1.00 Vietnamese dong random",
"1.00 Vietnamese dong random",
"1.00 Yemeni dinars random",
"1.00 Yemeni rial random",
"1.00 Yemeni rials random",
- "1.00 Yugoslavian Convertible Dinar (1990-1992) random",
- "1.00 Yugoslavian Hard Dinar (1966-1990) random",
- "1.00 Yugoslavian New Dinar (1994-2002) random",
- "1.00 Yugoslavian convertible dinar (1990-1992) random",
- "1.00 Yugoslavian convertible dinars (1990-1992) random",
- "1.00 Yugoslavian hard dinar (1966-1990) random",
- "1.00 Yugoslavian hard dinars (1966-1990) random",
- "1.00 Yugoslavian new dinar (1994-2002) random",
- "1.00 Yugoslavian new dinars (1994-2002) random",
- "1.00 Zairean New Zaire (1993-1998) random",
- "1.00 Zairean Zaire (1971-1993) random",
- "1.00 Zairean new zaire (1993-1998) random",
- "1.00 Zairean new zaires (1993-1998) random",
- "1.00 Zairean zaire (1971-1993) random",
- "1.00 Zairean zaires (1971-1993) random",
+ "1.00 Yugoslavian Convertible Dinar (1990\\u20131992) random",
+ "1.00 Yugoslavian Hard Dinar (1966\\u20131990) random",
+ "1.00 Yugoslavian New Dinar (1994\\u20132002) random",
+ "1.00 Yugoslavian convertible dinar (1990\\u20131992) random",
+ "1.00 Yugoslavian convertible dinars (1990\\u20131992) random",
+ "1.00 Yugoslavian hard dinar (1966\\u20131990) random",
+ "1.00 Yugoslavian hard dinars (1966\\u20131990) random",
+ "1.00 Yugoslavian new dinar (1994\\u20132002) random",
+ "1.00 Yugoslavian new dinars (1994\\u20132002) random",
+ "1.00 Zairean New Zaire (1993\\u20131998) random",
+ "1.00 Zairean Zaire (1971\\u20131993) random",
+ "1.00 Zairean new zaire (1993\\u20131998) random",
+ "1.00 Zairean new zaires (1993\\u20131998) random",
+ "1.00 Zairean zaire (1971\\u20131993) random",
+ "1.00 Zairean zaires (1971\\u20131993) random",
"1.00 Zambian Kwacha random",
"1.00 Zambian kwacha random",
"1.00 Zambian kwachas random",
- "1.00 Zimbabwean Dollar (1980-2008) random",
- "1.00 Zimbabwean dollar (1980-2008) random",
- "1.00 Zimbabwean dollars (1980-2008) random",
+ "1.00 Zimbabwean Dollar (1980\\u20132008) random",
+ "1.00 Zimbabwean dollar (1980\\u20132008) random",
+ "1.00 Zimbabwean dollars (1980\\u20132008) random",
"1.00 euro random",
"1.00 euros random",
- "1.00 Turkish lira (1922-2005) random",
+ "1.00 Turkish lira (1922\\u20132005) random",
"1.00 special drawing rights random",
"1.00 Colombian real value unit random",
"1.00 Colombian real value units random",
"AW1.00",
"AZ1.00",
"Afghan Afghan1.00",
- "Afghan Afghani (1927-20021.00",
+ "Afghan Afghani (1927\\u201320021.00",
"Afl1.00",
"Albanian Le1.00",
"Algerian Dina1.00",
"Andorran Peset1.00",
"Angolan Kwanz1.00",
- "Angolan Kwanza (1977-19901.00",
- "Angolan Readjusted Kwanza (1995-19991.00",
- "Angolan New Kwanza (1990-20001.00",
+ "Angolan Kwanza (1977\\u201319901.00",
+ "Angolan Readjusted Kwanza (1995\\u201319991.00",
+ "Angolan New Kwanza (1990\\u201320001.00",
"Argentine Austra1.00",
"Argentine Pes1.00",
- "Argentine Peso (1983-19851.00",
+ "Argentine Peso (1983\\u201319851.00",
"Armenian Dra1.00",
"Aruban Flori1.00",
"Australian Dolla1.00",
"Austrian Schillin1.00",
"Azerbaijani Mana1.00",
- "Azerbaijani Manat (1993-20061.00",
+ "Azerbaijani Manat (1993\\u201320061.00",
"B1.00",
"BA1.00",
"BB1.00",
"Bangladeshi Tak1.00",
"Barbadian Dolla1.00",
"Bds1.00",
- "Belarusian New Ruble (1994-19991.00",
+ "Belarusian Ruble (1994\\u201319991.00",
"Belarusian Rubl1.00",
"Belgian Fran1.00",
"Belgian Franc (convertible1.00",
"Brazilian Cruzad1.00",
"Brazilian Cruzado Nov1.00",
"Brazilian Cruzeir1.00",
- "Brazilian Cruzeiro (1990-19931.00",
- "Brazilian New Cruzeiro (1967-19861.00",
+ "Brazilian Cruzeiro (1990\\u201319931.00",
+ "Brazilian New Cruzeiro (1967\\u201319861.00",
"Brazilian Rea1.00",
"British Pound Sterlin1.00",
"Brunei Dolla1.00",
"C1.00",
"CA1.00",
"CD1.00",
- "CFA Franc BCEA1.00",
- "CFA Franc BEA1.00",
"CFP Fran1.00",
"CFP1.00",
"CH1.00",
"Georgian Kupon Lari1.00",
"Georgian Lar1.00",
"Ghanaian Ced1.00",
- "Ghanaian Cedi (1979-20071.00",
+ "Ghanaian Cedi (1979\\u201320071.00",
"Gibraltar Poun1.00",
"Gol1.00",
"Greek Drachm1.00",
"Mauritanian Ouguiy1.00",
"Mauritian Rupe1.00",
"Mexican Pes1.00",
- "Mexican Silver Peso (1861-19921.00",
+ "Mexican Silver Peso (1861\\u201319921.00",
"Mexican Investment Uni1.00",
"Moldovan Le1.00",
"Mongolian Tugri1.00",
"Moroccan Fran1.00",
"Mozambican Escud1.00",
"Mozambican Metica1.00",
- "Myanma Kya1.00",
+ "Myanmar Kya1.00",
"N1.00",
"NA1.00",
"NAf1.00",
"Dutch Guilde1.00",
"Israeli New Sheqe1.00",
"New Zealand Dolla1.00",
- "Nicaraguan C\\u00f3rdoba (1988-19911.00",
+ "Nicaraguan C\\u00f3rdoba (1988\\u201319911.00",
"Nicaraguan C\\u00f3rdob1.00",
"Nigerian Nair1.00",
"North Korean Wo1.00",
"Nr1.00",
"OM1.00",
"Old Mozambican Metica1.00",
- "Romanian Leu (1952-20061.00",
- "Serbian Dinar (2002-20061.00",
- "Sudanese Dinar (1992-20071.00",
- "Sudanese Pound (1957-19981.00",
- "Turkish Lira (1922-20051.00",
+ "Romanian Leu (1952\\u201320061.00",
+ "Serbian Dinar (2002\\u201320061.00",
+ "Sudanese Dinar (1992\\u201320071.00",
+ "Sudanese Pound (1957\\u201319981.00",
+ "Turkish Lira (1922\\u201320051.00",
"Omani Ria1.00",
"PA1.00",
"PE1.00",
"Papua New Guinean Kin1.00",
"Paraguayan Guaran1.00",
"Peruvian Int1.00",
- "Peruvian Sol (1863-19651.00",
+ "Peruvian Sol (1863\\u201319651.00",
"Peruvian Sol Nuev1.00",
"Philippine Pes1.00",
"Platinu1.00",
"Polish Zlot1.00",
- "Polish Zloty (1950-19951.00",
+ "Polish Zloty (1950\\u201319951.00",
"Portuguese Escud1.00",
"Portuguese Guinea Escud1.00",
"Pr1.00",
"Rhodesian Dolla1.00",
"Romanian Le1.00",
"Russian Rubl1.00",
- "Russian Ruble (1991-19981.00",
+ "Russian Ruble (1991\\u201319981.00",
"Rwandan Fran1.00",
"S1.00",
"SA1.00",
"SV1.00",
"SY1.00",
"SZ1.00",
- "Saint Helena Poun1.00",
- "S\\u00e3o Tom\\u00e9 and Pr\\u00edncipe Dobr1.00",
+ "St. Helena Poun1.00",
+ "S\\u00e3o Tom\\u00e9 & Pr\\u00edncipe Dobr1.00",
"Saudi Riya1.00",
"Serbian Dina1.00",
"Seychellois Rupe1.00",
"Thai Bah1.00",
"Timorese Escud1.00",
"Tongan Pa\\u20bbang1.00",
- "Trinidad and Tobago Dolla1.00",
+ "Trinidad & Tobago Dolla1.00",
"Tunisian Dina1.00",
"Turkish Lir1.00",
"Turkmenistani Mana1.00",
"UY1.00",
"UZ1.00",
"Ugandan Shillin1.00",
- "Ugandan Shilling (1966-19871.00",
+ "Ugandan Shilling (1966\\u201319871.00",
"Ukrainian Hryvni1.00",
"Ukrainian Karbovanet1.00",
"Colombian Real Value Uni1.00",
"United Arab Emirates Dirha1.00",
"Unknown Currenc1.00",
"Ur1.00",
- "Uruguay Peso (1975-19931.00",
+ "Uruguay Peso (1975\\u201319931.00",
"Uruguay Peso Uruguay1.00",
"Uruguay Peso (Indexed Units1.00",
- "Uzbekistan So1.00",
+ "Uzbekistani So1.00",
"V1.00",
"VE1.00",
"VN1.00",
"Venezuelan Bol\\u00edva1.00",
"Venezuelan Bol\\u00edvar Fuert1.00",
"Vietnamese Don1.00",
+ "West African CFA Fran1.00",
+ "Central African CFA Fran1.00",
"WIR Eur1.00",
"WIR Fran1.00",
"WS1.00",
"Yemeni Dina1.00",
"Yemeni Ria1.00",
"Yugoslavian Convertible Dina1.00",
- "Yugoslavian Hard Dinar (1966-19901.00",
+ "Yugoslavian Hard Dinar (1966\\u201319901.00",
"Yugoslavian New Dina1.00",
"Z1.00",
"ZA1.00",
"ZM1.00",
"ZR1.00",
"ZW1.00",
- "Zairean New Zaire (1993-19981.00",
+ "Zairean New Zaire (1993\\u201319981.00",
"Zairean Zair1.00",
"Zambian Kwach1.00",
- "Zimbabwean Dollar (1980-20081.00",
+ "Zimbabwean Dollar (1980\\u201320081.00",
"dra1.00",
"lar1.00",
"le1.00",
};
Locale locale("en_US");
- for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
- UnicodeString formatted = ctou(DATA[i]);
- UErrorCode status = U_ZERO_ERROR;
- NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
- if (numFmt != NULL && U_SUCCESS(status)) {
- ParsePosition parsePos;
- LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
- if (parsePos.getIndex() > 0) {
- double doubleVal = currAmt->getNumber().getDouble(status);
- if ( doubleVal != 1.0 ) {
- errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
- }
- } else {
- errln("Failed to parse as currency: " + formatted);
- }
- } else {
- dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
- delete numFmt;
- break;
- }
- delete numFmt;
+ for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
+ UnicodeString formatted = ctou(DATA[i]);
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> numFmt(NumberFormat::createInstance(locale, UNUM_CURRENCY, status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
+ return;
+ }
+ // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
+ numFmt->setLenient(TRUE);
+ ParsePosition parsePos;
+ LocalPointer<CurrencyAmount> currAmt(numFmt->parseCurrency(formatted, parsePos));
+ if (parsePos.getIndex() > 0) {
+ double doubleVal = currAmt->getNumber().getDouble(status);
+ if ( doubleVal != 1.0 ) {
+ errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
+ }
+ } else {
+ errln("Failed to parse as currency: " + formatted);
+ }
}
- for (uint32_t i=0; i<sizeof(WRONG_DATA)/sizeof(WRONG_DATA[0]); ++i) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(WRONG_DATA); ++i) {
UnicodeString formatted = ctou(WRONG_DATA[i]);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
if (failure(status, "NumberFormat::createInstance", TRUE)) return;
double val = 12345.67;
-
+
{
int32_t expected[] = {
UNUM_CURRENCY_FIELD, 0, 1,
UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
UNUM_FRACTION_FIELD, 8, 10,
};
- int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
FieldPositionIterator posIter;
UnicodeString result;
UNUM_EXPONENT_SIGN_FIELD, 6, 7,
UNUM_EXPONENT_FIELD, 7, 8
};
- int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
+ int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
FieldPositionIterator posIter;
UnicodeString result;
//
// Test formatting & parsing of big decimals.
-// API test, not a comprehensive test.
+// API test, not a comprehensive test.
// See DecimalFormatTest/DataDrivenTests
//
-#define ASSERT_SUCCESS(status) {if (U_FAILURE(status)) errln("file %s, line %d: status: %s", \
- __FILE__, __LINE__, u_errorName(status));}
-#define ASSERT_EQUALS(expected, actual) {if ((expected) != (actual)) \
- errln("file %s, line %d: %s != %s", __FILE__, __LINE__, #expected, #actual);}
-
-static UBool operator != (const char *s1, UnicodeString &s2) {
- // This function lets ASSERT_EQUALS("literal", UnicodeString) work.
- UnicodeString us1(s1);
- return us1 != s2;
+#define ASSERT_SUCCESS(status) { \
+ assertSuccess(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (status)); \
+}
+#define ASSERT_EQUALS(expected, actual) { \
+ assertEquals(UnicodeString("file ") + __FILE__ + ", line " + __LINE__, (expected), (actual)); \
}
void NumberFormatTest::TestDecimal() {
ASSERT_SUCCESS(status);
StringPiece s = f.getDecimalNumber(status);
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("1.2345678999987654321E+667", s);
+ ASSERT_EQUALS("1.2345678999987654321E+667", s.data());
//printf("%s\n", s.data());
}
ASSERT_EQUALS(123.45, f.getDouble());
ASSERT_EQUALS(123.45, f.getDouble(status));
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("123.45", f.getDecimalNumber(status));
+ ASSERT_EQUALS("123.45", f.getDecimalNumber(status).data());
ASSERT_SUCCESS(status);
f.setDecimalNumber("4.5678E7", status);
ASSERT_EQUALS(-123, f.getLong());
ASSERT_EQUALS(-123, f.getLong(status));
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("-123", f.getDecimalNumber(status));
+ ASSERT_EQUALS("-123", f.getDecimalNumber(status).data());
ASSERT_SUCCESS(status);
status = U_ZERO_ERROR;
ASSERT_EQUALS(1234567890123LL, f.getInt64());
ASSERT_EQUALS(1234567890123LL, f.getInt64(status));
ASSERT_SUCCESS(status);
- ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status));
+ ASSERT_EQUALS("1234567890123", f.getDecimalNumber(status).data());
ASSERT_SUCCESS(status);
}
Formattable result;
fmtr->parse(input, result, status);
ASSERT_SUCCESS(status);
- ASSERT_EQUALS(0, strcmp("0.0184", result.getDecimalNumber(status).data()));
+ ASSERT_EQUALS("0.0184", result.getDecimalNumber(status).data());
//std::cout << result.getDecimalNumber(status).data();
delete fmtr;
}
}
-
+
+#if U_PLATFORM != U_PF_CYGWIN || defined(CYGWINMSVC)
+ /*
+ * This test fails on Cygwin (1.7.16) using GCC because of a rounding issue with strtod().
+ * See #9463
+ */
{
// Check that a parse returns a decimal number with full accuracy
UErrorCode status = U_ZERO_ERROR;
delete fmtr;
}
}
+#endif
}
errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
+ text1 + " text2=" + text2);
}
- delete fmt;
}
+ delete fmt;
}
-void NumberFormatTest::TestExponentParse() {
-
- UErrorCode status = U_ZERO_ERROR;
- Formattable result;
- ParsePosition parsePos(0);
-
- // set the exponent symbol
- status = U_ZERO_ERROR;
- DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getDefault(), status);
- if(U_FAILURE(status)) {
- dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
- return;
- }
-
- // create format instance
- status = U_ZERO_ERROR;
- DecimalFormat fmt("#####", symbols, status);
- if(U_FAILURE(status)) {
- errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
- }
-
- // parse the text
- fmt.parse("5.06e-27", result, parsePos);
- if(result.getType() != Formattable::kDouble &&
- result.getDouble() != 5.06E-27 &&
- parsePos.getIndex() != 8
- )
- {
- errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
- result.getDouble(), parsePos.getIndex());
- }
-}
+void NumberFormatTest::TestExponentParse() {
+
+ UErrorCode status = U_ZERO_ERROR;
+ Formattable result;
+ ParsePosition parsePos(0);
+
+ // set the exponent symbol
+ status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale::getDefault(), status);
+ if(U_FAILURE(status)) {
+ dataerrln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (Default)");
+ return;
+ }
+
+ // create format instance
+ status = U_ZERO_ERROR;
+ DecimalFormat fmt(u"#####", symbols, status);
+ if(U_FAILURE(status)) {
+ errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
+ }
+
+ // parse the text
+ fmt.parse("5.06e-27", result, parsePos);
+ if(result.getType() != Formattable::kDouble &&
+ result.getDouble() != 5.06E-27 &&
+ parsePos.getIndex() != 8
+ )
+ {
+ errln("ERROR: parse failed - expected 5.06E-27, 8 - returned %d, %i",
+ result.getDouble(), parsePos.getIndex());
+ }
+}
void NumberFormatTest::TestExplicitParents() {
static const char* parentLocaleTests[][2]= {
/* locale ID */ /* expected */
{"es_CO", "1.250,75" },
- {"es_CR", "1.250,75" },
{"es_ES", "1.250,75" },
{"es_GQ", "1.250,75" },
{"es_MX", "1,250.75" },
UnicodeString s;
- for(int i=0; i < (int)(sizeof(parentLocaleTests)/sizeof(parentLocaleTests[i])); i++){
+ for(int i=0; i < UPRV_LENGTHOF(parentLocaleTests); i++){
UErrorCode status = U_ZERO_ERROR;
const char *localeID = parentLocaleTests[i][0];
UnicodeString expected(parentLocaleTests[i][1], -1, US_INV);
CHECK_DATA(status, "NumberingSystem::getAvailableNames()")
int32_t nsCount = availableNumberingSystems->count(status);
- if ( nsCount < 36 ) {
- errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 36, got %d",nsCount);
+ if ( nsCount < 74 ) {
+ errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
}
/* A relatively simple test of the API. We call getAvailableNames() and cycle through */
for ( int32_t i = 0 ; i < nsCount ; i++ ) {
const char *nsname = availableNumberingSystems->next(&len,status);
NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
+ logln("OK for ns = %s",nsname);
if ( uprv_strcmp(nsname,ns->getName()) ) {
errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
}
{
U_STRING_DECL(pattern,"#",1);
U_STRING_INIT(pattern,"#",1);
-
+
U_STRING_DECL(infstr,"INF",3);
U_STRING_INIT(infstr,"INF",3);
U_STRING_DECL(nanstr,"NAN",3);
U_STRING_INIT(nanstr,"NAN",3);
-
+
UChar outputbuf[50] = {0};
UErrorCode status = U_ZERO_ERROR;
UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
UFieldPosition position = { 0, 0, 0};
unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);
-
+
if ( u_strcmp(infstr, outputbuf)) {
errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
}
unum_close(fmt);
}
+
+void NumberFormatTest::TestFormatFastpaths() {
+ // get some additional case
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString(u"0000"),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = 1;
+ UnicodeString expect = "0001";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "-9223372036854775808";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "9223372036854775807";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = 0;
+ // uint8_t bits[8];
+ // memcpy(bits,&long_number,8);
+ // for(int i=0;i<8;i++) {
+ // logln("bits: %02X", (unsigned int)bits[i]);
+ // }
+ UnicodeString expect = "0000000000000000000";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ }
+ }
+ }
+ {
+ UErrorCode status=U_ZERO_ERROR;
+ DecimalFormat df(UnicodeString("0000000000000000000",""),status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ } else {
+ int64_t long_number = U_INT64_MIN + 1;
+ UnicodeString expect = "-9223372036854775807";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
+ __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ }
+ }
+ }
+}
+
+
+void NumberFormatTest::TestFormattableSize(void) { // test ICU 61 behavior
+ if(sizeof(FmtStackData) > UNUM_INTERNAL_STACKARRAY_SIZE) {
+ errln("Error: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
+ sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+ } else if(sizeof(FmtStackData) < UNUM_INTERNAL_STACKARRAY_SIZE) {
+ logln("Warning: sizeof(FmtStackData)=%d, UNUM_INTERNAL_STACKARRAY_SIZE=%d\n",
+ sizeof(FmtStackData), UNUM_INTERNAL_STACKARRAY_SIZE);
+ } else {
+ logln("sizeof(Formattable)=%d, 112=%d\n",
+ sizeof(Formattable), 112);
+ }
+}
+
+UBool NumberFormatTest::testFormattableAsUFormattable(const char *file, int line, Formattable &f) {
+ UnicodeString fileLine = UnicodeString(file)+UnicodeString(":")+line+UnicodeString(": ");
+
+ UFormattable *u = f.toUFormattable();
+ logln();
+ if (u == NULL) {
+ errln("%s:%d: Error: f.toUFormattable() retuned NULL.");
+ return FALSE;
+ }
+ logln("%s:%d: comparing Formattable with UFormattable", file, line);
+ logln(fileLine + toString(f));
+
+ UErrorCode status = U_ZERO_ERROR;
+ UErrorCode valueStatus = U_ZERO_ERROR;
+ UFormattableType expectUType = UFMT_COUNT; // invalid
+
+ UBool triedExact = FALSE; // did we attempt an exact comparison?
+ UBool exactMatch = FALSE; // was the exact comparison true?
+
+ switch( f.getType() ) {
+ case Formattable::kDate:
+ expectUType = UFMT_DATE;
+ exactMatch = (f.getDate()==ufmt_getDate(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kDouble:
+ expectUType = UFMT_DOUBLE;
+ exactMatch = (f.getDouble()==ufmt_getDouble(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kLong:
+ expectUType = UFMT_LONG;
+ exactMatch = (f.getLong()==ufmt_getLong(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kString:
+ expectUType = UFMT_STRING;
+ {
+ UnicodeString str;
+ f.getString(str);
+ int32_t len;
+ const UChar* uch = ufmt_getUChars(u, &len, &valueStatus);
+ if(U_SUCCESS(valueStatus)) {
+ UnicodeString str2(uch, len);
+ assertTrue("UChar* NULL-terminated", uch[len]==0);
+ exactMatch = (str == str2);
+ }
+ triedExact = TRUE;
+ }
+ break;
+ case Formattable::kArray:
+ expectUType = UFMT_ARRAY;
+ triedExact = TRUE;
+ {
+ int32_t count = ufmt_getArrayLength(u, &valueStatus);
+ int32_t count2;
+ const Formattable *array2 = f.getArray(count2);
+ exactMatch = assertEquals(fileLine + " array count", count, count2);
+
+ if(exactMatch) {
+ for(int i=0;U_SUCCESS(valueStatus) && i<count;i++) {
+ UFormattable *uu = ufmt_getArrayItemByIndex(u, i, &valueStatus);
+ if(*Formattable::fromUFormattable(uu) != (array2[i])) {
+ errln("%s:%d: operator== did not match at index[%d] - %p vs %p", file, line, i,
+ (const void*)Formattable::fromUFormattable(uu), (const void*)&(array2[i]));
+ exactMatch = FALSE;
+ } else {
+ if(!testFormattableAsUFormattable("(sub item)",i,*Formattable::fromUFormattable(uu))) {
+ exactMatch = FALSE;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case Formattable::kInt64:
+ expectUType = UFMT_INT64;
+ exactMatch = (f.getInt64()==ufmt_getInt64(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ case Formattable::kObject:
+ expectUType = UFMT_OBJECT;
+ exactMatch = (f.getObject()==ufmt_getObject(u, &valueStatus));
+ triedExact = TRUE;
+ break;
+ }
+ UFormattableType uType = ufmt_getType(u, &status);
+
+ if(U_FAILURE(status)) {
+ errln("%s:%d: Error calling ufmt_getType - %s", file, line, u_errorName(status));
+ return FALSE;
+ }
+
+ if(uType != expectUType) {
+ errln("%s:%d: got type (%d) expected (%d) from ufmt_getType", file, line, (int) uType, (int) expectUType);
+ }
+
+ if(triedExact) {
+ if(U_FAILURE(valueStatus)) {
+ errln("%s:%d: got err %s trying to ufmt_get...() for exact match check", file, line, u_errorName(valueStatus));
+ } else if(!exactMatch) {
+ errln("%s:%d: failed exact match for the Formattable type", file, line);
+ } else {
+ logln("%s:%d: exact match OK", file, line);
+ }
+ } else {
+ logln("%s:%d: note, did not attempt exact match for this formattable type", file, line);
+ }
+
+ if( assertEquals(fileLine + " isNumeric()", f.isNumeric(), ufmt_isNumeric(u))
+ && f.isNumeric()) {
+ UErrorCode convStatus = U_ZERO_ERROR;
+
+ if(uType != UFMT_INT64) { // may fail to compare
+ assertTrue(fileLine + " as doubles ==", f.getDouble(convStatus)==ufmt_getDouble(u, &convStatus));
+ }
+
+ if( assertSuccess(fileLine + " (numeric conversion status)", convStatus) ) {
+ StringPiece fDecNum = f.getDecimalNumber(convStatus);
+#if 1
+ int32_t len;
+ const char *decNumChars = ufmt_getDecNumChars(u, &len, &convStatus);
+#else
+ // copy version
+ char decNumChars[200];
+ int32_t len = ufmt_getDecNumChars(u, decNumChars, 200, &convStatus);
+#endif
+
+ if( assertSuccess(fileLine + " (decNumbers conversion)", convStatus) ) {
+ logln(fileLine + decNumChars);
+ assertEquals(fileLine + " decNumChars length==", len, fDecNum.length());
+ assertEquals(fileLine + " decNumChars digits", decNumChars, fDecNum.data());
+ }
+
+ UErrorCode int64ConversionF = U_ZERO_ERROR;
+ int64_t l = f.getInt64(int64ConversionF);
+ UErrorCode int64ConversionU = U_ZERO_ERROR;
+ int64_t r = ufmt_getInt64(u, &int64ConversionU);
+
+ if( (l==r)
+ && ( uType != UFMT_INT64 ) // int64 better not overflow
+ && (U_INVALID_FORMAT_ERROR==int64ConversionU)
+ && (U_INVALID_FORMAT_ERROR==int64ConversionF) ) {
+ logln("%s:%d: OK: 64 bit overflow", file, line);
+ } else {
+ assertEquals(fileLine + " as int64 ==", l, r);
+ assertSuccess(fileLine + " Formattable.getnt64()", int64ConversionF);
+ assertSuccess(fileLine + " ufmt_getInt64()", int64ConversionU);
+ }
+ }
+ }
+ return exactMatch || !triedExact;
+}
+
+void NumberFormatTest::TestUFormattable(void) {
+ {
+ // test that a default formattable is equal to Formattable()
+ UErrorCode status = U_ZERO_ERROR;
+ LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
+ assertSuccess("calling umt_open", status);
+ Formattable defaultFormattable;
+ assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+ assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
+ assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
+ (defaultFormattable
+ == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
+ assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
+ ((&defaultFormattable)
+ == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
+ assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
+ ((&defaultFormattable)
+ == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
+ testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
+ }
+ // test some random Formattables
+ {
+ Formattable f(ucal_getNow(), Formattable::kIsDate);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((double)1.61803398874989484820); // golden ratio
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ Formattable f("Hello world."); // should be invariant?
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
+ assertSuccess("Constructing a StringPiece", status2);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ UErrorCode status2 = U_ZERO_ERROR;
+ UObject *obj = new Locale();
+ Formattable f(obj);
+ assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
+ testFormattableAsUFormattable(__FILE__, __LINE__, f);
+ }
+ {
+ const Formattable array[] = {
+ Formattable(ucal_getNow(), Formattable::kIsDate),
+ Formattable((int32_t)4),
+ Formattable((double)1.234),
+ };
+
+ Formattable fa(array, 3);
+ testFormattableAsUFormattable(__FILE__, __LINE__, fa);
+ }
+}
+
+void NumberFormatTest::TestSignificantDigits(void) {
+ double input[] = {
+ 0, 0,
+ 0.1, -0.1,
+ 123, -123,
+ 12345, -12345,
+ 123.45, -123.45,
+ 123.44501, -123.44501,
+ 0.001234, -0.001234,
+ 0.00000000123, -0.00000000123,
+ 0.0000000000000000000123, -0.0000000000000000000123,
+ 1.2, -1.2,
+ 0.0000000012344501, -0.0000000012344501,
+ 123445.01, -123445.01,
+ 12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
+ };
+ const char* expected[] = {
+ "0.00", "0.00",
+ "0.100", "-0.100",
+ "123", "-123",
+ "12345", "-12345",
+ "123.45", "-123.45",
+ "123.45", "-123.45",
+ "0.001234", "-0.001234",
+ "0.00000000123", "-0.00000000123",
+ "0.0000000000000000000123", "-0.0000000000000000000123",
+ "1.20", "-1.20",
+ "0.0000000012345", "-0.0000000012345",
+ "123450", "-123450",
+ "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale("en_US");
+ LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+ NumberFormat::createInstance(locale, status)));
+ CHECK_DATA(status,"NumberFormat::createInstance")
+
+ numberFormat->setSignificantDigitsUsed(TRUE);
+ numberFormat->setMinimumSignificantDigits(3);
+ numberFormat->setMaximumSignificantDigits(5);
+ numberFormat->setGroupingUsed(false);
+
+ UnicodeString result;
+ UnicodeString expectedResult;
+ for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
+ numberFormat->format(input[i], result);
+ UnicodeString expectedResult(expected[i]);
+ if (result != expectedResult) {
+ errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
+ }
+ result.remove();
+ }
+}
+
+void NumberFormatTest::TestShowZero() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale("en_US");
+ LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+ NumberFormat::createInstance(locale, status)));
+ CHECK_DATA(status, "NumberFormat::createInstance")
+
+ numberFormat->setSignificantDigitsUsed(TRUE);
+ numberFormat->setMaximumSignificantDigits(3);
+
+ UnicodeString result;
+ numberFormat->format(0.0, result);
+ if (result != "0") {
+ errln((UnicodeString)"Expected: 0, got " + result);
+ }
+}
+
+void NumberFormatTest::TestBug9936() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale("en_US");
+ LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
+ NumberFormat::createInstance(locale, status)));
+ if (U_FAILURE(status)) {
+ dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
+ return;
+ }
+
+ if (numberFormat->areSignificantDigitsUsed() == TRUE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
+ }
+ numberFormat->setSignificantDigitsUsed(TRUE);
+ if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+ }
+
+ numberFormat->setSignificantDigitsUsed(FALSE);
+ if (numberFormat->areSignificantDigitsUsed() == TRUE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
+ }
+
+ numberFormat->setMinimumSignificantDigits(3);
+ if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+ }
+
+ numberFormat->setSignificantDigitsUsed(FALSE);
+ numberFormat->setMaximumSignificantDigits(6);
+ if (numberFormat->areSignificantDigitsUsed() == FALSE) {
+ errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
+ }
+
+}
+
+void NumberFormatTest::TestParseNegativeWithFaLocale() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
+ CHECK_DATA(status, "NumberFormat::createInstance")
+ test->setLenient(TRUE);
+ Formattable af;
+ ParsePosition ppos;
+ UnicodeString value("\\u200e-0,5");
+ value = value.unescape();
+ test->parse(value, af, ppos);
+ if (ppos.getIndex() == 0) {
+ errln("Expected -0,5 to parse for Farsi.");
+ }
+ delete test;
+}
+
+void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
+ CHECK_DATA(status, "NumberFormat::createInstance")
+ test->setLenient(TRUE);
+ Formattable af;
+ ParsePosition ppos;
+ UnicodeString value("\\u208B0.5");
+ value = value.unescape();
+ test->parse(value, af, ppos);
+ if (ppos.getIndex() == 0) {
+ errln(UnicodeString("Expected ") + value + UnicodeString(" to parse."));
+ }
+ delete test;
+}
+
+void NumberFormatTest::TestCustomCurrencySignAndSeparator() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols custom(Locale::getUS(), status);
+ CHECK(status, "DecimalFormatSymbols constructor");
+
+ custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "*");
+ custom.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, "^");
+ custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, ":");
+
+ UnicodeString pat(" #,##0.00");
+ pat.insert(0, (UChar)0x00A4);
+
+ DecimalFormat fmt(pat, custom, status);
+ CHECK(status, "DecimalFormat constructor");
+
+ UnicodeString numstr("* 1^234:56");
+ expect2(fmt, (Formattable)((double)1234.56), numstr);
+}
+
+typedef struct {
+ const char * locale;
+ UBool lenient;
+ UnicodeString numString;
+ double value;
+} SignsAndMarksItem;
+
+
+void NumberFormatTest::TestParseSignsAndMarks() {
+ const SignsAndMarksItem items[] = {
+ // locale lenient numString value
+ { "en", FALSE, CharsToUnicodeString("12"), 12 },
+ { "en", TRUE, CharsToUnicodeString("12"), 12 },
+ { "en", FALSE, CharsToUnicodeString("-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("- 23"), -23 },
+ { "en", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "en", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
+
+ { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "en@numbers=arab", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
+ { "en@numbers=arab", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "en@numbers=arab", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
+
+ { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "en@numbers=arabext", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
+ { "en@numbers=arabext", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
+
+ { "he", FALSE, CharsToUnicodeString("12"), 12 },
+ { "he", TRUE, CharsToUnicodeString("12"), 12 },
+ { "he", FALSE, CharsToUnicodeString("-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("- 23"), -23 },
+ { "he", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "he", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
+
+ { "ar", FALSE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "ar", TRUE, CharsToUnicodeString("\\u0663\\u0664"), 34 },
+ { "ar", FALSE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("- \\u0664\\u0665"), -45 },
+ { "ar", FALSE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("\\u200F-\\u0664\\u0665"), -45 },
+ { "ar", TRUE, CharsToUnicodeString("\\u200F- \\u0664\\u0665"), -45 },
+
+ { "ar_MA", FALSE, CharsToUnicodeString("12"), 12 },
+ { "ar_MA", TRUE, CharsToUnicodeString("12"), 12 },
+ { "ar_MA", FALSE, CharsToUnicodeString("-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("- 23"), -23 },
+ { "ar_MA", FALSE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("\\u200E-23"), -23 },
+ { "ar_MA", TRUE, CharsToUnicodeString("\\u200E- 23"), -23 },
+
+ { "fa", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "fa", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "fa", FALSE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u2212\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"), -67 },
+ { "fa", FALSE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"), -67 },
+ { "fa", TRUE, CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"), -67 },
+
+ { "ps", FALSE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "ps", TRUE, CharsToUnicodeString("\\u06F5\\u06F6"), 56 },
+ { "ps", FALSE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("-\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("- \\u06F6\\u06F7"), -67 },
+ { "ps", FALSE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"), -67 },
+ { "ps", FALSE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"), -67 },
+ { "ps", TRUE, CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"), -67 },
+ // terminator
+ { NULL, 0, UnicodeString(""), 0 },
+ };
+
+ const SignsAndMarksItem * itemPtr;
+ for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
+ UErrorCode status = U_ZERO_ERROR;
+ NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
+ if (U_SUCCESS(status)) {
+ numfmt->setLenient(itemPtr->lenient);
+ Formattable fmtobj;
+ ParsePosition ppos;
+ numfmt->parse(itemPtr->numString, fmtobj, ppos);
+ if (ppos.getIndex() == itemPtr->numString.length()) {
+ double parsedValue = fmtobj.getDouble(status);
+ if (U_FAILURE(status) || parsedValue != itemPtr->value) {
+ errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
+ }
+ } else {
+ errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
+ }
+ } else {
+ dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
+ }
+ delete numfmt;
+ }
+}
+
+typedef struct {
+ DecimalFormat::ERoundingMode mode;
+ double value;
+ UnicodeString expected;
+} Test10419Data;
+
+
+// Tests that rounding works right when fractional digits is set to 0.
+void NumberFormatTest::Test10419RoundingWith0FractionDigits() {
+ const Test10419Data items[] = {
+ { DecimalFormat::kRoundCeiling, 1.488, "2"},
+ { DecimalFormat::kRoundDown, 1.588, "1"},
+ { DecimalFormat::kRoundFloor, 1.888, "1"},
+ { DecimalFormat::kRoundHalfDown, 1.5, "1"},
+ { DecimalFormat::kRoundHalfEven, 2.5, "2"},
+ { DecimalFormat::kRoundHalfUp, 2.5, "3"},
+ { DecimalFormat::kRoundUp, 1.5, "2"},
+ };
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<DecimalFormat> decfmt((DecimalFormat *) NumberFormat::createInstance(Locale("en_US"), status));
+ if (U_FAILURE(status)) {
+ dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+ return;
+ }
+ for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
+ decfmt->setRoundingMode(items[i].mode);
+ decfmt->setMaximumFractionDigits(0);
+ UnicodeString actual;
+ if (items[i].expected != decfmt->format(items[i].value, actual)) {
+ errln("Expected " + items[i].expected + ", got " + actual);
+ }
+ }
+}
+
+void NumberFormatTest::Test10468ApplyPattern() {
+ // Padding char of fmt is now 'a'
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt("'I''ll'*a###.##", status);
+
+ if (U_FAILURE(status)) {
+ errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
+ return;
+ }
+
+ assertEquals("Padding character should be 'a'.", u"a", fmt.getPadCharacterString());
+
+ // Padding char of fmt ought to be '*' since that is the default and no
+ // explicit padding char is specified in the new pattern.
+ fmt.applyPattern("AA#,##0.00ZZ", status);
+
+ // Oops this still prints 'a' even though we changed the pattern.
+ assertEquals("applyPattern did not clear padding character.", u" ", fmt.getPadCharacterString());
+}
+
+void NumberFormatTest::TestRoundingScientific10542() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat format("0.00E0", status);
+ if (U_FAILURE(status)) {
+ errcheckln(status, "DecimalFormat constructor failed - %s", u_errorName(status));
+ return;
+ }
+
+ DecimalFormat::ERoundingMode roundingModes[] = {
+ DecimalFormat::kRoundCeiling,
+ DecimalFormat::kRoundDown,
+ DecimalFormat::kRoundFloor,
+ DecimalFormat::kRoundHalfDown,
+ DecimalFormat::kRoundHalfEven,
+ DecimalFormat::kRoundHalfUp,
+ DecimalFormat::kRoundUp};
+ const char *descriptions[] = {
+ "Round Ceiling",
+ "Round Down",
+ "Round Floor",
+ "Round half down",
+ "Round half even",
+ "Round half up",
+ "Round up"};
+
+ {
+ double values[] = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.02E-3", "3.02E-3", "3.02E-3",
+ "-3.00E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.01E-3",
+ "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.01E-3", "3.01E-3", "3.01E-3",
+ "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.01E-3", "3.02E-3",
+ "-3.01E-3", "-3.00E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
+ "-3.01E-3", "-3.01E-3", "-3.00E-3", "3.01E-3", "3.02E-3", "3.02E-3",
+ "-3.01E-3", "-3.01E-3", "-3.01E-3", "3.02E-3", "3.02E-3", "3.02E-3"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-3.00E3", "-3.00E3", "-3.00E3", "3.02E3", "3.02E3", "3.02E3",
+ "-3.00E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.01E3",
+ "-3.01E3", "-3.01E3", "-3.01E3", "3.01E3", "3.01E3", "3.01E3",
+ "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.01E3", "3.02E3",
+ "-3.01E3", "-3.00E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
+ "-3.01E3", "-3.01E3", "-3.00E3", "3.01E3", "3.02E3", "3.02E3",
+ "-3.01E3", "-3.01E3", "-3.01E3", "3.02E3", "3.02E3", "3.02E3"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
+ {
+ double values[] = {0.0, -0.0};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0",
+ "0.00E0", "-0.00E0"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+*/
+ {
+
+ double values[] = {1e25, 1e25 + 1e15, 1e25 - 1e15};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "1.00E25", "1.01E25", "1.00E25",
+ "1.00E25", "1.00E25", "9.99E24",
+ "1.00E25", "1.00E25", "9.99E24",
+ "1.00E25", "1.00E25", "1.00E25",
+ "1.00E25", "1.00E25", "1.00E25",
+ "1.00E25", "1.00E25", "1.00E25",
+ "1.00E25", "1.01E25", "1.00E25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-1.00E25", "-9.99E24", "-1.00E25",
+ "-1.00E25", "-9.99E24", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.01E25",
+ "-1.00E25", "-1.00E25", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.00E25",
+ "-1.00E25", "-1.00E25", "-1.01E25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "1.00E-25", "1.01E-25", "1.00E-25",
+ "1.00E-25", "1.00E-25", "9.99E-26",
+ "1.00E-25", "1.00E-25", "9.99E-26",
+ "1.00E-25", "1.00E-25", "1.00E-25",
+ "1.00E-25", "1.00E-25", "1.00E-25",
+ "1.00E-25", "1.00E-25", "1.00E-25",
+ "1.00E-25", "1.01E-25", "1.00E-25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+ {
+ double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
+ // The order of these expected values correspond to the order of roundingModes and the order of values.
+ const char *expected[] = {
+ "-1.00E-25", "-9.99E-26", "-1.00E-25",
+ "-1.00E-25", "-9.99E-26", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.01E-25",
+ "-1.00E-25", "-1.00E-25", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.00E-25",
+ "-1.00E-25", "-1.00E-25", "-1.01E-25"};
+ verifyRounding(
+ format,
+ values,
+ expected,
+ roundingModes,
+ descriptions,
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
+ }
+}
+
+void NumberFormatTest::TestZeroScientific10547() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt("0.00E0", status);
+ if (!assertSuccess("Format creation", status)) {
+ return;
+ }
+ UnicodeString out;
+ fmt.format(-0.0, out);
+ assertEquals("format", "-0.00E0", out, true);
+}
+
+void NumberFormatTest::verifyRounding(
+ DecimalFormat& format,
+ const double *values,
+ const char * const *expected,
+ const DecimalFormat::ERoundingMode *roundingModes,
+ const char * const *descriptions,
+ int32_t valueSize,
+ int32_t roundingModeSize) {
+ for (int32_t i = 0; i < roundingModeSize; ++i) {
+ format.setRoundingMode(roundingModes[i]);
+ for (int32_t j = 0; j < valueSize; j++) {
+ UnicodeString currentExpected(expected[i * valueSize + j]);
+ currentExpected = currentExpected.unescape();
+ UnicodeString actual;
+ format.format(values[j], actual);
+ if (currentExpected != actual) {
+ dataerrln("For %s value %f, expected '%s', got '%s'",
+ descriptions[i], values[j], CStr(currentExpected)(), CStr(actual)());
+ }
+ }
+ }
+}
+
+void NumberFormatTest::TestAccountingCurrency() {
+ UErrorCode status = U_ZERO_ERROR;
+ UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;
+
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)(double)0, "$0.00", TRUE, status);
+ expect(NumberFormat::createInstance("en_US", style, status),
+ (Formattable)(double)-0.2, "($0.20)", TRUE, status);
+ expect(NumberFormat::createInstance("ja_JP", style, status),
+ (Formattable)10000, UnicodeString("\\u00A510,000").unescape(), TRUE, status);
+ expect(NumberFormat::createInstance("ja_JP", style, status),
+ (Formattable)-1000.5, UnicodeString("(\\u00A51,000)").unescape(), FALSE, status);
+ expect(NumberFormat::createInstance("de_DE", style, status),
+ (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
+}
+
+// for #5186
+void NumberFormatTest::TestEquality() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale("root"), status);
+ if (U_FAILURE(status)) {
+ dataerrln("Fail: can't create DecimalFormatSymbols for root");
+ return;
+ }
+ UnicodeString pattern("#,##0.###");
+ DecimalFormat fmtBase(pattern, symbols, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Fail: can't create DecimalFormat using root symbols");
+ return;
+ }
+
+ DecimalFormat* fmtClone = (DecimalFormat*)fmtBase.clone();
+ fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
+ if (*fmtClone == fmtBase) {
+ errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
+ }
+ delete fmtClone;
+}
+
+void NumberFormatTest::TestCurrencyUsage() {
+ double agent = 123.567;
+
+ UErrorCode status;
+ DecimalFormat *fmt;
+
+ // compare the Currency and Currency Cash Digits
+ // Note that as of CLDR 26:
+ // * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
+ // * CAD rounds to .05 in cash mode only
+ // 1st time for getter/setter, 2nd time for factory method
+ Locale enUS_PKR("en_US@currency=PKR");
+
+ for(int i=0; i<2; i++){
+ status = U_ZERO_ERROR;
+ if(i == 0){
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_PKR, UNUM_CURRENCY, status);
+ if (assertSuccess("en_US@currency=PKR/CURRENCY", status, TRUE) == FALSE) {
+ continue;
+ }
+
+ UnicodeString original;
+ fmt->format(agent,original);
+ assertEquals("Test Currency Usage 1", u"PKR124", original); // use ICU 61 behavior
+
+ // test the getter here
+ UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+ assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);
+
+ fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+ }else{
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_PKR, UNUM_CASH_CURRENCY, status);
+ if (assertSuccess("en_US@currency=PKR/CASH", status, TRUE) == FALSE) {
+ continue;
+ }
+ }
+
+ // must be usage = cash
+ UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+ assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);
+
+ UnicodeString cash_currency;
+ fmt->format(agent,cash_currency);
+ assertEquals("Test Currency Usage 2", u"PKR124", cash_currency); // use ICU 61 behavior
+ delete fmt;
+ }
+
+ // compare the Currency and Currency Cash Rounding
+ // 1st time for getter/setter, 2nd time for factory method
+ Locale enUS_CAD("en_US@currency=CAD");
+ for(int i=0; i<2; i++){
+ status = U_ZERO_ERROR;
+ if(i == 0){
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
+ continue;
+ }
+
+ UnicodeString original_rounding;
+ fmt->format(agent, original_rounding);
+ assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
+ fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+ }else{
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
+ continue;
+ }
+ }
+
+ UnicodeString cash_rounding_currency;
+ fmt->format(agent, cash_rounding_currency);
+ assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
+ delete fmt;
+ }
+
+ // Test the currency change
+ // 1st time for getter/setter, 2nd time for factory method
+ const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
+ for(int i=0; i<2; i++){
+ status = U_ZERO_ERROR;
+ if(i == 0){
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
+ continue;
+ }
+ fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
+ }else{
+ fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
+ if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
+ continue;
+ }
+ }
+
+ UnicodeString cur_original;
+ fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
+ fmt->format(agent, cur_original);
+ assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);
+
+ fmt->setCurrency(CUR_PKR, status);
+ assertSuccess("Set currency to PKR", status);
+
+ UnicodeString PKR_changed;
+ fmt->format(agent, PKR_changed);
+ assertEquals("Test Currency Usage 6", u"PKR124", PKR_changed); // use ICU 61 behavior
+ delete fmt;
+ }
+}
+
+
+// Check the constant MAX_INT64_IN_DOUBLE.
+// The value should convert to a double with no loss of precision.
+// A failure may indicate a platform with a different double format, requiring
+// a revision to the constant.
+//
+// Note that this is actually hard to test, because the language standard gives
+// compilers considerable flexibility to do unexpected things with rounding and
+// with overflow in simple int to/from float conversions. Some compilers will completely optimize
+// away a simple round-trip conversion from int64_t -> double -> int64_t.
+
+void NumberFormatTest::TestDoubleLimit11439() {
+ char buf[50];
+ for (int64_t num = MAX_INT64_IN_DOUBLE-10; num<=MAX_INT64_IN_DOUBLE; num++) {
+ sprintf(buf, "%lld", (long long)num);
+ double fNum = 0.0;
+ sscanf(buf, "%lf", &fNum);
+ int64_t rtNum = static_cast<int64_t>(fNum);
+ if (num != rtNum) {
+ errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
+ return;
+ }
+ }
+ for (int64_t num = -MAX_INT64_IN_DOUBLE+10; num>=-MAX_INT64_IN_DOUBLE; num--) {
+ sprintf(buf, "%lld", (long long)num);
+ double fNum = 0.0;
+ sscanf(buf, "%lf", &fNum);
+ int64_t rtNum = static_cast<int64_t>(fNum);
+ if (num != rtNum) {
+ errln("%s:%d MAX_INT64_IN_DOUBLE test, %lld did not round trip. Got %lld", __FILE__, __LINE__, (long long)num, (long long)rtNum);
+ return;
+ }
+ }
+}
+
+void NumberFormatTest::TestGetAffixes() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en_US", status);
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString affixStr;
+ assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+
+ // Test equality with affixes. set affix methods can't capture special
+ // characters which is why equality should fail.
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString someAffix;
+ fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(someAffix));
+ assertTrue("", fmt != fmtCopy);
+ }
+ fmt.setPositivePrefix("Don't");
+ fmt.setPositiveSuffix("do");
+ UnicodeString someAffix("be''eet\\u00a4\\u00a4\\u00a4 it.");
+ someAffix = someAffix.unescape();
+ fmt.setNegativePrefix(someAffix);
+ fmt.setNegativeSuffix("%");
+ assertEquals("", "Don't", fmt.getPositivePrefix(affixStr));
+ assertEquals("", "do", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", someAffix, fmt.getNegativePrefix(affixStr));
+ assertEquals("", "%", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::TestToPatternScientific11648() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ DecimalFormatSymbols sym(en, status);
+ DecimalFormat fmt("0.00", sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ fmt.setScientificNotation(TRUE);
+ UnicodeString pattern;
+ assertEquals("", "0.00E0", fmt.toPattern(pattern));
+ DecimalFormat fmt2(pattern, sym, status);
+ assertSuccess("", status);
+}
+
+void NumberFormatTest::TestBenchmark() {
+/*
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ DecimalFormatSymbols sym(en, status);
+ DecimalFormat fmt("0.0000000", new DecimalFormatSymbols(sym), status);
+// DecimalFormat fmt("0.00000E0", new DecimalFormatSymbols(sym), status);
+// DecimalFormat fmt("0", new DecimalFormatSymbols(sym), status);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 1000000; ++i) {
+ UnicodeString append;
+ fmt.format(3.0, append, fpos, status);
+// fmt.format(4.6692016, append, fpos, status);
+// fmt.format(1234567.8901, append, fpos, status);
+// fmt.format(2.99792458E8, append, fpos, status);
+// fmt.format(31, append);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+
+ UErrorCode status = U_ZERO_ERROR;
+ MessageFormat fmt("{0, plural, one {I have # friend.} other {I have # friends.}}", status);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ Formattable one(1.0);
+ Formattable three(3.0);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 500000; ++i) {
+ UnicodeString append;
+ fmt.format(&one, 1, append, fpos, status);
+ UnicodeString append2;
+ fmt.format(&three, 1, append2, fpos, status);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+
+ UErrorCode status = U_ZERO_ERROR;
+ Locale en("en");
+ Measure measureC(23, MeasureUnit::createCelsius(status), status);
+ MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ clock_t start = clock();
+ for (int32_t i = 0; i < 1000000; ++i) {
+ UnicodeString appendTo;
+ fmt.formatMeasures(
+ &measureC, 1, appendTo, fpos, status);
+ }
+ errln("Took %f", (double) (clock() - start) / CLOCKS_PER_SEC);
+ assertSuccess("", status);
+*/
+}
+
+void NumberFormatTest::TestFractionalDigitsForCurrency() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+ return;
+ }
+ UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
+ fmt->setCurrency(JPY, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ assertEquals("", 0, fmt->getMaximumFractionDigits());
+}
+
+
+void NumberFormatTest::TestFormatCurrencyPlural() {
+ UErrorCode status = U_ZERO_ERROR;
+ Locale locale = Locale::createCanonical("en_US");
+ NumberFormat *fmt = NumberFormat::createInstance(locale, UNUM_CURRENCY_PLURAL, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating NumberFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString formattedNum;
+ fmt->format(11234.567, formattedNum, NULL, status);
+ assertEquals("", "11,234.57 US dollars", formattedNum);
+ delete fmt;
+}
+
+void NumberFormatTest::TestCtorApplyPatternDifference() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en_US", status);
+ UnicodeString pattern("\\u00a40");
+ DecimalFormat fmt(pattern.unescape(), sym, status);
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
+ return;
+ }
+ UnicodeString result;
+ assertEquals(
+ "ctor favors precision of currency",
+ "$5.00",
+ fmt.format((double)5, result));
+ result.remove();
+ fmt.applyPattern(pattern.unescape(), status);
+ assertEquals(
+ "applyPattern favors precision of pattern",
+ "$5",
+ fmt.format((double)5, result));
+}
+
+void NumberFormatTest::Test11868() {
+ double posAmt = 34.567;
+ double negAmt = -9876.543;
+
+ Locale selectedLocale("en_US");
+ UErrorCode status = U_ZERO_ERROR;
+
+ UnicodeString result;
+ FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createInstance(
+ selectedLocale, UNUM_CURRENCY_PLURAL, status));
+ if (!assertSuccess("Format creation", status)) {
+ return;
+ }
+ fmt->format(posAmt, result, fpCurr, status);
+ assertEquals("", "34.57 US dollars", result);
+ assertEquals("begin index", 6, fpCurr.getBeginIndex());
+ assertEquals("end index", 16, fpCurr.getEndIndex());
+
+ // Test field position iterator
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_INTEGER_FIELD, 0, 2},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+ {UNUM_FRACTION_FIELD, 3, 5},
+ {UNUM_CURRENCY_FIELD, 6, 16},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt->format(posAmt, result, &iter, status);
+ assertEquals("", "34.57 US dollars", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+
+ result.remove();
+ fmt->format(negAmt, result, fpCurr, status);
+ assertEquals("", "-9,876.54 US dollars", result);
+ assertEquals("begin index", 10, fpCurr.getBeginIndex());
+ assertEquals("end index", 20, fpCurr.getEndIndex());
+
+ // Test field position iterator
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
+ {UNUM_INTEGER_FIELD, 1, 6},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
+ {UNUM_FRACTION_FIELD, 7, 9},
+ {UNUM_CURRENCY_FIELD, 10, 20},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt->format(negAmt, result, &iter, status);
+ assertEquals("", "-9,876.54 US dollars", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+}
+
+void NumberFormatTest::Test10727_RoundingZero() {
+ IcuTestErrorCode status(*this, "Test10727_RoundingZero");
+ DecimalQuantity dq;
+ dq.setToDouble(-0.0);
+ assertTrue("", dq.isNegative());
+ dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
+ assertTrue("", dq.isNegative());
+}
+
+void NumberFormatTest::Test11739_ParseLongCurrency() {
+ IcuTestErrorCode status(*this, "Test11739_ParseLongCurrency");
+ LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("sr_BA", status));
+ if (status.errDataIfFailureAndReset()) { return; }
+ ((DecimalFormat*) nf.getAlias())->applyPattern(u"#,##0.0 ¤¤¤", status);
+ ParsePosition ppos(0);
+ LocalPointer<CurrencyAmount> result(nf->parseCurrency(u"1.500 амерички долар", ppos));
+ assertEquals("Should parse to 1500 USD", -1, ppos.getErrorIndex());
+ assertEquals("Should parse to 1500 USD", 1500LL, result->getNumber().getInt64(status));
+ assertEquals("Should parse to 1500 USD", u"USD", result->getISOCurrency());
+}
+
+void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
+ IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
+ DecimalFormat df(u"a*'நி'###0b", status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ UnicodeString result;
+ df.format(12, result.remove());
+ // TODO(13034): Re-enable this test when support is added in ICU4C.
+ //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
+ df = DecimalFormat(u"a*\U0001F601###0b", status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ result = df.format(12, result.remove());
+ assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
+ df = DecimalFormat(u"a*''###0b", status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ result = df.format(12, result.remove());
+ assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
+}
+
+void NumberFormatTest::Test13737_ParseScientificStrict() {
+ IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
+ LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
+ df->setLenient(FALSE);
+ // Parse Test
+ expect(*df, u"1.2", 1.2);
+}
+
+void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
+ {
+ const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createCurrencyInstance("en", status));
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+ dfmt->setCurrency(USD);
+ UnicodeString result;
+
+ // This line should be a no-op. I am setting the positive prefix
+ // to be the same thing it was before.
+ dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));
+
+ UnicodeString appendTo;
+ assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
+ assertSuccess("", status);
+ }
+ {
+ const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> fmt(
+ NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
+ UnicodeString result;
+ UnicodeString tripleIntlCurrency(" \\u00a4\\u00a4\\u00a4");
+ tripleIntlCurrency = tripleIntlCurrency.unescape();
+ assertEquals("", tripleIntlCurrency, dfmt->getPositiveSuffix(result)); // use ICU 61 behavior
+ dfmt->setCurrency(USD);
+
+ // getPositiveSuffix() always returns the suffix for the
+ // "other" plural category
+ assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+ UnicodeString appendTo;
+ assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
+ assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
+ dfmt->setPositiveSuffix("booya");
+ appendTo.remove();
+ assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
+ assertEquals("", "booya", dfmt->getPositiveSuffix(result));
+ }
+}
+
+void NumberFormatTest::Test11475_signRecognition() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym("en", status);
+ UnicodeString result;
+ {
+ DecimalFormat fmt("+0.00", sym, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_INTEGER_FIELD, 1, 2},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
+ {UNUM_FRACTION_FIELD, 3, 5},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(2.3, result, &iter, status);
+ assertEquals("", "+2.30", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ {
+ DecimalFormat fmt("++0.00+;-(#)--", sym, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 2},
+ {UNUM_INTEGER_FIELD, 2, 3},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+ {UNUM_FRACTION_FIELD, 4, 6},
+ {UNUM_SIGN_FIELD, 6, 7},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(2.3, result, &iter, status);
+ assertEquals("", "++2.30+", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ {
+ NumberFormatTest_Attributes attributes[] = {
+ {UNUM_SIGN_FIELD, 0, 1},
+ {UNUM_INTEGER_FIELD, 2, 3},
+ {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
+ {UNUM_FRACTION_FIELD, 4, 6},
+ {UNUM_SIGN_FIELD, 7, 9},
+ {0, -1, 0}};
+ UnicodeString result;
+ FieldPositionIterator iter;
+ fmt.format(-2.3, result, &iter, status);
+ assertEquals("", "-(2.30)--", result);
+ verifyFieldPositionIterator(attributes, iter);
+ }
+ }
+}
+
+void NumberFormatTest::Test11640_getAffixes() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols("en_US", status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00 %\\u00a4\\u00a4");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, symbols, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ UnicodeString affixStr;
+ assertEquals("", "US dollars ", fmt.getPositivePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getPositiveSuffix(affixStr));
+ assertEquals("", "-US dollars ", fmt.getNegativePrefix(affixStr));
+ assertEquals("", " %USD", fmt.getNegativeSuffix(affixStr));
+}
+
+void NumberFormatTest::Test11649_toPatternWithMultiCurrency() {
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
+ pattern = pattern.unescape();
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat fmt(pattern, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ static UChar USD[] = {0x55, 0x53, 0x44, 0x0};
+ fmt.setCurrency(USD);
+ UnicodeString appendTo;
+
+ assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
+
+ UnicodeString topattern;
+ fmt.toPattern(topattern);
+ DecimalFormat fmt2(topattern, status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+ fmt2.setCurrency(USD);
+
+ appendTo.remove();
+ assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
+}
+
+void NumberFormatTest::Test13327_numberingSystemBufferOverflow() {
+ UErrorCode status = U_ZERO_ERROR;
+ for (int runId = 0; runId < 2; runId++) {
+ // Construct a locale string with a very long "numbers" value.
+ // The first time, make the value length exactly equal to ULOC_KEYWORDS_CAPACITY.
+ // The second time, make it exceed ULOC_KEYWORDS_CAPACITY.
+ int extraLength = (runId == 0) ? 0 : 5;
+
+ CharString localeId("en@numbers=", status);
+ for (int i = 0; i < ULOC_KEYWORDS_CAPACITY + extraLength; i++) {
+ localeId.append('x', status);
+ }
+ assertSuccess("Constructing locale string", status);
+ Locale locale(localeId.data());
+
+ LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(locale, status));
+ assertFalse("Should not be null", ns.getAlias() == nullptr);
+ assertSuccess("Should create with no error", status);
+ }
+}
+
+void NumberFormatTest::Test13391_chakmaParsing() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
+ NumberFormat::createInstance(Locale("ccp"), status)));
+ if (df == nullptr) {
+ dataerrln("%s %d Chakma df is null", __FILE__, __LINE__);
+ return;
+ }
+ const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
+ UnicodeString actual;
+ df->format(12345, actual, status);
+ assertSuccess("Should not fail when formatting in ccp", status);
+ assertEquals("Should produce expected output in ccp", expected, actual);
+
+ Formattable result;
+ df->parse(expected, result, status);
+ assertSuccess("Should not fail when parsing in ccp", status);
+ assertEquals("Should parse to 12345 in ccp", 12345, result);
+
+ const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
+ UnicodeString actualScientific;
+ df.adoptInstead(static_cast<DecimalFormat*>(
+ NumberFormat::createScientificInstance(Locale("ccp"), status)));
+ df->format(130, actualScientific, status);
+ assertSuccess("Should not fail when formatting scientific in ccp", status);
+ assertEquals("Should produce expected scientific output in ccp",
+ expectedScientific, actualScientific);
+
+ Formattable resultScientific;
+ df->parse(expectedScientific, resultScientific, status);
+ assertSuccess("Should not fail when parsing scientific in ccp", status);
+ assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
+}
+
+
+void NumberFormatTest::verifyFieldPositionIterator(
+ NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
+ int32_t idx = 0;
+ FieldPosition fp;
+ while (iter.next(fp)) {
+ if (expected[idx].spos == -1) {
+ errln("Iterator should have ended. got %d", fp.getField());
+ return;
+ }
+ assertEquals("id", expected[idx].id, fp.getField());
+ assertEquals("start", expected[idx].spos, fp.getBeginIndex());
+ assertEquals("end", expected[idx].epos, fp.getEndIndex());
+ ++idx;
+ }
+ if (expected[idx].spos != -1) {
+ errln("Premature end of iterator. expected %d", expected[idx].id);
+ }
+}
+
+void NumberFormatTest::Test11735_ExceptionIssue() {
+ IcuTestErrorCode status(*this, "Test11735_ExceptionIssue");
+ Locale enLocale("en");
+ DecimalFormatSymbols symbols(enLocale, status);
+ if (status.isSuccess()) {
+ DecimalFormat fmt("0", symbols, status);
+ assertSuccess("Fail: Construct DecimalFormat formatter", status, true, __FILE__, __LINE__);
+ ParsePosition ppos(0);
+ fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
+ assertEquals("Issue11735 ppos", 0, ppos.getIndex());
+ }
+}
+
+void NumberFormatTest::Test11035_FormatCurrencyAmount() {
+ UErrorCode status = U_ZERO_ERROR;
+ double amount = 12345.67;
+ const char16_t* expected = u"12,345$67 ";
+
+ // Test two ways to set a currency via API
+
+ Locale loc1 = Locale("pt_PT");
+ LocalPointer<NumberFormat> fmt1(NumberFormat::createCurrencyInstance("loc1", status),
+ status);
+ if (U_FAILURE(status)) {
+ dataerrln("%s %d NumberFormat instance fmt1 is null", __FILE__, __LINE__);
+ return;
+ }
+ fmt1->setCurrency(u"PTE", status);
+ assertSuccess("Setting currency on fmt1", status);
+ UnicodeString actualSetCurrency;
+ fmt1->format(amount, actualSetCurrency);
+
+ Locale loc2 = Locale("pt_PT@currency=PTE");
+ LocalPointer<NumberFormat> fmt2(NumberFormat::createCurrencyInstance(loc2, status));
+ assertSuccess("Creating fmt2", status);
+ UnicodeString actualLocaleString;
+ fmt2->format(amount, actualLocaleString);
+
+ // TODO: The following test will fail until DecimalFormat wraps NumberFormatter.
+ if (!logKnownIssue("13574")) {
+ assertEquals("Custom Currency Pattern, Set Currency", expected, actualSetCurrency);
+ }
+}
+
+void NumberFormatTest::Test11318_DoubleConversion() {
+ IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
+ if (U_FAILURE(status)) {
+ dataerrln("%s %d Error in NumberFormat instance creation", __FILE__, __LINE__);
+ return;
+ }
+ nf->setMaximumFractionDigits(40);
+ nf->setMaximumIntegerDigits(40);
+ DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf.getAlias());
+ if (df != NULL) {
+ UErrorCode status = U_ZERO_ERROR;
+ df->setAttribute(UNUM_FORMAT_WITH_FULL_PRECISION, TRUE, status); // Apple
+ }
+ UnicodeString appendTo;
+ nf->format(999999999999999.9, appendTo);
+ assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
+}
+
+void NumberFormatTest::TestParsePercentRegression() {
+ IcuTestErrorCode status(*this, "TestParsePercentRegression");
+ LocalPointer<DecimalFormat> df1((DecimalFormat*) NumberFormat::createInstance("en", status), status);
+ LocalPointer<DecimalFormat> df2((DecimalFormat*) NumberFormat::createPercentInstance("en", status), status);
+ if (status.isFailure()) {return; }
+ df1->setLenient(TRUE);
+ df2->setLenient(TRUE);
+
+ {
+ ParsePosition ppos;
+ Formattable result;
+ df1->parse("50%", result, ppos);
+ assertEquals("df1 should accept a number but not the percent sign", 2, ppos.getIndex());
+ assertEquals("df1 should return the number as 50", 50.0, result.getDouble(status));
+ }
+ {
+ ParsePosition ppos;
+ Formattable result;
+ df2->parse("50%", result, ppos);
+ assertEquals("df2 should accept the percent sign", 3, ppos.getIndex());
+ assertEquals("df2 should return the number as 0.5", 0.5, result.getDouble(status));
+ }
+ {
+ ParsePosition ppos;
+ Formattable result;
+ df2->parse("50", result, ppos);
+ assertEquals("df2 should return the number as 0.5 even though the percent sign is missing",
+ 0.5,
+ result.getDouble(status));
+ }
+}
+
+void NumberFormatTest::TestMultiplierWithScale() {
+ // to be added
+}
+
+void NumberFormatTest::TestFastFormatInt32() {
+ IcuTestErrorCode status(*this, "TestFastFormatInt32");
+
+ // The two simplest formatters, old API and new API.
+ // Old API should use the fastpath for ints.
+ LocalizedNumberFormatter lnf = NumberFormatter::withLocale("en");
+ LocalPointer<NumberFormat> df(NumberFormat::createInstance("en", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
+
+ double nums[] = {
+ 0.0,
+ -0.0,
+ NAN,
+ INFINITY,
+ 0.1,
+ 1.0,
+ 1.1,
+ 2.0,
+ 3.0,
+ 9.0,
+ 10.0,
+ 99.0,
+ 100.0,
+ 999.0,
+ 1000.0,
+ 9999.0,
+ 10000.0,
+ 99999.0,
+ 100000.0,
+ 999999.0,
+ 1000000.0,
+ static_cast<double>(INT32_MAX) - 1,
+ static_cast<double>(INT32_MAX),
+ static_cast<double>(INT32_MAX) + 1,
+ static_cast<double>(INT32_MIN) - 1,
+ static_cast<double>(INT32_MIN),
+ static_cast<double>(INT32_MIN) + 1};
+
+ for (auto num : nums) {
+ UnicodeString expected = lnf.formatDouble(num, status).toString();
+ UnicodeString actual;
+ df->format(num, actual);
+ assertEquals(UnicodeString("d = ") + num, expected, actual);
+ }
+}
+
+void NumberFormatTest::Test11646_Equality() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale::getEnglish(), status);
+ UnicodeString pattern(u"\u00a4\u00a4\u00a4 0.00 %\u00a4\u00a4");
+ DecimalFormat fmt(pattern, symbols, status);
+ if (!assertSuccess("", status)) return;
+
+ // Test equality with affixes. set affix methods can't capture special
+ // characters which is why equality should fail.
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString positivePrefix;
+ fmtCopy.setPositivePrefix(fmtCopy.getPositivePrefix(positivePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy = DecimalFormat(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString positivePrefix;
+ fmtCopy.setPositiveSuffix(fmtCopy.getPositiveSuffix(positivePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString negativePrefix;
+ fmtCopy.setNegativePrefix(fmtCopy.getNegativePrefix(negativePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+ {
+ DecimalFormat fmtCopy(fmt);
+ assertTrue("", fmt == fmtCopy);
+ UnicodeString negativePrefix;
+ fmtCopy.setNegativeSuffix(fmtCopy.getNegativeSuffix(negativePrefix));
+ assertFalse("", fmt == fmtCopy);
+ }
+}
+
+void NumberFormatTest::TestParseNaN() {
+ IcuTestErrorCode status(*this, "TestParseNaN");
+
+ DecimalFormat df("0", { "en", status }, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ Formattable parseResult;
+ df.parse(u"NaN", parseResult, status);
+ assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
+ assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
+ UnicodeString formatResult;
+ df.format(parseResult.getDouble(), formatResult);
+ assertEquals("NaN should round-trip", u"NaN", formatResult);
+}
+
+void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
+ IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");
+
+ // In a locale with a different <list> symbol, like arabic,
+ // kPatternSeparatorSymbol should still be ';'
+ {
+ DecimalFormatSymbols dfs("ar", status);
+ assertEquals("pattern separator symbol should be ;",
+ u";",
+ dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
+ }
+
+ // However, the custom symbol should be used in localized notation
+ // when set manually via API
+ {
+ DecimalFormatSymbols dfs("en", status);
+ dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
+ DecimalFormat df(u"0", dfs, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ df.applyPattern("a0;b0", status); // should not throw
+ UnicodeString result;
+ assertEquals("should apply the normal pattern",
+ df.getNegativePrefix(result.remove()),
+ "b");
+ df.applyLocalizedPattern(u"c0!d0", status); // should not throw
+ assertEquals("should apply the localized pattern",
+ df.getNegativePrefix(result.remove()),
+ "d");
+ }
+}
+
+void NumberFormatTest::Test13055_PercentageRounding() {
+ IcuTestErrorCode status(*this, "PercentageRounding");
+ UnicodeString actual;
+ LocalPointer<NumberFormat>pFormat(NumberFormat::createPercentInstance("en_US", status));
+ if (U_FAILURE(status)) {
+ dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+ return;
+ }
+ pFormat->setMaximumFractionDigits(0);
+ pFormat->setRoundingMode(DecimalFormat::kRoundHalfEven);
+ pFormat->format(2.155, actual);
+ assertEquals("Should round percent toward even number", "216%", actual);
+}
+
+void NumberFormatTest::Test11839() {
+ IcuTestErrorCode errorCode(*this, "Test11839");
+ // Ticket #11839: DecimalFormat does not respect custom plus sign
+ LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(Locale::getEnglish(), errorCode), errorCode);
+ if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
+ dfs->setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"a∸");
+ dfs->setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"b∔"); // ∔ U+2214 DOT PLUS
+ DecimalFormat df(u"0.00+;0.00-", dfs.orphan(), errorCode);
+ UnicodeString result;
+ df.format(-1.234, result, errorCode);
+ assertEquals("Locale-specific minus sign should be used", u"1.23a∸", result);
+ df.format(1.234, result.remove(), errorCode);
+ assertEquals("Locale-specific plus sign should be used", u"1.23b∔", result);
+ // Test round-trip with parse
+ expect2(df, -456, u"456.00a∸");
+ expect2(df, 456, u"456.00b∔");
+}
+
+void NumberFormatTest::Test10354() {
+ IcuTestErrorCode errorCode(*this, "Test10354");
+ // Ticket #10354: invalid FieldPositionIterator when formatting with empty NaN
+ DecimalFormatSymbols dfs(errorCode);
+ UnicodeString empty;
+ dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, empty);
+ DecimalFormat df(errorCode);
+ df.setDecimalFormatSymbols(dfs);
+ UnicodeString result;
+ FieldPositionIterator positions;
+ df.format(NAN, result, &positions, errorCode);
+ errorCode.errIfFailureAndReset("DecimalFormat.format(NAN, FieldPositionIterator) failed");
+ FieldPosition fp;
+ while (positions.next(fp)) {
+ // Should not loop forever
+ }
+}
+
+void NumberFormatTest::Test11645_ApplyPatternEquality() {
+ IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
+ const char16_t* pattern = u"#,##0.0#";
+ LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ fmt->applyPattern(pattern, status);
+ LocalPointer<DecimalFormat> fmtCopy;
+
+ static const int32_t newMultiplier = 37;
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
+ fmtCopy->setMultiplier(newMultiplier);
+ assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
+ fmtCopy->applyPattern(pattern, status);
+ //assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
+ //assertFalse("multiplier", *fmt == *fmtCopy);
+
+ static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
+ fmtCopy->setRoundingMode(newRoundingMode);
+ assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
+ fmtCopy->applyPattern(pattern, status);
+ assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
+ assertFalse("roundingMode", *fmt == *fmtCopy);
+
+ static const char16_t *const newCurrency = u"EAT";
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
+ fmtCopy->setCurrency(newCurrency);
+ assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
+ fmtCopy->applyPattern(pattern, status);
+ assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
+ assertFalse("currency", *fmt == *fmtCopy);
+
+ static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
+ fmtCopy.adoptInstead(new DecimalFormat(*fmt));
+ assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
+ fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
+ assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
+ fmtCopy->applyPattern(pattern, status);
+ assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
+ assertFalse("currencyUsage", *fmt == *fmtCopy);
+}
+
+void NumberFormatTest::Test12567() {
+ IcuTestErrorCode errorCode(*this, "Test12567");
+ // Ticket #12567: DecimalFormat.equals() may not be symmetric
+ LocalPointer<DecimalFormat> df1((DecimalFormat *)
+ NumberFormat::createInstance(Locale::getUS(), UNUM_CURRENCY, errorCode));
+ LocalPointer<DecimalFormat> df2((DecimalFormat *)
+ NumberFormat::createInstance(Locale::getUS(), UNUM_DECIMAL, errorCode));
+ if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
+ // NOTE: CurrencyPluralInfo equality not tested in C++ because its operator== is not defined.
+ df1->applyPattern(u"0.00", errorCode);
+ df2->applyPattern(u"0.00", errorCode);
+ //assertTrue("df1 == df2", *df1 == *df2);
+ //assertTrue("df2 == df1", *df2 == *df1);
+ df2->setPositivePrefix(u"abc");
+ assertTrue("df1 != df2", *df1 != *df2);
+ assertTrue("df2 != df1", *df2 != *df1);
+}
+
+void NumberFormatTest::Test11626_CustomizeCurrencyPluralInfo() {
+ IcuTestErrorCode errorCode(*this, "Test11626_CustomizeCurrencyPluralInfo");
+ // Ticket #11626: No unit test demonstrating how to use CurrencyPluralInfo to
+ // change formatting spelled out currencies
+ // Use locale sr because it has interesting plural rules.
+ Locale locale("sr");
+ LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols(locale, errorCode), errorCode);
+ CurrencyPluralInfo info(locale, errorCode);
+ if (!assertSuccess("", errorCode, true, __FILE__, __LINE__)) { return; }
+ info.setCurrencyPluralPattern(u"one", u"0 qwerty", errorCode);
+ info.setCurrencyPluralPattern(u"few", u"0 dvorak", errorCode);
+ DecimalFormat df(u"#", symbols.orphan(), UNUM_CURRENCY_PLURAL, errorCode);
+ df.setCurrencyPluralInfo(info);
+ df.setCurrency(u"USD");
+ df.setMaximumFractionDigits(0);
+
+ UnicodeString result;
+ //assertEquals("Plural one", u"1 qwerty", df.format(1, result, errorCode));
+ //assertEquals("Plural few", u"3 dvorak", df.format(3, result.remove(), errorCode));
+ assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
+
+ info.setPluralRules(u"few: n is 1; one: n in 2..4", errorCode);
+ df.setCurrencyPluralInfo(info);
+ //assertEquals("Plural one", u"1 dvorak", df.format(1, result.remove(), errorCode));
+ //assertEquals("Plural few", u"3 qwerty", df.format(3, result.remove(), errorCode));
+ assertEquals("Plural other", u"99 америчких долара", df.format(99, result.remove(), errorCode));
+}
+
+void NumberFormatTest::Test13056_GroupingSize() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat df(u"#,##0", status);
+ if (!assertSuccess("", status)) return;
+ assertEquals("Primary grouping should return 3", 3, df.getGroupingSize());
+ assertEquals("Secondary grouping should return 0", 0, df.getSecondaryGroupingSize());
+ df.setSecondaryGroupingSize(3);
+ assertEquals("Primary grouping should still return 3", 3, df.getGroupingSize());
+ assertEquals("Secondary grouping should round-trip", 3, df.getSecondaryGroupingSize());
+ df.setGroupingSize(4);
+ assertEquals("Primary grouping should return 4", 4, df.getGroupingSize());
+ assertEquals("Secondary should remember explicit setting and return 3", 3, df.getSecondaryGroupingSize());
+}
+
+
+void NumberFormatTest::Test11025_CurrencyPadding() {
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString pattern(u"¤¤ **####0.00");
+ DecimalFormatSymbols sym(Locale::getFrance(), status);
+ if (!assertSuccess("", status)) return;
+ DecimalFormat fmt(pattern, sym, status);
+ if (!assertSuccess("", status)) return;
+ UnicodeString result;
+ fmt.format(433.0, result);
+ assertEquals("Number should be padded to 11 characters", "EUR *433,00", result);
+}
+
+void NumberFormatTest::Test11648_ExpDecFormatMalPattern() {
+ UErrorCode status = U_ZERO_ERROR;
+
+ DecimalFormat fmt("0.00", {"en", status}, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ fmt.setScientificNotation(TRUE);
+ UnicodeString pattern;
+
+ assertEquals("A valid scientific notation pattern should be produced",
+ "0.00E0",
+ fmt.toPattern(pattern));
+
+ DecimalFormat fmt2(pattern, status);
+ assertSuccess("", status);
+}
+
+void NumberFormatTest::Test11649_DecFmtCurrencies() {
+ IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
+ UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
+ pattern = pattern.unescape();
+ DecimalFormat fmt(pattern, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ static const UChar USD[] = u"USD";
+ fmt.setCurrency(USD);
+ UnicodeString appendTo;
+
+ assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
+ UnicodeString topattern;
+
+ // assertEquals("", pattern, fmt.toPattern(topattern));
+ DecimalFormat fmt2(topattern, status);
+ fmt2.setCurrency(USD);
+
+ appendTo.remove();
+ assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
+}
+
+void NumberFormatTest::Test13148_ParseGroupingSeparators() {
+ IcuTestErrorCode status(*this, "Test13148");
+ LocalPointer<DecimalFormat> fmt(
+ (DecimalFormat*)NumberFormat::createInstance("en-ZA", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+
+ DecimalFormatSymbols symbols = *fmt->getDecimalFormatSymbols();
+
+ symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'.');
+ symbols.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u',');
+ fmt->setDecimalFormatSymbols(symbols);
+ Formattable number;
+ fmt->parse(u"300,000", number, status);
+ assertEquals("Should parse as 300000", 300000LL, number.getInt64(status));
+}
+
+void NumberFormatTest::Test12753_PatternDecimalPoint() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols symbols(Locale::getUS(), status);
+ symbols.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"*", false);
+ DecimalFormat df(u"0.00", symbols, status);
+ if (!assertSuccess("", status)) return;
+ df.setDecimalPatternMatchRequired(true);
+ Formattable result;
+ df.parse(u"123",result, status);
+ assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set",
+ U_INVALID_FORMAT_ERROR, status);
+ }
+
+ void NumberFormatTest::Test11647_PatternCurrencySymbols() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormat df(status);
+ df.applyPattern(u"¤¤¤¤#", status);
+ if (!assertSuccess("", status)) return;
+ UnicodeString actual;
+ df.format(123, actual);
+ //assertEquals("Should replace 4 currency signs with U+FFFD", u"\uFFFD123", actual);
+}
+
+void NumberFormatTest::Test11913_BigDecimal() {
+ UErrorCode status = U_ZERO_ERROR;
+ LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
+ if (!assertSuccess("", status)) return;
+ UnicodeString result;
+ df->format(StringPiece("1.23456789E400"), result, nullptr, status);
+ assertSuccess("", status);
+ assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
+ assertEquals("Should format more than 309 digits", 534, result.length());
+}
+
+void NumberFormatTest::Test11020_RoundingInScientificNotation() {
+ UErrorCode status = U_ZERO_ERROR;
+ DecimalFormatSymbols sym(Locale::getFrance(), status);
+ DecimalFormat fmt(u"0.05E0", sym, status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ assertSuccess("", status);
+ UnicodeString result;
+ fmt.format(12301.2, result);
+ assertEquals("Rounding increment should be applied after magnitude scaling", u"1,25E4", result);
+}
+
+void NumberFormatTest::Test11640_TripleCurrencySymbol() {
+ IcuTestErrorCode status(*this, "Test11640_TripleCurrencySymbol");
+ UnicodeString actual;
+ DecimalFormat dFormat(u"¤¤¤ 0", status);
+ if (U_FAILURE(status)) {
+ dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
+ return;
+ }
+ dFormat.setCurrency(u"USD");
+ UnicodeString result;
+ dFormat.getPositivePrefix(result);
+ assertEquals("Triple-currency should give long name on getPositivePrefix",
+ "US dollars ", result);
+}
+
+
+void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
+ IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
+ FieldPositionIterator fpi;
+ UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
+ LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ nf->format(5142.3, result, &fpi, status);
+
+ int32_t expected[] = {
+ UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
+ UNUM_INTEGER_FIELD, 8, 13,
+ UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
+ UNUM_FRACTION_FIELD, 14, 15,
+ };
+ int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
+ expectPositions(fpi, expected, tupleCount, result);
+}
+
+void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
+ IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");
+
+ LocalPointer<NumberFormat> df(
+ NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
+ if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
+ expect2(*df, 1.5, u"1.50 US dollars");
+}
+
+void NumberFormatTest::Test13804_EmptyStringsWhenParsing() {
+ IcuTestErrorCode status(*this, "Test13804_EmptyStringsWhenParsing");
+
+ DecimalFormatSymbols dfs("en", status);
+ if (status.errIfFailureAndReset()) {
+ return;
+ }
+ dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kThreeDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kFourDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kSixDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kSevenDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kEightDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kNineDigitSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kExponentMultiplicationSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"", FALSE);
+ dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
+ dfs.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
+ dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u"", FALSE);
+ dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u"", FALSE);
+
+ DecimalFormat df("0", dfs, status);
+ if (status.errIfFailureAndReset()) {
+ return;
+ }
+ df.setGroupingUsed(TRUE);
+ df.setScientificNotation(TRUE);
+ df.setLenient(TRUE); // enable all matchers
+ {
+ UnicodeString result;
+ df.format(0, result); // should not crash or hit infinite loop
+ }
+ const char16_t* samples[] = {
+ u"",
+ u"123",
+ u"$123",
+ u"-",
+ u"+",
+ u"44%",
+ u"1E+2.3"
+ };
+ for (auto& sample : samples) {
+ logln(UnicodeString(u"Attempting parse on: ") + sample);
+ status.setScope(sample);
+ // We don't care about the results, only that we don't crash and don't loop.
+ Formattable result;
+ ParsePosition ppos(0);
+ df.parse(sample, result, ppos);
+ ppos = ParsePosition(0);
+ LocalPointer<CurrencyAmount> curramt(df.parseCurrency(sample, ppos));
+ status.errIfFailureAndReset();
+ }
+
+ // Test with a nonempty exponent separator symbol to cover more code
+ dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"E", FALSE);
+ df.setDecimalFormatSymbols(dfs);
+ {
+ Formattable result;
+ ParsePosition ppos(0);
+ df.parse(u"1E+2.3", result, ppos);
+ }
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */