ICU-2825 first implementation of MeasureFormat

X-SVN-Rev: 15015
This commit is contained in:
Alan Liu 2004-04-21 18:05:06 +00:00
parent 662b4b3704
commit 461f739085
11 changed files with 372 additions and 109 deletions

View file

@ -0,0 +1,78 @@
/*
**********************************************************************
* Copyright (c) 2004, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: April 20, 2004
* Since: ICU 3.0
**********************************************************************
*/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "currfmt.h"
#include "unicode/numfmt.h"
U_NAMESPACE_BEGIN
CurrencyFormat::CurrencyFormat(const Locale& locale, UErrorCode& ec) :
fmt(NULL) {
fmt = NumberFormat::createCurrencyInstance(locale, ec);
}
CurrencyFormat::CurrencyFormat(const CurrencyFormat& other) :
fmt(NULL) {
fmt = (NumberFormat*) other.fmt->clone();
}
CurrencyFormat::~CurrencyFormat() {
delete fmt;
}
UBool CurrencyFormat::operator==(const Format& other) const {
if (this == &other) {
return TRUE;
}
if (other.getDynamicClassID() != CurrencyFormat::getStaticClassID()) {
return FALSE;
}
const CurrencyFormat* c = (const CurrencyFormat*) &other;
return *fmt == *c->fmt;
}
Format* CurrencyFormat::clone() const {
return new CurrencyFormat(*this);
}
UnicodeString& CurrencyFormat::format(const Formattable& obj,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& ec) const {
return fmt->format(obj, appendTo, pos, ec);
}
UnicodeString& CurrencyFormat::format(const Formattable& obj,
UnicodeString& appendTo,
UErrorCode& ec) const {
return MeasureFormat::format(obj, appendTo, ec);
}
void CurrencyFormat::parseObject(const UnicodeString& source,
Formattable& result,
ParsePosition& pos) const {
fmt->parseCurrency(source, result, pos);
}
void CurrencyFormat::parseObject(const UnicodeString& source,
Formattable& result,
UErrorCode& ec) const {
MeasureFormat::parseObject(source, result, ec);
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyFormat)
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */

112
icu4c/source/i18n/currfmt.h Normal file
View file

@ -0,0 +1,112 @@
/*
**********************************************************************
* Copyright (c) 2004, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: April 20, 2004
* Since: ICU 3.0
**********************************************************************
*/
#ifndef CURRENCYFORMAT_H
#define CURRENCYFORMAT_H
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "unicode/measfmt.h"
U_NAMESPACE_BEGIN
class NumberFormat;
/**
* Temporary internal concrete subclass of MeasureFormat implementing
* parsing and formatting of currency amount objects. This class is
* likely to be redesigned and rewritten in the near future.
*
* <p>This class currently delegates to DecimalFormat for parsing and
* formatting.
*
* @see MeasureFormat
* @author Alan Liu
* @internal
*/
class U_I18N_API CurrencyFormat : public MeasureFormat {
public:
/**
* Construct a CurrencyFormat for the given locale.
*/
CurrencyFormat(const Locale& locale, UErrorCode& ec);
/**
* Copy constructor.
*/
CurrencyFormat(const CurrencyFormat& other);
/**
* Destructor.
*/
virtual ~CurrencyFormat();
/**
* Override Format API.
*/
virtual UBool operator==(const Format& other) const;
/**
* Override Format API.
*/
virtual Format* clone() const;
/**
* Override Format API.
*/
virtual UnicodeString& format(const Formattable& obj,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode& ec) const;
/**
* Redeclare Format API to prevent hiding.
*/
UnicodeString& format(const Formattable& obj,
UnicodeString& appendTo,
UErrorCode& ec) const;
/**
* Override Format API.
*/
virtual void parseObject(const UnicodeString& source,
Formattable& result,
ParsePosition& pos) const;
/**
* Redeclare Format API to prevent hiding.
*/
void parseObject(const UnicodeString& source,
Formattable& result,
UErrorCode& ec) const;
/**
* Override Format API.
*/
virtual UClassID getDynamicClassID() const;
/**
* Returns the class ID for this class.
*/
static UClassID getStaticClassID();
private:
NumberFormat* fmt;
};
U_NAMESPACE_END
#endif // #if !UCONFIG_NO_FORMATTING
#endif // #ifndef CURRENCYFORMAT_H

View file

@ -1198,12 +1198,6 @@ Formattable& DecimalFormat::parseCurrency(const UnicodeString& text,
return result;
}
Formattable& DecimalFormat::parseCurrency(const UnicodeString& text,
Formattable& result,
UErrorCode& status) const {
return NumberFormat::parseCurrency(text, result, status);
}
/**
* Parses the given text as either a number or a currency amount.
* @param text the string to parse

View file

@ -457,6 +457,12 @@
Outputs="..\..\include\unicode\$(InputFileName)"/>
</FileConfiguration>
</File>
<File
RelativePath=".\currfmt.cpp">
</File>
<File
RelativePath=".\currfmt.h">
</File>
<File
RelativePath=".\datefmt.cpp">
</File>
@ -660,6 +666,26 @@
<File
RelativePath=".\japancal.h">
</File>
<File
RelativePath=".\measfmt.cpp">
</File>
<File
RelativePath=".\unicode\measfmt.h">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode"
Outputs="..\..\include\unicode\$(InputFileName)"/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="copy &quot;$(InputPath)&quot; ..\..\include\unicode"
Outputs="..\..\include\unicode\$(InputFileName)"/>
</FileConfiguration>
</File>
<File
RelativePath=".\msgfmt.cpp">
</File>

View file

@ -0,0 +1,42 @@
/*
**********************************************************************
* Copyright (c) 2004, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: April 20, 2004
* Since: ICU 3.0
**********************************************************************
*/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "unicode/measfmt.h"
#include "currfmt.h"
U_NAMESPACE_BEGIN
MeasureFormat* MeasureFormat::createCurrencyFormat(const Locale& locale,
UErrorCode& ec) {
CurrencyFormat* fmt = NULL;
if (U_SUCCESS(ec)) {
fmt = new CurrencyFormat(locale, ec);
if (U_FAILURE(ec)) {
delete fmt;
fmt = NULL;
}
}
return fmt;
}
MeasureFormat* MeasureFormat::createCurrencyFormat(UErrorCode& ec) {
if (U_FAILURE(ec)) {
return NULL;
}
return MeasureFormat::createCurrencyFormat(Locale::getDefault(), ec);
}
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1997-2003, International Business Machines Corporation and *
* Copyright (C) 1997-2004, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -348,19 +348,6 @@ Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
return result;
}
Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
Formattable& result,
UErrorCode& ec) const {
if (U_SUCCESS(ec)) {
ParsePosition pos(0);
parseCurrency(text, result, pos);
if (pos.getIndex() == 0) {
ec = U_INVALID_FORMAT_ERROR;
}
}
return result;
}
// -------------------------------------
// Sets to only parse integers.

View file

@ -885,35 +885,12 @@ public:
* on output, the position after the last matched character. If
* the parse fails, the position in unchanged upon output.
* @return a reference to result
* @draft ICU 3.0
* @internal
*/
virtual Formattable& parseCurrency(const UnicodeString& text,
Formattable& result,
ParsePosition& pos) const;
// Redeclare here, otherwise function will be hidden
/**
* Parses text from the beginning of the given string as a
* currency amount. The method might not use the entire text of
* the given string. Unlike the parse() method, this method will
* attempt to parse a generic currency name, searching for a match
* of this object's locale's currency display names, or for a
* 3-letter ISO currency code. This method will fail if this
* format is not a currency format, that is, if it does not
* contain the currency pattern symbol (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 status input-output error code
* @return a reference to result
* @draft ICU 3.0
*/
Formattable& parseCurrency(const UnicodeString& text,
Formattable& result,
UErrorCode& status) const;
/**
* Returns the decimal format symbols, which is generally not changed
* by the programmer or user.

View file

@ -0,0 +1,61 @@
/*
**********************************************************************
* Copyright (c) 2004, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: April 20, 2004
* Since: ICU 3.0
**********************************************************************
*/
#ifndef MEASUREFORMAT_H
#define MEASUREFORMAT_H
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "unicode/format.h"
U_NAMESPACE_BEGIN
/**
* A formatter for measure objects. This is an abstract base class.
*
* <p>To format or parse a measure object, first create a formatter
* object using a MeasureFormat factory method. Then use that
* object's format and parse methods.
*
* @see Format
* @author Alan Liu
* @draft ICU 3.0
*/
class U_I18N_API MeasureFormat : public Format {
public:
/**
* Return a formatter for CurrencyAmount objects in the given
* locale.
* @param locale desired locale
* @param ec input-output error code
* @return a formatter object, or NULL upon error
* @draft ICU 3.0
*/
static MeasureFormat* createCurrencyFormat(const Locale& locale,
UErrorCode& ec);
/**
* Return a formatter for CurrencyAmount objects in the default
* locale.
* @param ec input-output error code
* @return a formatter object, or NULL upon error
* @draft ICU 3.0
*/
static MeasureFormat* createCurrencyFormat(UErrorCode& ec);
};
U_NAMESPACE_END
#endif // #if !UCONFIG_NO_FORMATTING
#endif // #ifndef MEASUREFORMAT_H

View file

@ -387,34 +387,12 @@ public:
* on output, the position after the last matched character. If
* the parse fails, the position in unchanged upon output.
* @return a reference to result
* @draft ICU 3.0
* @internal
*/
virtual Formattable& parseCurrency(const UnicodeString& text,
Formattable& result,
ParsePosition& pos) const;
/**
* Parses text from the beginning of the given string as a
* currency amount. The method might not use the entire text of
* the given string. Unlike the parse() method, this method will
* attempt to parse a generic currency name, searching for a match
* of this object's locale's currency display names, or for a
* 3-letter ISO currency code. This method will fail if this
* format is not a currency format, that is, if it does not
* contain the currency pattern symbol (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 status input-output error code
* @return a reference to result
* @draft ICU 3.0
*/
Formattable& parseCurrency(const UnicodeString& text,
Formattable& result,
UErrorCode& status) const;
/**
* Return true if this format will parse numbers as integers
* only. For example in the English locale, with ParseIntegerOnly

View file

@ -17,6 +17,7 @@
#include "unicode/decimfmt.h"
#include "unicode/ucurr.h"
#include "unicode/ustring.h"
#include "unicode/measfmt.h"
#include "digitlst.h"
#include "textfile.h"
#include "tokiter.h"
@ -1583,7 +1584,9 @@ void NumberFormatTest::TestCases() {
Locale loc("en", "US", "");
DecimalFormat *ref = 0, *fmt = 0;
UnicodeString pat, tok, str, out, where;
MeasureFormat *mfmt = 0;
UnicodeString pat, tok, mloc, str, out, where, currAmt;
Formattable n;
for (;;) {
ec = U_ZERO_ERROR;
@ -1609,7 +1612,6 @@ void NumberFormatTest::TestCases() {
case 3: // fp:
case 4: // rt:
case 5: // p:
case 8: // fpc:
if (!tokens.next(tok, ec)) goto error;
if (tok != "-") {
pat = tok;
@ -1620,7 +1622,7 @@ void NumberFormatTest::TestCases() {
ec = U_ZERO_ERROR;
if (!tokens.next(tok, ec)) goto error;
if (!tokens.next(tok, ec)) goto error;
if (cmd == 3 || cmd == 8) {
if (cmd == 3) {
if (!tokens.next(tok, ec)) goto error;
}
continue;
@ -1633,7 +1635,6 @@ void NumberFormatTest::TestCases() {
UnicodeString num;
if (!tokens.next(num, ec)) goto error;
if (!tokens.next(str, ec)) goto error;
Formattable n;
ref->parse(num, n, ec);
assertSuccess("parse", ec);
assertEquals(where + "\"" + pat + "\".format(" + num + ")",
@ -1652,36 +1653,6 @@ void NumberFormatTest::TestCases() {
n, m);
}
}
// fpc: <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
else if (cmd == 8) {
UnicodeString currAmt;
if (!tokens.next(currAmt, ec)) goto error;
if (!tokens.next(str, ec)) goto error;
Formattable n;
parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
if (assertSuccess("parseCurrencyAmount", ec)) {
UChar save[4];
u_strcpy(save, fmt->getCurrency());
assertEquals(where + "\"" + pat + "\".format(" + currAmt + ")",
str, fmt->format(n, out.remove(), ec));
assertSuccess("format", ec);
if (u_strcmp(save, fmt->getCurrency()) != 0) {
errln((UnicodeString)"FAIL: " + where +
"NumberFormat.getCurrency() => " + fmt->getCurrency() +
", expected " + save);
}
}
if (!tokens.next(currAmt, ec)) goto error;
parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
if (assertSuccess("parseCurrencyAmount", ec)) {
Formattable m;
fmt->parseCurrency(str, m, ec);
if (assertSuccess("parseCurrency", ec)) {
assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
n, m);
}
}
}
// p: <pattern or '-'> <string to parse> <exp. number>
else {
UnicodeString expstr;
@ -1696,6 +1667,42 @@ void NumberFormatTest::TestCases() {
exp, n);
}
break;
case 8: // fpc:
if (!tokens.next(tok, ec)) goto error;
if (tok != "-") {
mloc = tok;
delete mfmt;
mfmt = MeasureFormat::createCurrencyFormat(
Locale::createFromName(CharString(mloc)), ec);
if (U_FAILURE(ec)) {
errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
ec = U_ZERO_ERROR;
if (!tokens.next(tok, ec)) goto error;
if (!tokens.next(tok, ec)) goto error;
if (!tokens.next(tok, ec)) goto error;
continue;
}
}
// fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
if (!tokens.next(currAmt, ec)) goto error;
if (!tokens.next(str, ec)) goto error;
parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
if (assertSuccess("parseCurrencyAmount", ec)) {
assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
str, mfmt->format(n, out.remove(), ec));
assertSuccess("format", ec);
}
if (!tokens.next(currAmt, ec)) goto error;
parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
if (assertSuccess("parseCurrencyAmount", ec)) {
Formattable m;
mfmt->parseObject(str, m, ec);
if (assertSuccess("parseCurrency", ec)) {
assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
n, m);
}
}
break;
case 6:
// perr: <pattern or '-'> <invalid string>
errln("FAIL: Under construction");
@ -1759,6 +1766,7 @@ void NumberFormatTest::TestCases() {
}
done:
delete mfmt;
delete fmt;
delete ref;
}

View file

@ -72,14 +72,14 @@ rt: "" 123.456 "123.456"
rt: "" -123.456 "-123.456"
# Currency
fpc: "\u00A4 0.00" 1234.56/USD "$ 1234.56" 1234.56/USD
fpc: - 1234.56/JPY "\u00A5 1235" 1235/JPY
fpc: "en_US" 1234.56/USD "$1,234.56" 1234.56/USD
fpc: - 1234.56/JPY "\u00A51,235" 1235/JPY
# ISO codes that overlap display names (QQQ vs. Q)
fpc: - 123/QQQ "QQQ 123.00" 123/QQQ # QQQ is fake
fpc: - 123/GTQ "Q 123.00" 123/GTQ
fpc: - 123/QQQ "QQQ123.00" 123/QQQ # QQQ is fake
fpc: - 123/GTQ "Q123.00" 123/GTQ
# ChoiceFormat-based display names
fpc: - 1/INR "Re. 1.00" 1/INR
fpc: - 2/INR "Rs. 2.00" 2/INR
fpc: - 1/INR "Re.1.00" 1/INR
fpc: - 2/INR "Rs.2.00" 2/INR
# Display names with shared prefix (YDD vs. Y)
fpc: - 100/YDD "YDD 100.00" 100/YDD
fpc: - 100/CNY "Y 100.00" 100/CNY
fpc: - 100/YDD "YDD100.00" 100/YDD
fpc: - 100/CNY "Y100.00" 100/CNY