ICU-8697 C, change parseCurrency methods to return CurrencyAmount*, make draft ICU 49

X-SVN-Rev: 31440
This commit is contained in:
Peter Edberg 2012-02-19 06:45:47 +00:00
parent 5824cdd742
commit 05b2ae1381
7 changed files with 159 additions and 122 deletions

View File

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (c) 2004-2010, International Business Machines
* Copyright (c) 2004-2012 International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
@ -16,6 +16,7 @@
#include "currfmt.h"
#include "unicode/numfmt.h"
#include "unicode/curramt.h"
U_NAMESPACE_BEGIN
@ -62,7 +63,10 @@ void CurrencyFormat::parseObject(const UnicodeString& source,
Formattable& result,
ParsePosition& pos) const
{
fmt->parseCurrency(source, result, pos);
CurrencyAmount* currAmt = fmt->parseCurrency(source, pos);
if (currAmt != NULL) {
result.adoptObject(currAmt);
}
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyFormat)

View File

@ -1591,32 +1591,48 @@ void
DecimalFormat::parse(const UnicodeString& text,
Formattable& result,
ParsePosition& parsePosition) const {
parse(text, result, parsePosition, FALSE);
parse(text, result, parsePosition, NULL);
}
Formattable& DecimalFormat::parseCurrency(const UnicodeString& text,
Formattable& result,
ParsePosition& pos) const {
parse(text, result, pos, TRUE);
return result;
CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
ParsePosition& pos) const {
CurrencyAmount* currAmt = NULL;
Formattable parseResult;
int32_t start = pos.getIndex();
UChar curbuf[4];
parse(text, parseResult, pos, curbuf);
if (pos.getIndex() != start && pos.getErrorIndex() == -1) {
UErrorCode ec = U_ZERO_ERROR;
currAmt = new CurrencyAmount(parseResult, curbuf, ec);
if (U_FAILURE(ec) || currAmt == NULL) {
pos.setIndex(start); // indicate failure
if ( currAmt != NULL ) {
delete currAmt;
currAmt = NULL;
}
}
}
return currAmt;
}
/**
* Parses the given text as either a number or a currency amount.
* Parses the given text as a number, optionally providing a currency amount.
* @param text the string to parse
* @param result output parameter for the result
* @param result output parameter for the numeric result.
* @param parsePosition input-output position; on input, the
* position within text to match; must have 0 <= pos.getIndex() <
* text.length(); on output, the position after the last matched
* character. If the parse fails, the position in unchanged upon
* output.
* @param parseCurrency if true, a currency amount is parsed;
* otherwise a Number is parsed
* @param currency if non-NULL, it should point to a 4-UChar buffer.
* In this case the text is parsed as a currency format, and the
* ISO 4217 code for the parsed currency is put into the buffer.
* Otherwise the text is parsed as a non-currency format.
*/
void DecimalFormat::parse(const UnicodeString& text,
Formattable& result,
ParsePosition& parsePosition,
UBool parseCurrency) const {
UChar* currency) const {
int32_t startIdx, backup;
int32_t i = startIdx = backup = parsePosition.getIndex();
@ -1658,8 +1674,6 @@ void DecimalFormat::parse(const UnicodeString& text,
// status is used to record whether a number is infinite.
UBool status[fgStatusLength];
UChar curbuf[4];
UChar* currency = parseCurrency ? curbuf : NULL;
DigitList *digits = new DigitList;
if (digits == NULL) {
return; // no way to report error from here.
@ -1705,13 +1719,6 @@ void DecimalFormat::parse(const UnicodeString& text,
}
result.adoptDigitList(digits);
}
if (parseCurrency) {
UErrorCode ec = U_ZERO_ERROR;
Formattable n(result);
result.adoptObject(new CurrencyAmount(n, curbuf, ec));
U_ASSERT(U_SUCCESS(ec)); // should always succeed
}
}

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1997-2011, International Business Machines Corporation and *
* Copyright (C) 1997-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -623,27 +623,29 @@ NumberFormat::parse(const UnicodeString& text,
}
}
Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
Formattable& result,
ParsePosition& pos) const {
CurrencyAmount* NumberFormat::parseCurrency(const UnicodeString& text,
ParsePosition& pos) const {
// Default implementation only -- subclasses should override
CurrencyAmount* currAmt = NULL;
Formattable parseResult;
int32_t start = pos.getIndex();
parse(text, result, pos);
if (pos.getIndex() != start) {
parse(text, parseResult, pos);
if (pos.getIndex() != start && pos.getErrorIndex() == -1) {
UChar curr[4];
UErrorCode ec = U_ZERO_ERROR;
getEffectiveCurrency(curr, ec);
if (U_SUCCESS(ec)) {
Formattable n(result);
CurrencyAmount *tempCurAmnt = new CurrencyAmount(n, curr, ec); // Use for null testing.
if (U_FAILURE(ec) || tempCurAmnt == NULL) {
currAmt = new CurrencyAmount(parseResult, curr, ec);
if (U_FAILURE(ec) || currAmt == NULL) {
pos.setIndex(start); // indicate failure
} else {
result.adoptObject(tempCurAmnt);
if ( currAmt != NULL ) {
delete currAmt;
currAmt = NULL;
}
}
}
}
return result;
return currAmt;
}
// -------------------------------------

View File

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 1997-2011, International Business Machines
* Copyright (C) 1997-2012, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@ -37,6 +37,7 @@
#include "unicode/locid.h"
#include "unicode/fpositer.h"
#include "unicode/stringpiece.h"
#include "unicode/curramt.h"
U_NAMESPACE_BEGIN
@ -1108,6 +1109,7 @@ public:
Formattable& result,
UErrorCode& status) const;
#ifndef U_HIDE_DRAFT_API
/**
* Parses text from the given string as a currency amount. Unlike
* the parse() method, this method will attempt to parse a generic
@ -1118,18 +1120,18 @@ public:
* (U+00A4) in its prefix or suffix.
*
* @param text the string to parse
* @param result output parameter to receive result. This will have
* its currency set to the parsed ISO currency code.
* @param pos input-output position; on input, the position within
* text to match; must have 0 <= pos.getIndex() < text.length();
* on output, the position after the last matched character. If
* the parse fails, the position in unchanged upon output.
* @return a reference to result
* @internal
* @param pos input-output position; on input, the position within text
* to match; must have 0 <= pos.getIndex() < text.length();
* on output, the position after the last matched character.
* If the parse fails, the position in unchanged upon output.
* @return if parse succeeds, a pointer to a newly-created CurrencyAmount
* object (owned by the caller) containing information about
* the parsed currency; if parse fails, this is NULL.
* @draft ICU 49
*/
virtual Formattable& parseCurrency(const UnicodeString& text,
Formattable& result,
ParsePosition& pos) const;
virtual CurrencyAmount* parseCurrency(const UnicodeString& text,
ParsePosition& pos) const;
#endif /* U_HIDE_DRAFT_API */
/**
* Returns the decimal format symbols, which is generally not changed
@ -1944,7 +1946,7 @@ private:
void parse(const UnicodeString& text,
Formattable& result,
ParsePosition& pos,
UBool parseCurrency) const;
UChar* currency) const;
enum {
fgStatusInfinite,
@ -2179,7 +2181,7 @@ private:
* and plural currency style. And the patterns are set through applyPattern.
*/
// TODO: innerclass?
/* This is not needed in the class declaration, so it is moved into decimfmp.cpp
/* This is not needed in the class declaration, so it is moved into decimfmp.cpp
struct AffixPatternsForCurrency : public UMemory {
// negative prefix pattern
UnicodeString negPrefixPatternForCurrency;
@ -2209,7 +2211,7 @@ private:
* equals to 3, such as the pattern contains 3 currency sign or
* the formatter style is currency plural format style.
*/
/* This is not needed in the class declaration, so it is moved into decimfmp.cpp
/* This is not needed in the class declaration, so it is moved into decimfmp.cpp
struct AffixesForCurrency : public UMemory {
// negative prefix
UnicodeString negPrefixForCurrency;

View File

@ -36,6 +36,7 @@
#include "unicode/unum.h" // UNumberFormatStyle
#include "unicode/locid.h"
#include "unicode/stringpiece.h"
#include "unicode/curramt.h"
class NumberFormatTest;
@ -569,6 +570,7 @@ public:
Formattable& result,
UErrorCode& status) const;
#ifndef U_HIDE_DRAFT_API
/**
* Parses text from the given string as a currency amount. Unlike
* the parse() method, this method will attempt to parse a generic
@ -579,18 +581,18 @@ public:
* (U+00A4) in its prefix or suffix.
*
* @param text the string to parse
* @param result output parameter to receive result. This will have
* its currency set to the parsed ISO currency code.
* @param pos input-output position; on input, the position within
* text to match; must have 0 <= pos.getIndex() < text.length();
* on output, the position after the last matched character. If
* the parse fails, the position in unchanged upon output.
* @return a reference to result
* @internal
* @param pos input-output position; on input, the position within text
* to match; must have 0 <= pos.getIndex() < text.length();
* on output, the position after the last matched character.
* If the parse fails, the position in unchanged upon output.
* @return if parse succeeds, a pointer to a newly-created CurrencyAmount
* object (owned by the caller) containing information about
* the parsed currency; if parse fails, this is NULL.
* @draft ICU 49
*/
virtual Formattable& parseCurrency(const UnicodeString& text,
Formattable& result,
ParsePosition& pos) const;
virtual CurrencyAmount* parseCurrency(const UnicodeString& text,
ParsePosition& pos) const;
#endif /* U_HIDE_DRAFT_API */
/**
* Return true if this format will parse numbers as integers
@ -1060,7 +1062,7 @@ NumberFormat::isParseIntegerOnly() const
inline UBool
NumberFormat::isLenient() const
{
return fLenient;
return fLenient;
}
inline UnicodeString&

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2011, International Business Machines
* Copyright (C) 1996-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
* Modification History:
@ -318,7 +318,6 @@ parseRes(Formattable& res,
const UChar* text,
int32_t textLength,
int32_t *parsePos /* 0 = start */,
UBool parseCurrency,
UErrorCode *status)
{
if(U_FAILURE(*status))
@ -331,11 +330,7 @@ parseRes(Formattable& res,
if(parsePos != 0)
pp.setIndex(*parsePos);
if (parseCurrency) {
((const NumberFormat*)fmt)->parseCurrency(src, res, pp);
} else {
((const NumberFormat*)fmt)->parse(src, res, pp);
}
((const NumberFormat*)fmt)->parse(src, res, pp);
if(pp.getErrorIndex() != -1) {
*status = U_PARSE_ERROR;
@ -355,7 +350,7 @@ unum_parse( const UNumberFormat* fmt,
UErrorCode *status)
{
Formattable res;
parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
parseRes(res, fmt, text, textLength, parsePos, status);
return res.getLong(*status);
}
@ -367,7 +362,7 @@ unum_parseInt64( const UNumberFormat* fmt,
UErrorCode *status)
{
Formattable res;
parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
parseRes(res, fmt, text, textLength, parsePos, status);
return res.getInt64(*status);
}
@ -379,7 +374,7 @@ unum_parseDouble( const UNumberFormat* fmt,
UErrorCode *status)
{
Formattable res;
parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
parseRes(res, fmt, text, textLength, parsePos, status);
return res.getDouble(*status);
}
@ -400,7 +395,7 @@ unum_parseDecimal(const UNumberFormat* fmt,
return -1;
}
Formattable res;
parseRes(res, fmt, text, textLength, parsePos, FALSE, status);
parseRes(res, fmt, text, textLength, parsePos, status);
StringPiece sp = res.getDecimalNumber(*status);
if (U_FAILURE(*status)) {
return -1;
@ -423,15 +418,38 @@ unum_parseDoubleCurrency(const UNumberFormat* fmt,
int32_t* parsePos, /* 0 = start */
UChar* currency,
UErrorCode* status) {
Formattable res;
parseRes(res, fmt, text, textLength, parsePos, TRUE, status);
double doubleVal = 0.0;
currency[0] = 0;
const CurrencyAmount* c;
if (res.getType() == Formattable::kObject &&
(c = dynamic_cast<const CurrencyAmount*>(res.getObject())) != NULL) {
u_strcpy(currency, c->getISOCurrency());
if (U_FAILURE(*status)) {
return doubleVal;
}
return res.getDouble(*status);
int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
const UnicodeString src((UChar*)text, len, len);
ParsePosition pp;
if (parsePos != NULL) {
pp.setIndex(*parsePos);
}
*status = U_PARSE_ERROR; // assume failure, reset if succeed
CurrencyAmount* currAmt = ((const NumberFormat*)fmt)->parseCurrency(src, pp);
if (pp.getErrorIndex() != -1) {
if (parsePos != NULL) {
*parsePos = pp.getErrorIndex();
}
if (currAmt != NULL) {
delete currAmt;
}
} else {
if (parsePos != NULL) {
*parsePos = pp.getIndex();
}
if (currAmt != NULL) {
*status = U_ZERO_ERROR;
u_strcpy(currency, currAmt->getISOCurrency());
doubleVal = currAmt->getNumber().getDouble(*status);
delete currAmt;
}
}
return doubleVal;
}
U_CAPI const char* U_EXPORT2

View File

@ -159,9 +159,11 @@ NumberFormatTest::TestAPI(void)
}
ParsePosition ppos;
test->parseCurrency("",bla,ppos);
if(U_FAILURE(status)) {
errln("Problems accessing the parseCurrency function for NumberFormat");
CurrencyAmount* currAmt = test->parseCurrency("",ppos);
// old test for (U_FAILURE(status)) was bogus here, method does not set status!
if (currAmt != NULL) {
errln("Parsed empty string as currency");
delete currAmt;
}
delete test;
@ -854,10 +856,10 @@ NumberFormatTest::TestParse(void)
// -------------------------------------
static const char *lenientAffixTestCases[] = {
"(1)",
"( 1)",
"(1 )",
"( 1 )"
"(1)",
"( 1)",
"(1 )",
"( 1 )"
};
static const char *lenientMinusTestCases[] = {
@ -867,33 +869,33 @@ static const char *lenientMinusTestCases[] = {
};
static const char *lenientCurrencyTestCases[] = {
"$1,000",
"$ 1,000",
"$1000",
"$ 1000",
"$1 000.00",
"$ 1 000.00",
"$ 1\\u00A0000.00",
"1000.00"
"$1,000",
"$ 1,000",
"$1000",
"$ 1000",
"$1 000.00",
"$ 1 000.00",
"$ 1\\u00A0000.00",
"1000.00"
};
static const char *lenientNegativeCurrencyTestCases[] = {
"($1,000)",
"($ 1,000)",
"($1000)",
"($ 1000)",
"($1 000.00)",
"($ 1 000.00)",
"( $ 1,000.00 )",
"($ 1\\u00A0000.00)",
"(1000.00)"
"($1,000)",
"($ 1,000)",
"($1000)",
"($ 1000)",
"($1 000.00)",
"($ 1 000.00)",
"( $ 1,000.00 )",
"($ 1\\u00A0000.00)",
"(1000.00)"
};
static const char *lenientPercentTestCases[] = {
"25%",
" 25%",
" 25 %",
"25 %",
"25%",
" 25%",
" 25 %",
"25 %",
"25\\u00A0%",
"25"
};
@ -4064,7 +4066,7 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
"Latvian Lats1.00",
"Latvian Ruble1.00",
"Latvian lats1.00",
"Latvian lati.00",
"Latvian lati1.00",
"Latvian ruble1.00",
"Latvian rubles1.00",
"Lebanese Pound1.00",
@ -6015,14 +6017,16 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
if (numFmt != NULL && U_SUCCESS(status)) {
Formattable parseResult;
ParsePosition parsePos;
numFmt->parseCurrency(formatted, parseResult, parsePos);
if (parsePos.getIndex() == 0 ||
(parseResult.getType() == Formattable::kDouble &&
parseResult.getDouble() != 1.0)) {
errln("wrong parsing, " + formatted);
errln("data: " + formatted);
CurrencyAmount* currAmt = numFmt->parseCurrency(formatted, parsePos);
if (currAmt != NULL) {
double doubleVal = currAmt->getNumber().getDouble(status);
if ( doubleVal != 1.0 ) {
errln("Parsed as currency value other than 1.0: " + formatted + " -> " + doubleVal);
}
delete currAmt;
} else {
errln("Failed to parse as currency: " + formatted);
}
} else {
dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));
@ -6037,14 +6041,12 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
UErrorCode status = U_ZERO_ERROR;
NumberFormat* numFmt = NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
if (numFmt != NULL && U_SUCCESS(status)) {
Formattable parseResult;
ParsePosition parsePos;
numFmt->parseCurrency(formatted, parseResult, parsePos);
if (parsePos.getIndex() > 0 ||
(parseResult.getType() == Formattable::kDouble &&
parseResult.getDouble() == 1.0)) {
errln("parsed but should not be: " + formatted);
errln("data: " + formatted);
CurrencyAmount* currAmt = numFmt->parseCurrency(formatted, parsePos);
if (currAmt != NULL) {
double doubleVal = currAmt->getNumber().getDouble(status);
errln("Parsed as currency, should not have: " + formatted + " -> " + doubleVal);
delete currAmt;
}
} else {
dataerrln("Unable to create NumberFormat. - %s", u_errorName(status));