ICU-10970 Support required decimal point
X-SVN-Rev: 36300
This commit is contained in:
parent
6dfe296e91
commit
867e55f0cb
@ -2944,6 +2944,18 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't see a decimal and it is required, check to see if the pattern had one
|
||||
if(!sawDecimal && isDecimalPatternMatchRequired())
|
||||
{
|
||||
if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
|
||||
{
|
||||
parsePosition.setIndex(oldStart);
|
||||
parsePosition.setErrorIndex(position);
|
||||
debug("decimal point match required fail!");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (backup != -1)
|
||||
{
|
||||
position = backup;
|
||||
@ -3057,6 +3069,20 @@ printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d
|
||||
parsePosition.setErrorIndex(position);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// check if we missed a required decimal point
|
||||
if(fastParseOk && isDecimalPatternMatchRequired())
|
||||
{
|
||||
if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
|
||||
{
|
||||
parsePosition.setIndex(oldStart);
|
||||
parsePosition.setErrorIndex(position);
|
||||
debug("decimal point match required fail!");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -4168,6 +4194,24 @@ DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Checks if decimal point pattern match is required
|
||||
UBool
|
||||
DecimalFormat::isDecimalPatternMatchRequired(void) const
|
||||
{
|
||||
return fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Checks if decimal point pattern match is required
|
||||
|
||||
void
|
||||
DecimalFormat::setDecimalPatternMatchRequired(UBool newValue)
|
||||
{
|
||||
fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Emits the pattern of this DecimalFormat instance.
|
||||
|
||||
@ -5480,6 +5524,7 @@ DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
|
||||
/* These are stored in fBoolFlags */
|
||||
case UNUM_PARSE_NO_EXPONENT:
|
||||
case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
|
||||
case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
|
||||
if(!fBoolFlags.isValidValue(newValue)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
@ -5567,6 +5612,7 @@ int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
|
||||
/* These are stored in fBoolFlags */
|
||||
case UNUM_PARSE_NO_EXPONENT:
|
||||
case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
|
||||
case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
|
||||
return fBoolFlags.get(attr);
|
||||
|
||||
case UNUM_SCALE:
|
||||
|
@ -1631,6 +1631,26 @@ public:
|
||||
*/
|
||||
virtual void setDecimalSeparatorAlwaysShown(UBool newValue);
|
||||
|
||||
/**
|
||||
* Allows you to get the parse behavior of the pattern decimal mark.
|
||||
*
|
||||
* @return TRUE if input must contain a match to decimal mark in pattern
|
||||
* @draft ICU 54
|
||||
*/
|
||||
UBool isDecimalPatternMatchRequired(void) const;
|
||||
|
||||
/**
|
||||
* Allows you to set the behavior of the pattern decimal mark.
|
||||
*
|
||||
* if TRUE, the input must have a decimal mark if one was specified in the pattern. When
|
||||
* FALSE the decimal mark may be omitted from the input.
|
||||
*
|
||||
* @param newValue set TRUE if input must contain a match to decimal mark in pattern
|
||||
* @draft ICU 54
|
||||
*/
|
||||
virtual void setDecimalPatternMatchRequired(UBool newValue);
|
||||
|
||||
|
||||
/**
|
||||
* Synthesizes a pattern string that represents the current state
|
||||
* of this Format object.
|
||||
|
@ -940,6 +940,16 @@ typedef enum UNumberFormatAttribute {
|
||||
*/
|
||||
UNUM_PARSE_NO_EXPONENT,
|
||||
|
||||
/**
|
||||
* if this attribute is set to 1, specifies that, if the pattern contains a
|
||||
* decimal mark the input is required to have one. If this attribute is set to 0,
|
||||
* specifies that input does not have to contain a decimal mark.
|
||||
* Has no effect on formatting.
|
||||
* Default: 0 (unset)
|
||||
* @draft ICU 54
|
||||
*/
|
||||
UNUM_PARSE_DECIMAL_MARK_REQUIRED,
|
||||
|
||||
/* The following cannot be #ifndef U_HIDE_INTERNAL_API, needed in .h file variable declararions */
|
||||
/** Limit of boolean attributes.
|
||||
* @internal */
|
||||
|
@ -79,6 +79,12 @@ void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const
|
||||
TestBadFastpath();
|
||||
}
|
||||
break;
|
||||
case 7: name = "TestRequiredDecimalPoint";
|
||||
if(exec) {
|
||||
logln((UnicodeString)"TestRequiredDecimalPoint ---");
|
||||
TestRequiredDecimalPoint();
|
||||
}
|
||||
break;
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
@ -825,4 +831,52 @@ void IntlTestDecimalFormatAPI::TestBadFastpath() {
|
||||
assertEquals("Format 1234 w/ grouping", "1,234", df->format(1234, fmt));
|
||||
}
|
||||
|
||||
void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString text("99");
|
||||
double expected = 99;
|
||||
double whatIGot = 0.0;
|
||||
Formattable result1;
|
||||
UnicodeString pat1("##.0000");
|
||||
UnicodeString pat2("00.0");
|
||||
|
||||
LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status));
|
||||
if (U_FAILURE(status)) {
|
||||
dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
df->applyPattern(pat1, status);
|
||||
if(U_FAILURE(status)) {
|
||||
errln((UnicodeString)"ERROR: applyPattern() failed");
|
||||
}
|
||||
df->parse(text, result1, status);
|
||||
if(U_FAILURE(status)) {
|
||||
errln((UnicodeString)"ERROR: parse() failed");
|
||||
}
|
||||
df->setDecimalPatternMatchRequired(TRUE);
|
||||
df->parse(text, result1, status);
|
||||
if(U_SUCCESS(status)) {
|
||||
errln((UnicodeString)"ERROR: unexpected parse()");
|
||||
}
|
||||
|
||||
|
||||
status = U_ZERO_ERROR;
|
||||
df->applyPattern(pat2, status);
|
||||
df->setDecimalPatternMatchRequired(FALSE);
|
||||
if(U_FAILURE(status)) {
|
||||
errln((UnicodeString)"ERROR: applyPattern(2) failed");
|
||||
}
|
||||
df->parse(text, result1, status);
|
||||
if(U_FAILURE(status)) {
|
||||
errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status));
|
||||
}
|
||||
df->setDecimalPatternMatchRequired(TRUE);
|
||||
df->parse(text, result1, status);
|
||||
if(U_SUCCESS(status)) {
|
||||
errln((UnicodeString)"ERROR: unexpected parse(2)");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
void TestScale();
|
||||
void TestFixedDecimal();
|
||||
void TestBadFastpath();
|
||||
void TestRequiredDecimalPoint();
|
||||
private:
|
||||
/*Helper functions */
|
||||
void verify(const UnicodeString& message, const UnicodeString& got, double expected);
|
||||
|
Loading…
Reference in New Issue
Block a user