ICU-13828 DecimalFormat Error Code handling cleanups.

X-SVN-Rev: 41515
This commit is contained in:
Andy Heninger 2018-06-11 03:56:58 +00:00
parent 7c45a289d5
commit 04d300adeb
4 changed files with 137 additions and 9 deletions

View File

@ -96,17 +96,21 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols*
}
DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status) {
LocalPointer<const DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
fields = new DecimalFormatFields();
if (U_FAILURE(status)) {
return;
}
if (fields == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
if (symbolsToAdopt == nullptr) {
if (adoptedSymbols.isNull()) {
fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status);
} else {
fields->symbols.adoptInsteadAndCheckErrorCode(symbolsToAdopt, status);
fields->symbols.adoptInsteadAndCheckErrorCode(adoptedSymbols.orphan(), status);
}
}
@ -968,9 +972,11 @@ void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern,
}
void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern, UErrorCode& status) {
UnicodeString pattern = PatternStringUtils::convertLocalized(
localizedPattern, *fields->symbols, false, status);
applyPattern(pattern, status);
if (U_SUCCESS(status)) {
UnicodeString pattern = PatternStringUtils::convertLocalized(
localizedPattern, *fields->symbols, false, status);
applyPattern(pattern, status);
}
}
void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
@ -1080,6 +1086,9 @@ void DecimalFormat::setCurrency(const char16_t* theCurrency) {
}
void DecimalFormat::setCurrencyUsage(UCurrencyUsage newUsage, UErrorCode* ec) {
if (U_FAILURE(*ec)) {
return;
}
if (!fields->properties->currencyUsage.isNull() && newUsage == fields->properties->currencyUsage.getNoError()) {
return;
}
@ -1158,9 +1167,11 @@ void DecimalFormat::touchNoError() {
void DecimalFormat::setPropertiesFromPattern(const UnicodeString& pattern, int32_t ignoreRounding,
UErrorCode& status) {
// Cast workaround to get around putting the enum in the public header file
auto actualIgnoreRounding = static_cast<IgnoreRounding>(ignoreRounding);
PatternParser::parseToExistingProperties(pattern, *fields->properties, actualIgnoreRounding, status);
if (U_SUCCESS(status)) {
// Cast workaround to get around putting the enum in the public header file
auto actualIgnoreRounding = static_cast<IgnoreRounding>(ignoreRounding);
PatternParser::parseToExistingProperties(pattern, *fields->properties, actualIgnoreRounding, status);
}
}
const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& status) const {

View File

@ -150,7 +150,7 @@ struct DecimalFormatFields : public UMemory {
LocalPointer<DecimalFormatProperties> exportedProperties;
// Data for fastpath
bool canUseFastFormat;
bool canUseFastFormat = false;
struct FastFormatData {
char16_t cpZero;
char16_t cpGroupingSeparator;

View File

@ -89,6 +89,12 @@ void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const
TestRequiredDecimalPoint();
}
break;
case 8: name = "testErrorCode";
if(exec) {
logln((UnicodeString)"testErrorCode ---");
testErrorCode();
}
break;
default: name = ""; break;
}
}
@ -1022,4 +1028,114 @@ void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
}
}
// WHERE Macro yields a literal string of the form "source_file_name:line number "
#define WHERE __FILE__ ":" XLINE(__LINE__) " "
#define XLINE(s) LINE(s)
#define LINE(s) #s
void IntlTestDecimalFormatAPI::testErrorCode() {
// Try each DecimalFormat constructor with an errorCode set on input,
// Verify no crashes or leaks, and that the errorCode is not altered.
UErrorCode status = U_ZERO_ERROR;
const UnicodeString pattern(u"0.###E0");
UParseError pe;
DecimalFormatSymbols symbols(Locale::getUS(), status);
assertSuccess(WHERE, status);
{
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat df(status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
{
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat df(pattern, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
{
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
{
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), UNUM_DECIMAL_COMPACT_LONG, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
{
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), pe, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
{
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat df(pattern, symbols ,status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
// Try each DecimalFormat method with an error code parameter, verifying that
// an input error is not altered.
status = U_INTERNAL_PROGRAM_ERROR;
DecimalFormat dfBogus(status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_ZERO_ERROR;
DecimalFormat dfGood(pattern, new DecimalFormatSymbols(symbols), status);
assertSuccess(WHERE, status);
for (DecimalFormat *df: {&dfBogus, &dfGood}) {
status = U_INTERNAL_PROGRAM_ERROR;
df->setAttribute(UNUM_PARSE_INT_ONLY, 0, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->getAttribute(UNUM_MAX_FRACTION_DIGITS, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
UnicodeString dest;
FieldPosition fp;
df->format(1.2, dest, fp, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->format(1.2, dest, nullptr, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->format((int32_t)666, dest, nullptr, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->format((int64_t)666, dest, nullptr, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->format(StringPiece("3.1415926535897932384626"), dest, nullptr, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->applyPattern(pattern, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->applyLocalizedPattern(pattern, pe, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->applyLocalizedPattern(pattern, status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->setCurrency(u"USD", status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
status = U_INTERNAL_PROGRAM_ERROR;
df->setCurrencyUsage(UCURR_USAGE_CASH, &status);
assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -33,6 +33,7 @@ public:
void TestFixedDecimal();
void TestBadFastpath();
void TestRequiredDecimalPoint();
void testErrorCode();
private:
/*Helper functions */
void verify(const UnicodeString& message, const UnicodeString& got, double expected);