From 41b7ee189db18a5562f822d2b211bea5fae22383 Mon Sep 17 00:00:00 2001 From: Travis Keep Date: Thu, 25 Jul 2013 17:58:37 +0000 Subject: [PATCH] ICU-10258 Parse different variations of '+' and '-' when isLenient is set in C++. X-SVN-Rev: 33989 --- icu4c/source/i18n/decimfmt.cpp | 63 ++++++++++++++++++++++++- icu4c/source/test/intltest/numfmtst.cpp | 30 ++++++++++++ icu4c/source/test/intltest/numfmtst.h | 2 + 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/icu4c/source/i18n/decimfmt.cpp b/icu4c/source/i18n/decimfmt.cpp index cf6b2382be6..df2dc48fc49 100644 --- a/icu4c/source/i18n/decimfmt.cpp +++ b/icu4c/source/i18n/decimfmt.cpp @@ -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 (acontains(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; } diff --git a/icu4c/source/test/intltest/numfmtst.cpp b/icu4c/source/test/intltest/numfmtst.cpp index 3cc78fca58f..803c326cf8c 100644 --- a/icu4c/source/test/intltest/numfmtst.cpp +++ b/icu4c/source/test/intltest/numfmtst.cpp @@ -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 */ diff --git a/icu4c/source/test/intltest/numfmtst.h b/icu4c/source/test/intltest/numfmtst.h index 48649b929ac..22b3b9f67a7 100644 --- a/icu4c/source/test/intltest/numfmtst.h +++ b/icu4c/source/test/intltest/numfmtst.h @@ -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); -- 2.40.0