From 64f350c92a339a4f5b1770036ef3c3b5c9d18931 Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Thu, 19 Feb 2009 08:41:08 +0000 Subject: [PATCH] ICU-6734 unum_parse does not report parse errors for rule-based number formatters X-SVN-Rev: 25442 --- icu4c/source/i18n/rbnf.cpp | 6 ++- icu4c/source/i18n/unum.cpp | 10 ++--- icu4c/source/test/cintltst/cnumtst.c | 62 +++++++++++++++++++++++++++- icu4c/source/test/cintltst/cnumtst.h | 7 +++- 4 files changed, 77 insertions(+), 8 deletions(-) diff --git a/icu4c/source/i18n/rbnf.cpp b/icu4c/source/i18n/rbnf.cpp index 6b42857861..36e4a3615f 100644 --- a/icu4c/source/i18n/rbnf.cpp +++ b/icu4c/source/i18n/rbnf.cpp @@ -1152,9 +1152,13 @@ RuleBasedNumberFormat::parse(const UnicodeString& text, } } - parsePosition.setIndex(parsePosition.getIndex() + high_pp.getIndex()); + int32_t startIndex = parsePosition.getIndex(); + parsePosition.setIndex(startIndex + high_pp.getIndex()); if (high_pp.getIndex() > 0) { parsePosition.setErrorIndex(-1); + } else { + int32_t errorIndex = (high_pp.getErrorIndex()>0)? high_pp.getErrorIndex(): 0; + parsePosition.setErrorIndex(startIndex + errorIndex); } result = high_result; if (result.getType() == Formattable::kDouble) { diff --git a/icu4c/source/i18n/unum.cpp b/icu4c/source/i18n/unum.cpp index 3dfd93e6e2..ef8b594771 100644 --- a/icu4c/source/i18n/unum.cpp +++ b/icu4c/source/i18n/unum.cpp @@ -317,13 +317,13 @@ parseRes(Formattable& res, ((const NumberFormat*)fmt)->parse(src, res, pp); } - if(parsePos != 0) { - if(pp.getErrorIndex() == -1) - *parsePos = pp.getIndex(); - else { + if(pp.getErrorIndex() != -1) { + *status = U_PARSE_ERROR; + if(parsePos != 0) { *parsePos = pp.getErrorIndex(); - *status = U_PARSE_ERROR; } + } else if(parsePos != 0) { + *parsePos = pp.getIndex(); } } diff --git a/icu4c/source/test/cintltst/cnumtst.c b/icu4c/source/test/cintltst/cnumtst.c index 6a9e8b2204..7e332d2564 100644 --- a/icu4c/source/test/cintltst/cnumtst.c +++ b/icu4c/source/test/cintltst/cnumtst.c @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2008, International Business Machines Corporation and + * Copyright (c) 1997-2009, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /******************************************************************************** @@ -42,6 +42,7 @@ static void TestNBSPInPattern(void); void addNumForTest(TestNode** root) { TESTCASE(TestNumberFormat); + TESTCASE(TestSpelloutNumberParse); TESTCASE(TestSignificantDigits); TESTCASE(TestNumberFormatPadding); TESTCASE(TestInt64Format); @@ -763,6 +764,65 @@ free(result); } +typedef struct { + const char * testname; + const char * locale; + const UChar * source; + int32_t startPos; + int32_t value; + int32_t endPos; + UErrorCode status; +} SpelloutParseTest; + +static const UChar ustr_en0[] = {0x7A, 0x65, 0x72, 0x6F, 0}; /* zero */ +static const UChar ustr_123[] = {0x31, 0x32, 0x33, 0}; /* 123 */ +static const UChar ustr_en123[] = {0x6f, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79, + 0x2d, 0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* one hundred and twenty-three */ +static const UChar ustr_fr123[] = {0x63, 0x65, 0x6e, 0x74, 0x20, 0x76, 0x69, 0x6e, 0x67, 0x74, 0x2d, + 0x74, 0x72, 0x6f, 0x69, 0x73, 0}; /* cent vingt-trois */ +static const UChar ustr_ja123[] = {0x767e, 0x4e8c, 0x5341, 0x4e09, 0}; /* kanji 100(+)2(*)10(+)3 */ + +static const SpelloutParseTest spelloutParseTests[] = { + /* name loc src start val end status */ + { "en0", "en", ustr_en0, 0, 0, 4, U_ZERO_ERROR }, + { "en0", "en", ustr_en0, 2, 0, 2, U_PARSE_ERROR }, + { "en0", "ja", ustr_en0, 0, 0, 0, U_PARSE_ERROR }, + { "123", "en", ustr_123, 0, 0, 0, U_PARSE_ERROR }, + { "en123", "en", ustr_en123, 0, 123, 28, U_ZERO_ERROR }, + { "en123", "en", ustr_en123, 16, 23, 28, U_ZERO_ERROR }, + { "en123", "fr", ustr_en123, 16, 0, 16, U_PARSE_ERROR }, + { "fr123", "fr", ustr_fr123, 0, 123, 16, U_ZERO_ERROR }, + { "fr123", "fr", ustr_fr123, 5, 23, 16, U_ZERO_ERROR }, + { "fr123", "en", ustr_fr123, 0, 0, 0, U_PARSE_ERROR }, + { "ja123", "ja", ustr_ja123, 0, 123, 4, U_ZERO_ERROR }, + { "ja123", "ja", ustr_ja123, 1, 23, 4, U_ZERO_ERROR }, + { "ja123", "fr", ustr_ja123, 0, 0, 0, U_PARSE_ERROR }, + { NULL, NULL, NULL, 0, 0, 0, 0 } /* terminator */ +}; + +static void TestSpelloutNumberParse() +{ + const SpelloutParseTest * testPtr; + for (testPtr = spelloutParseTests; testPtr->testname != NULL; ++testPtr) { + UErrorCode status = U_ZERO_ERROR; + int32_t value, position = testPtr->startPos; + UNumberFormat *nf = unum_open(UNUM_SPELLOUT, NULL, 0, testPtr->locale, NULL, &status); + if (U_FAILURE(status)) { + log_err("unum_open fails for UNUM_SPELLOUT with locale %s, status %s\n", testPtr->locale, myErrorName(status)); + continue; + } + value = unum_parse(nf, testPtr->source, -1, &position, &status); + if ( value != testPtr->value || position != testPtr->endPos || status != testPtr->status ) { + log_err("unum_parse SPELLOUT, locale %s, testname %s, startPos %d: for value / endPos / status, expected %d / %d / %s, got %d / %d / %s\n", + testPtr->locale, testPtr->testname, testPtr->startPos, + testPtr->value, testPtr->endPos, myErrorName(testPtr->status), + value, position, myErrorName(status) ); + } + unum_close(nf); + } +} + static void TestSignificantDigits() { UChar temp[128]; diff --git a/icu4c/source/test/cintltst/cnumtst.h b/icu4c/source/test/cintltst/cnumtst.h index 93851dc733..1a95feec7b 100644 --- a/icu4c/source/test/cintltst/cnumtst.h +++ b/icu4c/source/test/cintltst/cnumtst.h @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2005, International Business Machines Corporation and + * Copyright (c) 1997-2009, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /******************************************************************************** @@ -28,6 +28,11 @@ **/ static void TestNumberFormat(void); +/** + * The function used to test parsing of numbers in UNUM_SPELLOUT style + **/ +static void TestSpelloutNumberParse(void); + /** * The function used to test significant digits in the Number format API **/