/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2014, International Business Machines Corporation and
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/* Modification History:
#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 "datadrivennumberformattestsuite.h"
+#include "unicode/msgfmt.h"
+
+class NumberFormatTestDataDriven : public DataDrivenNumberFormatTestSuite {
+protected:
+UBool isFormatPass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status);
+UBool isToPatternPass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status);
+UBool isParsePass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status);
+UBool isParseCurrencyPass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status);
+};
+
+static DigitList &strToDigitList(
+ const UnicodeString &str,
+ DigitList &digitList,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return digitList;
+ }
+ if (str == "NaN") {
+ digitList.set(uprv_getNaN());
+ return digitList;
+ }
+ if (str == "-Inf") {
+ digitList.set(-1*uprv_getInfinity());
+ return digitList;
+ }
+ if (str == "Inf") {
+ digitList.set(uprv_getInfinity());
+ return digitList;
+ }
+ CharString formatValue;
+ formatValue.appendInvariantChars(str, status);
+ digitList.set(StringPiece(formatValue.data()), status, 0);
+ return digitList;
+}
+
+static UnicodeString &format(
+ const DecimalFormat &fmt,
+ const DigitList &digitList,
+ UnicodeString &appendTo,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return appendTo;
+ }
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ return fmt.format(digitList, appendTo, fpos, status);
+}
+
+template<class T>
+static UnicodeString &format(
+ const DecimalFormat &fmt,
+ T value,
+ UnicodeString &appendTo,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return appendTo;
+ }
+ FieldPosition fpos(FieldPosition::DONT_CARE);
+ return fmt.format(value, appendTo, fpos, status);
+}
+
+static void adjustDecimalFormat(
+ const NumberFormatTestTuple &tuple,
+ DecimalFormat &fmt,
+ UnicodeString &appendErrorMessage) {
+ if (tuple.minIntegerDigitsFlag) {
+ fmt.setMinimumIntegerDigits(tuple.minIntegerDigits);
+ }
+ if (tuple.maxIntegerDigitsFlag) {
+ fmt.setMaximumIntegerDigits(tuple.maxIntegerDigits);
+ }
+ if (tuple.minFractionDigitsFlag) {
+ fmt.setMinimumFractionDigits(tuple.minFractionDigits);
+ }
+ if (tuple.maxFractionDigitsFlag) {
+ fmt.setMaximumFractionDigits(tuple.maxFractionDigits);
+ }
+ if (tuple.currencyFlag) {
+ UErrorCode status = U_ZERO_ERROR;
+ UnicodeString currency(tuple.currency);
+ const UChar *terminatedCurrency = currency.getTerminatedBuffer();
+ fmt.setCurrency(terminatedCurrency, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error setting currency.");
+ }
+ }
+ if (tuple.minGroupingDigitsFlag) {
+ fmt.setMinimumGroupingDigits(tuple.minGroupingDigits);
+ }
+ if (tuple.useSigDigitsFlag) {
+ fmt.setSignificantDigitsUsed(tuple.useSigDigits != 0);
+ }
+ if (tuple.minSigDigitsFlag) {
+ fmt.setMinimumSignificantDigits(tuple.minSigDigits);
+ }
+ if (tuple.maxSigDigitsFlag) {
+ fmt.setMaximumSignificantDigits(tuple.maxSigDigits);
+ }
+ if (tuple.useGroupingFlag) {
+ fmt.setGroupingUsed(tuple.useGrouping != 0);
+ }
+ if (tuple.multiplierFlag) {
+ fmt.setMultiplier(tuple.multiplier);
+ }
+ if (tuple.roundingIncrementFlag) {
+ fmt.setRoundingIncrement(tuple.roundingIncrement);
+ }
+ if (tuple.formatWidthFlag) {
+ fmt.setFormatWidth(tuple.formatWidth);
+ }
+ if (tuple.padCharacterFlag) {
+ fmt.setPadCharacter(tuple.padCharacter);
+ }
+ if (tuple.useScientificFlag) {
+ fmt.setScientificNotation(tuple.useScientific != 0);
+ }
+ if (tuple.groupingFlag) {
+ fmt.setGroupingSize(tuple.grouping);
+ }
+ if (tuple.grouping2Flag) {
+ fmt.setSecondaryGroupingSize(tuple.grouping2);
+ }
+ if (tuple.roundingModeFlag) {
+ fmt.setRoundingMode(tuple.roundingMode);
+ }
+ if (tuple.currencyUsageFlag) {
+ UErrorCode status = U_ZERO_ERROR;
+ fmt.setCurrencyUsage(tuple.currencyUsage, &status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("CurrencyUsage: error setting.");
+ }
+ }
+ if (tuple.minimumExponentDigitsFlag) {
+ fmt.setMinimumExponentDigits(tuple.minimumExponentDigits);
+ }
+ if (tuple.exponentSignAlwaysShownFlag) {
+ fmt.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
+ }
+ if (tuple.decimalSeparatorAlwaysShownFlag) {
+ fmt.setDecimalSeparatorAlwaysShown(
+ tuple.decimalSeparatorAlwaysShown != 0);
+ }
+ if (tuple.padPositionFlag) {
+ fmt.setPadPosition(tuple.padPosition);
+ }
+ if (tuple.positivePrefixFlag) {
+ fmt.setPositivePrefix(tuple.positivePrefix);
+ }
+ if (tuple.positiveSuffixFlag) {
+ fmt.setPositiveSuffix(tuple.positiveSuffix);
+ }
+ if (tuple.negativePrefixFlag) {
+ fmt.setNegativePrefix(tuple.negativePrefix);
+ }
+ if (tuple.negativeSuffixFlag) {
+ fmt.setNegativeSuffix(tuple.negativeSuffix);
+ }
+ if (tuple.localizedPatternFlag) {
+ UErrorCode status = U_ZERO_ERROR;
+ fmt.applyLocalizedPattern(tuple.localizedPattern, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error setting localized pattern.");
+ }
+ }
+ fmt.setLenient(NFTT_GET_FIELD(tuple, lenient, 1) != 0);
+ if (tuple.parseIntegerOnlyFlag) {
+ fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
+ }
+ if (tuple.decimalPatternMatchRequiredFlag) {
+ fmt.setDecimalPatternMatchRequired(
+ tuple.decimalPatternMatchRequired != 0);
+ }
+ if (tuple.parseNoExponentFlag) {
+ UErrorCode status = U_ZERO_ERROR;
+ fmt.setAttribute(
+ UNUM_PARSE_NO_EXPONENT,
+ tuple.parseNoExponent,
+ status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error setting parse no exponent flag.");
+ }
+ }
+}
+
+static DecimalFormat *newDecimalFormat(
+ const Locale &locale,
+ const UnicodeString &pattern,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ LocalPointer<DecimalFormatSymbols> symbols(
+ new DecimalFormatSymbols(locale, status), status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ UParseError perror;
+ LocalPointer<DecimalFormat> result(new DecimalFormat(
+ pattern, symbols.getAlias(), perror, status), status);
+ if (!result.isNull()) {
+ symbols.orphan();
+ }
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ return result.orphan();
+}
+
+static DecimalFormat *newDecimalFormat(
+ const NumberFormatTestTuple &tuple,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ Locale en("en");
+ return newDecimalFormat(
+ NFTT_GET_FIELD(tuple, locale, en),
+ NFTT_GET_FIELD(tuple, pattern, "0"),
+ status);
+}
+
+UBool NumberFormatTestDataDriven::isFormatPass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error creating DecimalFormat.");
+ return FALSE;
+ }
+ adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+ if (appendErrorMessage.length() > 0) {
+ return FALSE;
+ }
+ DigitList digitList;
+ strToDigitList(tuple.format, digitList, status);
+ {
+ UnicodeString appendTo;
+ format(*fmtPtr, digitList, appendTo, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error formatting.");
+ return FALSE;
+ }
+ if (appendTo != tuple.output) {
+ appendErrorMessage.append(
+ UnicodeString("Expected: ") + tuple.output + ", got: " + appendTo);
+ return FALSE;
+ }
+ }
+ double doubleVal = digitList.getDouble();
+ {
+ UnicodeString appendTo;
+ format(*fmtPtr, doubleVal, appendTo, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error formatting.");
+ return FALSE;
+ }
+ if (appendTo != tuple.output) {
+ appendErrorMessage.append(
+ UnicodeString("double Expected: ") + tuple.output + ", got: " + appendTo);
+ return FALSE;
+ }
+ }
+ if (!uprv_isNaN(doubleVal) && !uprv_isInfinite(doubleVal) && doubleVal == uprv_floor(doubleVal)) {
+ int64_t intVal = digitList.getInt64();
+ {
+ UnicodeString appendTo;
+ format(*fmtPtr, intVal, appendTo, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error formatting.");
+ return FALSE;
+ }
+ if (appendTo != tuple.output) {
+ appendErrorMessage.append(
+ UnicodeString("int64 Expected: ") + tuple.output + ", got: " + appendTo);
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+UBool NumberFormatTestDataDriven::isToPatternPass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error creating DecimalFormat.");
+ return FALSE;
+ }
+ adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+ if (appendErrorMessage.length() > 0) {
+ return FALSE;
+ }
+ if (tuple.toPatternFlag) {
+ UnicodeString actual;
+ fmtPtr->toPattern(actual);
+ if (actual != tuple.toPattern) {
+ appendErrorMessage.append(
+ UnicodeString("Expected: ") + tuple.toPattern + ", got: " + actual + ". ");
+ }
+ }
+ if (tuple.toLocalizedPatternFlag) {
+ UnicodeString actual;
+ fmtPtr->toLocalizedPattern(actual);
+ if (actual != tuple.toLocalizedPattern) {
+ appendErrorMessage.append(
+ UnicodeString("Expected: ") + tuple.toLocalizedPattern + ", got: " + actual + ". ");
+ }
+ }
+ return appendErrorMessage.length() == 0;
+}
+
+UBool NumberFormatTestDataDriven::isParsePass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error creating DecimalFormat.");
+ return FALSE;
+ }
+ adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+ if (appendErrorMessage.length() > 0) {
+ return FALSE;
+ }
+ Formattable result;
+ ParsePosition ppos;
+ fmtPtr->parse(tuple.parse, result, ppos);
+ if (ppos.getIndex() == 0) {
+ if (tuple.output != "fail") {
+ appendErrorMessage.append("Parse failed but was expected to succeed.");
+ return FALSE;
+ }
+ return TRUE;
+ }
+ UnicodeString resultStr(UnicodeString::fromUTF8(result.getDecimalNumber(status)));
+ if (tuple.output == "fail") {
+ appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
+ return FALSE;
+ }
+ DigitList expected;
+ strToDigitList(tuple.output, expected, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error parsing.");
+ return FALSE;
+ }
+ if (expected != *result.getDigitList()) {
+ appendErrorMessage.append(
+ UnicodeString("Expected: ") + tuple.output + ", got: " + resultStr + ". ");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+UBool NumberFormatTestDataDriven::isParseCurrencyPass(
+ const NumberFormatTestTuple &tuple,
+ UnicodeString &appendErrorMessage,
+ UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ LocalPointer<DecimalFormat> fmtPtr(newDecimalFormat(tuple, status));
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error creating DecimalFormat.");
+ return FALSE;
+ }
+ adjustDecimalFormat(tuple, *fmtPtr, appendErrorMessage);
+ if (appendErrorMessage.length() > 0) {
+ return FALSE;
+ }
+ ParsePosition ppos;
+ LocalPointer<CurrencyAmount> currAmt(
+ fmtPtr->parseCurrency(tuple.parse, ppos));
+ if (ppos.getIndex() == 0) {
+ if (tuple.output != "fail") {
+ appendErrorMessage.append("Parse failed but was expected to succeed.");
+ return FALSE;
+ }
+ return TRUE;
+ }
+ UnicodeString currStr(currAmt->getISOCurrency());
+ Formattable resultFormattable(currAmt->getNumber());
+ UnicodeString resultStr(UnicodeString::fromUTF8(resultFormattable.getDecimalNumber(status)));
+ if (tuple.output == "fail") {
+ appendErrorMessage.append(UnicodeString("Parse succeeded: ") + resultStr + ", but was expected to fail.");
+ return FALSE;
+ }
+ DigitList expected;
+ strToDigitList(tuple.output, expected, status);
+ if (U_FAILURE(status)) {
+ appendErrorMessage.append("Error parsing.");
+ return FALSE;
+ }
+ if (expected != *currAmt->getNumber().getDigitList()) {
+ appendErrorMessage.append(
+ UnicodeString("Expected: ") + tuple.output + ", got: " + resultStr + ". ");
+ return FALSE;
+ }
+ if (currStr != tuple.outputCurrency) {
+ appendErrorMessage.append(UnicodeString(
+ "Expected currency: ") + tuple.outputCurrency + ", got: " + currStr + ". ");
+ return FALSE;
+ }
+ return TRUE;
+}
//#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"
TESTCASE_AUTO(TestZeroScientific10547);
TESTCASE_AUTO(TestAccountingCurrency);
TESTCASE_AUTO(TestEquality);
+ TESTCASE_AUTO(TestCurrencyUsage);
+ TESTCASE_AUTO(TestNumberFormatTestTuple);
+ TESTCASE_AUTO(TestDataDriven);
+ TESTCASE_AUTO(TestDoubleLimit11439);
+ TESTCASE_AUTO(TestFastPathConsistent11524);
+ TESTCASE_AUTO(TestGetAffixes);
+ TESTCASE_AUTO(TestToPatternScientific11648);
+ TESTCASE_AUTO(TestBenchmark);
+ TESTCASE_AUTO(TestCtorApplyPatternDifference);
+ TESTCASE_AUTO(TestFractionalDigitsForCurrency);
+ TESTCASE_AUTO(TestFormatCurrencyPlural);
+ TESTCASE_AUTO(Test11868);
+ TESTCASE_AUTO(Test10727_RoundingZero);
+ TESTCASE_AUTO(Test11376_getAndSetPositivePrefix);
+ TESTCASE_AUTO(Test11475_signRecognition);
+ TESTCASE_AUTO(Test11640_getAffixes);
+ TESTCASE_AUTO(Test11649_toPatternWithMultiCurrency);
TESTCASE_AUTO_END;
}
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]));
+ int32_t pat_length = UPRV_LENGTHOF(pat);
const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
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
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");
{"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"}
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");
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);
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,56 CHF"); // no more 0.05 rounding here, see cldrbug 5548
"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);
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);
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);
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);
}
}
- 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);
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);
}
}
- 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);
dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
} 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);
// 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);
// 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"
UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec)),
possibleDataError);
- assertEquals("USD.getName(SYMBOL_NAME) in en_AU",
+ assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
UnicodeString("US$"),
- UnicodeString(ucurr_getName(USD, "en_AU",
+ 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);
}; // 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);
UErrorCode status = U_ZERO_ERROR;
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;
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)){
{ (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;
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 US dollars"
};
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;
{"USD1,234.56", "1234.56"},
{"1,234.56 US dollar", "1234.56"},
};
- for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ 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;
{"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$\\u00A01.00", "USD\\u00A01.00", "1.00\\u7F8E\\u5143"},
- {"zh_CN", "1234.56", "USD", "US$\\u00A01,234.56", "USD\\u00A01,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", "\\uFFE5\\u00A01.00", "CNY\\u00A01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
- {"zh_CN", "1234.56", "CNY", "\\uFFE5\\u00A01,234.56", "CNY\\u00A01,234.56", "1,234.56\\u4EBA\\u6C11\\u5E01"},
+ {"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", "\\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\\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", "INR1,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) {
+ 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]);
// format result using PLURALCURRENCYSTYLE,
{"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
{"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
- {"es_AR", "1", "USD", "US$1,00", "USD1,00", "1,00 d\\u00f3lar estadounidense"},
+ {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
{"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
{"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u200e\\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627\\u06f1\\u066b\\u06f0\\u06f0"},
- {"he_IL", "1", "USD", "1.00\\u00a0US$", "1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
+ {"he_IL", "1", "USD", "1.00\\u00a0$", "1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
{"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 Ameri\\u010dki dolar"},
{"id_ID", "1", "USD", "US$1,00", "USD1,00", "1,00 Dolar Amerika Serikat"},
{"it_IT", "1", "USD", "1,00\\u00a0US$", "1,00\\u00a0USD", "1,00 Dollaro Statunitense"},
{"ko_KR", "1", "USD", "US$1.00", "USD1.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
- {"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00 \\u7c73\\u30c9\\u30eb"},
- {"zh_CN", "1", "CNY", "\\uFFE5\\u00a01.00", "CNY\\u00a01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
+ {"ja_JP", "1", "USD", "$1.00", "USD1.00", "1.00\\u7c73\\u30c9\\u30eb"},
+ {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY01.00", "1.00\\u4EBA\\u6C11\\u5E01"},
{"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
{"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY1.00", "1.00 \\u4eba\\u6c11\\u5e63"},
{"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u5713"},
- {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00 \\u65e5\\u672c\\u5186"},
- {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00 \\u65e5\\u672c\\u5186"},
+ {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
+ {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY1.00", "1.00\\u65e5\\u672c\\u5186"},
{"ru_RU", "1", "RUB", "1,00\\u00A0\\u20BD", "1,00\\u00A0RUB", "1,00 \\u0420\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u0438\\u0439 \\u0440\\u0443\\u0431\\u043B\\u044C"}
};
static const UNumberFormatStyle currencyStyles[] = {
for (;;) {
printf("loop: %d\n", deadloop++);
#endif
- for (uint32_t i=0; i< sizeof(DATA)/sizeof(DATA[0]); ++i) { /* i = test case # - should be i=0*/
- for (int32_t kIndex = 2; kIndex < LENGTHOF(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]);
"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",
"RSD1.00",
"RSD1.00",
"RUB1.00",
- "RUB1.00",
"RUR1.00",
"RUR1.00",
"RWF1.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",
"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",
"unknown currency1.00",
"\\u00a31.00",
"\\u00a51.00",
- "\\u0e3f1.00",
"\\u20ab1.00",
"\\u20aa1.00",
"\\u20ac1.00",
"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 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 Uruguayan peso 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",
"C1.00",
"CA1.00",
"CD1.00",
- "CFA Franc BCEA1.00",
- "CFA Franc BEA1.00",
"CFP Fran1.00",
"CFP1.00",
"CH1.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",
"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",
};
Locale locale("en_US");
- for (uint32_t i=0; i<sizeof(DATA)/sizeof(DATA[0]); ++i) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
UnicodeString formatted = ctou(DATA[i]);
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
delete numFmt;
}
- 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);
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;
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);
}
{
UErrorCode status=U_ZERO_ERROR;
DecimalFormat df(UnicodeString("0000",""),status);
- int64_t long_number = 1;
- UnicodeString expect = "0001";
- UnicodeString result;
- FieldPosition pos;
- df.format(long_number, result, pos);
- if(U_FAILURE(status)||expect!=result) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ int64_t long_number = 1;
+ UnicodeString expect = "0001";
+ UnicodeString result;
+ FieldPosition pos;
+ df.format(long_number, result, pos);
+ if(U_FAILURE(status)||expect!=result) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- 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) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ 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) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- 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) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ 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) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
+ } 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);
- 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) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ 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) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
+ }
}
}
{
UErrorCode status=U_ZERO_ERROR;
DecimalFormat df(UnicodeString("0000000000000000000",""),status);
- 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) {
- errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ if (U_FAILURE(status)) {
+ dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
} else {
- logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ 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) {
+ errcheckln(status, "FAIL: expected '"+expect+"' got '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ } else {
+ logln("OK: got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
+ }
}
}
}
UnicodeString result;
UnicodeString expectedResult;
- for (unsigned int i = 0; i < sizeof(input)/sizeof(double); ++i) {
+ for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
numberFormat->format(input[i], result);
UnicodeString expectedResult(expected[i]);
if (result != expectedResult) {
dataerrln("Failure creating DecimalFormat %s", u_errorName(status));
return;
}
- for (int32_t i = 0; i < (int32_t) (sizeof(items) / sizeof(items[0])); ++i) {
+ for (int32_t i = 0; i < UPRV_LENGTHOF(items); ++i) {
decfmt->setRoundingMode(items[i].mode);
decfmt->setMaximumFractionDigits(0);
UnicodeString actual;
fmt.applyPattern("AA#,##0.00ZZ", status);
// Oops this still prints 'a' even though we changed the pattern.
- if (fmt.getPadCharacterString() != UnicodeString("*")) {
+ if (fmt.getPadCharacterString() != UnicodeString(" ")) {
errln("applyPattern did not clear padding character.");
}
}
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {-3006.0, -3005, -3004, 3014, 3015, 3016};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
/* Commented out for now until we decide how rounding to zero should work, +0 vs. -0
{
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
*/
{
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {-1e25, -1e25 + 1e15, -1e25 - 1e15};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {1e-25, 1e-25 + 1e-35, 1e-25 - 1e-35};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
{
double values[] = {-1e-25, -1e-25 + 1e-35, -1e-25 - 1e-35};
expected,
roundingModes,
descriptions,
- (int32_t) (sizeof(values) / sizeof(values[0])),
- (int32_t) (sizeof(roundingModes) / sizeof(roundingModes[0])));
+ UPRV_LENGTHOF(values),
+ UPRV_LENGTHOF(roundingModes));
}
}
delete fmtBase;
}
+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", UnicodeString("PKR124"), original);
+
+ // test the getter here
+ UCurrencyUsage curUsage = fmt->getCurrencyUsage();
+ assertEquals("Test usage getter - standard", curUsage, 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", curUsage, UCURR_USAGE_CASH);
+
+ UnicodeString cash_currency;
+ fmt->format(agent,cash_currency);
+ assertEquals("Test Currency Usage 2", UnicodeString("PKR124"), cash_currency);
+ 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", UnicodeString("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", UnicodeString("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", UnicodeString("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", UnicodeString("PKR124"), PKR_changed);
+ delete fmt;
+ }
+}
+
+void NumberFormatTest::TestNumberFormatTestTuple() {
+ NumberFormatTestTuple tuple;
+ UErrorCode status = U_ZERO_ERROR;
+
+ tuple.setField(
+ NumberFormatTestTuple::getFieldByName("locale"),
+ "en",
+ status);
+ tuple.setField(
+ NumberFormatTestTuple::getFieldByName("pattern"),
+ "#,##0.00",
+ status);
+ tuple.setField(
+ NumberFormatTestTuple::getFieldByName("minIntegerDigits"),
+ "-10",
+ status);
+ if (!assertSuccess("", status)) {
+ return;
+ }
+
+ // only what we set should be set.
+ assertEquals("", "en", tuple.locale.getName());
+ assertEquals("", "#,##0.00", tuple.pattern);
+ assertEquals("", -10, tuple.minIntegerDigits);
+ assertTrue("", tuple.localeFlag);
+ assertTrue("", tuple.patternFlag);
+ assertTrue("", tuple.minIntegerDigitsFlag);
+ assertFalse("", tuple.formatFlag);
+
+ UnicodeString appendTo;
+ assertEquals(
+ "",
+ "{locale: en, pattern: #,##0.00, minIntegerDigits: -10}",
+ tuple.toString(appendTo));
+
+ tuple.clear();
+ appendTo.remove();
+ assertEquals(
+ "",
+ "{}",
+ tuple.toString(appendTo));
+ tuple.setField(
+ NumberFormatTestTuple::getFieldByName("aBadFieldName"),
+ "someValue",
+ status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
+ }
+ status = U_ZERO_ERROR;
+ tuple.setField(
+ NumberFormatTestTuple::getFieldByName("minIntegerDigits"),
+ "someBadValue",
+ status);
+ if (status != U_ILLEGAL_ARGUMENT_ERROR) {
+ errln("Expected U_ILLEGAL_ARGUMENT_ERROR");
+ }
+}
+
+void
+NumberFormatTest::TestDataDriven() {
+ NumberFormatTestDataDriven dd;
+ dd.setCaller(this);
+ dd.run("numberformattestspecification.txt", FALSE);
+}
+
+
+// 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 = 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 = 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::TestFastPathConsistent11524() {
+ UErrorCode status = U_ZERO_ERROR;
+ NumberFormat *fmt = NumberFormat::createInstance("en", status);
+ if (U_FAILURE(status) || fmt == NULL) {
+ dataerrln("Failed call to NumberFormat::createInstance() - %s", u_errorName(status));
+ return;
+ }
+ fmt->setMaximumIntegerDigits(INT32_MIN);
+ UnicodeString appendTo;
+ assertEquals("", "0", fmt->format(123, appendTo));
+ appendTo.remove();
+ assertEquals("", "0", fmt->format(12345, appendTo));
+ delete fmt;
+}
+
+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(0);
+ 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(0);
+ 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(0);
+ 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(5, result));
+ result.remove();
+ fmt.applyPattern(pattern.unescape(), status);
+ assertEquals(
+ "applyPattern favors precision of pattern",
+ "$5",
+ fmt.format(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() {
+ DigitList d;
+ d.set(-0.0);
+ assertFalse("", d.isPositive());
+ d.round(3);
+ assertFalse("", d.isPositive());
+}
+
+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));
+ 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::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::checkExceptionIssue11735() {
+ UErrorCode status;
+ Locale enLocale("en");
+ DecimalFormatSymbols symbols(enLocale, status);
+
+ if (U_FAILURE(status)) {
+ errln((UnicodeString)
+ "Fail: Construct DecimalFormatSymbols");
+ }
+
+ DecimalFormat fmt("0", symbols, status);
+ if (U_FAILURE(status)) {
+ errln((UnicodeString)
+ "Fail: Construct DecimalFormat formatter");
+ }
+
+ ParsePosition ppos(0);
+ fmt.parseCurrency("53.45", ppos); // NPE thrown here in ICU4J.
+ assertEquals("Issue11735 ppos", 0, ppos.getIndex());
+}
+
#endif /* #if !UCONFIG_NO_FORMATTING */