ICU-10258 Parse different variations of '+' and '-' when isLenient is set in C++.

X-SVN-Rev: 33989
This commit is contained in:
Travis Keep 2013-07-25 17:58:37 +00:00
parent 75ee6eb19b
commit 41b7ee189d
3 changed files with 94 additions and 1 deletions

View file

@ -282,6 +282,61 @@ static const char fgLatn[]="latn";
static const char fgPatterns[]="patterns";
static const char fgDecimalFormat[]="decimalFormat";
static const char fgCurrencyFormat[]="currencyFormat";
static UChar32 gMinusSigns[] = {
0x002D,
0x207B,
0x208B,
0x2212,
0x2796,
0xFE63,
0xFF0D};
static UChar32 gPlusSigns[] = {
0x002B,
0x207A,
0x208A,
0x2795,
0xfB29,
0xFE62,
0xFF0B};
static UnicodeSet *gMinusSignsSet = NULL;
static UnicodeSet *gPlusSignsSet = NULL;
static UInitOnce gSignsInitOnce = U_INITONCE_INITIALIZER;
static void initSigns(const UChar32 *raw, int32_t len, UnicodeSet *s) {
for (int32_t i = 0; i < len; ++i) {
s->add(raw[i]);
}
}
static void U_CALLCONV initSigns() {
U_ASSERT(gMinusSignsSet == NULL);
U_ASSERT(gPlusSignsSet == NULL);
gMinusSignsSet = new UnicodeSet();
gPlusSignsSet = new UnicodeSet();
initSigns(
gMinusSigns,
sizeof(gMinusSigns) / sizeof(gMinusSigns[0]),
gMinusSignsSet);
initSigns(
gPlusSigns,
sizeof(gPlusSigns) / sizeof(gPlusSigns[0]),
gPlusSignsSet);
}
static const UnicodeSet* getMinusSigns() {
umtx_initOnce(gSignsInitOnce, &initSigns);
return gMinusSignsSet;
}
static const UnicodeSet* getPlusSigns() {
umtx_initOnce(gSignsInitOnce, &initSigns);
return gPlusSignsSet;
}
static const UChar fgTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
@ -2850,6 +2905,12 @@ int32_t DecimalFormat::compareAffix(const UnicodeString& text,
return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
}
static UBool equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) {
return lhs == rhs
|| (getMinusSigns()->contains(lhs) && getMinusSigns()->contains(rhs))
|| (getPlusSigns()->contains(lhs) && getPlusSigns()->contains(rhs));
}
/**
* Return the length matched by the given affix, or -1 if none.
* Runs of white space in the affix, match runs of white space in
@ -2966,7 +3027,7 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
UChar32 c = affix.char32At(i);
int32_t len = U16_LENGTH(c);
if (input.char32At(pos) != c) {
if (!equalWithSignCompatibility(input.char32At(pos), c)) {
return -1;
}

View file

@ -126,6 +126,8 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
TESTCASE_AUTO(TestShowZero);
TESTCASE_AUTO(TestCompatibleCurrencies);
TESTCASE_AUTO(TestBug9936);
TESTCASE_AUTO(TestParseNegativeWithFaLocale);
TESTCASE_AUTO(TestParseNegativeWithAlternateMinusSign);
TESTCASE_AUTO_END;
}
@ -7118,4 +7120,32 @@ void NumberFormatTest::TestBug9936() {
}
void NumberFormatTest::TestParseNegativeWithFaLocale() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
test->setLenient(TRUE);
Formattable af;
ParsePosition ppos;
test->parse(UnicodeString("-0.5"), af, ppos);
if (ppos.getIndex() == 0) {
errln("Expected -0.5 to parse for farse.");
}
delete test;
}
void NumberFormatTest::TestParseNegativeWithAlternateMinusSign() {
UErrorCode status = U_ZERO_ERROR;
DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("en", status);
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;
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -169,6 +169,8 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void TestCompatibleCurrencies();
void TestBug9936();
void TestParseNegativeWithFaLocale();
void TestParseNegativeWithAlternateMinusSign();
private:
UBool testFormattableAsUFormattable(const char *file, int line, Formattable &f);