From: Apple Date: Wed, 16 Sep 2009 17:43:53 +0000 (+0000) Subject: ICU-400.38.tar.gz X-Git-Tag: mac-os-x-1062^0 X-Git-Url: https://git.saurik.com/apple/icu.git/commitdiff_plain/7393aa2fd2c40c89f12c2db881842a563afdb429 ICU-400.38.tar.gz --- diff --git a/icuSources/i18n/decfmtst.cpp b/icuSources/i18n/decfmtst.cpp index 573dcbf9..6452936d 100644 --- a/icuSources/i18n/decfmtst.cpp +++ b/icuSources/i18n/decfmtst.cpp @@ -45,6 +45,10 @@ static const UChar gOtherGroupingSeparatorsPattern[] = { // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ] 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000}; +static const UChar gDashEquivalentsPattern[] = { + // [ \ - HYPHEN F_DASH N_DASH MINUS ] + 0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000}; + static const UChar gStrictDotEquivalentsPattern[] = { // [ . \u2024 \uFE52 \uFF0E \uFF61 ] 0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000}; @@ -57,6 +61,10 @@ static const UChar gStrictOtherGroupingSeparatorsPattern[] = { // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ] 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000}; +static const UChar gStrictDashEquivalentsPattern[] = { + // [ \ - MINUS ] + 0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000}; + DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL; @@ -64,18 +72,23 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status) : fDotEquivalents(NULL), fCommaEquivalents(NULL), fOtherGroupingSeparators(NULL), + fDashEquivalents(NULL), fStrictDotEquivalents(NULL), fStrictCommaEquivalents(NULL), fStrictOtherGroupingSeparators(NULL), + fStrictDashEquivalents(NULL), fDefaultGroupingSeparators(NULL), fStrictDefaultGroupingSeparators(NULL) { fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), *status); fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), *status); fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), *status); + fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), *status); + fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), *status); fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), *status); fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status); + fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), *status); fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents); @@ -87,8 +100,8 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status) fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators); // Check for null pointers - if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || - fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || + if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL || + fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL || fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL) { goto ExitConstrDeleteAll; } @@ -97,9 +110,11 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status) fDotEquivalents->freeze(); fCommaEquivalents->freeze(); fOtherGroupingSeparators->freeze(); + fDashEquivalents->freeze(); fStrictDotEquivalents->freeze(); fStrictCommaEquivalents->freeze(); fStrictOtherGroupingSeparators->freeze(); + fStrictDashEquivalents->freeze(); fDefaultGroupingSeparators->freeze(); fStrictDefaultGroupingSeparators->freeze(); @@ -109,9 +124,11 @@ ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error delete fDotEquivalents; fDotEquivalents = NULL; delete fCommaEquivalents; fCommaEquivalents = NULL; delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL; + delete fDashEquivalents; fDashEquivalents = NULL; delete fStrictDotEquivalents; fStrictDotEquivalents = NULL; delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL; delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; + delete fStrictDashEquivalents; fStrictDashEquivalents = NULL; delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL; delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; @@ -123,9 +140,11 @@ DecimalFormatStaticSets::~DecimalFormatStaticSets() { delete fDotEquivalents; fDotEquivalents = NULL; delete fCommaEquivalents; fCommaEquivalents = NULL; delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL; + delete fDashEquivalents; fDashEquivalents = NULL; delete fStrictDotEquivalents; fStrictDotEquivalents = NULL; delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL; delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; + delete fStrictDashEquivalents; fStrictDashEquivalents = NULL; delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL; delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; } diff --git a/icuSources/i18n/decfmtst.h b/icuSources/i18n/decfmtst.h index 8c3d851c..79d15838 100644 --- a/icuSources/i18n/decfmtst.h +++ b/icuSources/i18n/decfmtst.h @@ -37,10 +37,12 @@ public: UnicodeSet *fDotEquivalents; UnicodeSet *fCommaEquivalents; UnicodeSet *fOtherGroupingSeparators; + UnicodeSet *fDashEquivalents; UnicodeSet *fStrictDotEquivalents; UnicodeSet *fStrictCommaEquivalents; UnicodeSet *fStrictOtherGroupingSeparators; + UnicodeSet *fStrictDashEquivalents; UnicodeSet *fDefaultGroupingSeparators; UnicodeSet *fStrictDefaultGroupingSeparators; diff --git a/icuSources/i18n/decimfmt.cpp b/icuSources/i18n/decimfmt.cpp index 288a685c..4f51c10e 100644 --- a/icuSources/i18n/decimfmt.cpp +++ b/icuSources/i18n/decimfmt.cpp @@ -1580,7 +1580,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text, ParsePosition& parsePos position += U16_LENGTH(ch); } - else if (matchSymbol(text, position, groupingStringLength, *groupingString, groupingSet, ch) && isGroupingUsed()) + else if (groupingStringLength > 0 && matchSymbol(text, position, groupingStringLength, *groupingString, groupingSet, ch) && isGroupingUsed()) { #if CHECK_FOR_MISPLACED_GROUPING if (sawDecimal) { @@ -1888,10 +1888,29 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix, const UnicodeString& input, int32_t pos, UBool strict) { + UErrorCode status = U_ZERO_ERROR; int32_t start = pos; + UChar32 affixChar = affix.char32At(0); + int32_t affixLength = affix.length(); + int32_t inputLength = input.length(); + int32_t affixCharLength = U16_LENGTH(affixChar); + UnicodeSet *affixSet; + DecimalFormatStaticSets::initSets(&status); + if (strict) { - for (int32_t i=0; ifStrictDashEquivalents; + + // If the affix is exactly one character long and that character + // is in the dash set and the very next input character is also + // in the dash set, return a match. + if (affixCharLength == affixLength && affixSet->contains(affixChar)) { + if (affixSet->contains(input.char32At(pos))) { + return 1; + } + } + + for (int32_t i=0; ifDashEquivalents; + + if (affixCharLength == affixLength && affixSet->contains(affixChar)) { + pos = skipUWhiteSpace(input, pos); + + if (affixSet->contains(input.char32At(pos))) { + return pos - start + 1; + } + } for (int32_t i = 0; i < affixLength; ) { diff --git a/icuSources/i18n/smpdtfmt.cpp b/icuSources/i18n/smpdtfmt.cpp index 7f98827f..5b93dc49 100644 --- a/icuSources/i18n/smpdtfmt.cpp +++ b/icuSources/i18n/smpdtfmt.cpp @@ -2133,7 +2133,13 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC // in strict mode, these can only // be a number if count <= 2 if (!lenient && gotNumber && count > 2) { - return -1; + // We have a string pattern in strict mode + // but the input parsed as a number. Ignore + // the fact that the input parsed as a number + // and try to match it as a string. (Some + // locales have numbers for the month names.) + gotNumber = FALSE; + pos.setIndex(start); } break; diff --git a/icuSources/test/intltest/dtfmttst.cpp b/icuSources/test/intltest/dtfmttst.cpp index 65345fc0..78b07339 100644 --- a/icuSources/test/intltest/dtfmttst.cpp +++ b/icuSources/test/intltest/dtfmttst.cpp @@ -77,7 +77,9 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam /* TESTCASE(37,TestRelativeError); TESTCASE(38,TestRelativeOther); - */ + TESTCASE(39,TestNumberAsStringParsing); + */ + TESTCASE(37,TestNumberAsStringParsing); default: name = ""; break; } } @@ -2964,6 +2966,32 @@ void DateFormatTest::TestRelativeOther(void) } */ +void DateFormatTest::TestNumberAsStringParsing() +{ + UErrorCode status = U_ZERO_ERROR; + UnicodeString dateString("2009 7 2 08:14:16"); + UnicodeString datePattern("y MMMM d HH:mm:ss"); + SimpleDateFormat *formatter = new SimpleDateFormat(datePattern, Locale(""), status); + UDate date1 = 0; + + formatter->setLenient(FALSE); + date1 = formatter->parse(dateString, status); + + if (U_FAILURE(status)) { + errln("FAIL: Could not parse \"2009 7 2 08:14:16\" with pattern \"y MMMM d HH:mm:ss\""); + } else { + UnicodeString formatted; + + formatter->format(date1, formatted); + + if (formatted != dateString) { + errln("FAIL: parsed string did not match input."); + } + } + + delete formatter; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icuSources/test/intltest/dtfmttst.h b/icuSources/test/intltest/dtfmttst.h index 091c4597..cf490093 100644 --- a/icuSources/test/intltest/dtfmttst.h +++ b/icuSources/test/intltest/dtfmttst.h @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2007, International Business Machines Corporation and + * Copyright (c) 1997-2009, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -136,7 +136,11 @@ public: virtual void TestDateFormatZone146(void); void TestTimeZoneStringsAPI(void); - + +#if ICU_4_2_1 + void TestGMTParsing(void); +#endif + public: // package /** * Test the formatting of dates in different locales. @@ -159,6 +163,14 @@ public: // package void TestGenericTimeZoneOrder(void); +#if ICU_4_2_1 + void Test6338(void); + + void Test6726(void); + + void Test6880(void); +#endif + public: /** * Test host-specific formatting. @@ -185,17 +197,31 @@ public: void TestHostClone(void); +#if ICU_4_2_1 + void TestTimeZoneDisplayName(void); + + void TestRoundtripWithCalendar(void); +#endif + public: /*** * Test Relative Dates */ void TestRelative(void); - void TestTimeZoneDisplayName(void); +#if !ICU_4_2_1 + void TestTimeZoneDisplayName(void); +#endif /* void TestRelativeError(void); void TestRelativeOther(void); */ - private: +public: + /** + * Test parsing a number as a string + */ + void TestNumberAsStringParsing(void); + +private: void TestRelative(int daysdelta, const Locale& loc, const char *expectChars); diff --git a/icuSources/test/intltest/numfmtst.cpp b/icuSources/test/intltest/numfmtst.cpp index 4371c668..1ac9e1be 100644 --- a/icuSources/test/intltest/numfmtst.cpp +++ b/icuSources/test/intltest/numfmtst.cpp @@ -818,6 +818,12 @@ static const char *lenientAffixTestCases[] = { "( 1 )" }; +static const char *lenientMinusTestCases[] = { + "-5", + "\\u22125", + "\\u20105" +}; + static const char *lenientCurrencyTestCases[] = { "$1,000", "$ 1,000", @@ -898,8 +904,44 @@ NumberFormatTest::TestLenientParse(void) delete format; - Locale locale("en_US"); - NumberFormat *cFormat = NumberFormat::createCurrencyInstance(locale, status); + Locale en_US("en_US"); + Locale sv_SE("sv_SE"); + + NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, status); + + mFormat->setParseStrict(FALSE); + for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) { + UnicodeString testCase = ctou(lenientMinusTestCases[t]); + + mFormat->parse(testCase, n, status); + logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong()); + + if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) { + errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\""); + status = U_ZERO_ERROR; + } + } + + delete mFormat; + + mFormat = NumberFormat::createInstance(en_US, status); + + mFormat->setParseStrict(FALSE); + for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) { + UnicodeString testCase = ctou(lenientMinusTestCases[t]); + + mFormat->parse(testCase, n, status); + logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong()); + + if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) { + errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\""); + status = U_ZERO_ERROR; + } + } + + delete mFormat; + + NumberFormat *cFormat = NumberFormat::createCurrencyInstance(en_US, status); cFormat->setParseStrict(FALSE); for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) { @@ -932,7 +974,7 @@ NumberFormatTest::TestLenientParse(void) delete cFormat; - NumberFormat *pFormat = NumberFormat::createPercentInstance(locale, status); + NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status); pFormat->setParseStrict(FALSE); for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) { @@ -965,7 +1007,7 @@ NumberFormatTest::TestLenientParse(void) // Test cases that should fail with a strict parse and pass with a // lenient parse. - NumberFormat *nFormat = NumberFormat::createInstance(locale, status); + NumberFormat *nFormat = NumberFormat::createInstance(en_US, status); // first, make sure that they fail with a strict parse for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {