ICU-1097 initial C++ implementation

X-SVN-Rev: 8598
This commit is contained in:
Alan Liu 2002-05-13 19:33:05 +00:00
parent 566db2ce09
commit 2327cfe7d8
8 changed files with 432 additions and 25 deletions

View File

@ -55,8 +55,8 @@ cpdtrans.o hextouni.o rbt.o rbt_data.o rbt_pars.o rbt_rule.o rbt_set.o \
nultrans.o remtrans.o titletrn.o tolowtrn.o toupptrn.o \
name2uni.o uni2name.o unitohex.o nortrans.o unifilt.o quant.o transreg.o \
nfrs.o nfrule.o nfsubs.o rbnf.o upropset.o util.o esctrn.o unesctrn.o \
funcrepl.o strrepl.o tridpars.o unifunct.o caniter.o usetiter.o
funcrepl.o strrepl.o tridpars.o unifunct.o caniter.o usetiter.o \
currency.o
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))

View File

@ -0,0 +1,163 @@
/*
**********************************************************************
* Copyright (c) 2002, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* $Source: /xsrl/Nsvn/icu/icu/source/i18n/Attic/currency.cpp,v $
* $Date: 2002/05/13 19:32:16 $
* $Revision: 1.1 $
**********************************************************************
*/
#include "unicode/currency.h"
#include "cstring.h"
#include "unicode/locid.h"
#include "unicode/resbund.h"
U_NAMESPACE_BEGIN
/**
* TEMPORARY data structure.
*/
struct UCurrencyData {
char* code;
int32_t fractionDigits;
double rounding;
};
/**
* TEMPORARY Static data block giving currency fraction digits and
* rounding increments. The first entry with a NULL code gives
* the default values for currencies not listed here. The last
* entry with a NULL code marks the end.
*/
static UCurrencyData DATA[] = {
// TODO Temporary implementation; Redo this
// Code, Fraction digits, Rounding increment
{ NULL , 2, 0 }, // Default
{ "BYB", 0, 0 },
{ "CHF", 2, 0.25 },
{ "ESP", 0, 0 },
{ "IQD", 3, 0 },
{ "ITL", 0, 0 },
{ "JOD", 3, 0 },
{ "JPY", 0, 0 },
{ "KWD", 3, 0 },
{ "LUF", 0, 0 },
{ "LYD", 3, 0 },
{ "PTE", 0, 0 },
{ "PYG", 0, 0 },
{ "TND", 3, 0 },
{ "TRL", 0, 0 },
{ NULL , 0, 0 }, // END
};
/**
* TEMPORARY Internal function to look up currency data.
*/
static int32_t
_findData(const UnicodeString& currency) {
// TODO Temporary implementation; Redo this
// Convert currency code to char*
char isoCode[4];
currency.extract(0, 3, isoCode, "");
// Start from element 1
for (int32_t i=1; DATA[i].code != NULL; ++i) {
int32_t c = uprv_strcmp(DATA[i].code, isoCode);
if (c == 0) {
return i;
} else if (c > 0) {
break;
}
}
return 0; // Return default entry
}
/**
* Returns a currency object for the default currency in the given
* locale.
*/
UnicodeString
UCurrency::forLocale(const Locale& locale,
UErrorCode& ec) {
// Look up the CurrencyElements resource for this locale.
// It contains: [0] = currency symbol, e.g. "$";
// [1] = intl. currency symbol, e.g. "USD";
// [2] = monetary decimal separator, e.g. ".".
if (U_SUCCESS(ec)) {
ResourceBundle rb((char*)0, locale, ec);
return rb.get("CurrencyElements", ec).getStringEx(1, ec);
}
return "";
}
/**
* Returns the display string for this currency object in the
* given locale. For example, the display string for the USD
* currency object in the en_US locale is "$".
*/
UnicodeString
UCurrency::getSymbol(const UnicodeString& currency,
const Locale& locale) {
// Look up the Currencies resource for the given locale. The
// Currencies locale looks like this in the original C
// resource file:
//|en {
//| Currencies {
//| USD { "$" }
//| CHF { "sFr" }
//| //...
//| }
//|}
UErrorCode ec = U_ZERO_ERROR;
// Convert currency code to char*
char isoCode[4];
currency.extract(0, 3, isoCode, "");
ResourceBundle rb((char*)0, locale, ec);
UnicodeString result = rb.get("Currencies", ec).getStringEx(isoCode, ec);
if (U_SUCCESS(ec) && result.length() > 0) {
return result;
}
// Since the Currencies resource is not fully populated yet,
// check to see if we can find what we want in the CurrencyElements
// resource.
ec = U_ZERO_ERROR;
ResourceBundle ce = rb.get("CurrencyElements", ec);
if (ce.getStringEx(1, ec) == currency) {
return ce.getStringEx((int32_t)0, ec);
}
// If we fail to find a match, use the full ISO code
return currency;
}
/**
* Returns the number of the number of fraction digits that should
* be displayed for this currency.
* @return a non-negative number of fraction digits to be
* displayed
*/
int32_t
UCurrency::getDefaultFractionDigits(const UnicodeString& currency) {
// TODO Temporary implementation; Redo this
return DATA[_findData(currency)].fractionDigits;
}
/**
* Returns the rounding increment for this currency, or 0.0 if no
* rounding is done by this currency.
* @return the non-negative rounding increment, or 0.0 if none
*/
double
UCurrency::getRoundingIncrement(const UnicodeString& currency) {
// TODO Temporary implementation; Redo this
return DATA[_findData(currency)].rounding;
}
U_NAMESPACE_END
//eof

View File

@ -104,6 +104,8 @@ DecimalFormatSymbols::initialize(const Locale& locale, UErrorCode& status,
{
if (U_FAILURE(status)) return;
this->locale = locale;
ResourceBundle resource((char *)0, locale, status);
if (U_FAILURE(status))
{

View File

@ -43,6 +43,7 @@
#include "unicode/resbund.h"
#include "unicode/uchar.h"
#include "cmemory.h"
#include "unicode/currency.h"
U_NAMESPACE_BEGIN
@ -189,8 +190,7 @@ void
DecimalFormat::construct(UErrorCode& status,
UParseError& parseErr,
const UnicodeString* pattern,
DecimalFormatSymbols* symbolsToAdopt,
const Locale& locale)
DecimalFormatSymbols* symbolsToAdopt)
{
fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!!
// fDigitList = new DigitList(); // Do this BEFORE aborting on status failure!!!
@ -214,7 +214,7 @@ DecimalFormat::construct(UErrorCode& status,
if (fSymbols == NULL)
{
fSymbols = new DecimalFormatSymbols(locale, status);
fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
}
UnicodeString str;
@ -232,7 +232,13 @@ DecimalFormat::construct(UErrorCode& status,
{
return;
}
if (symbolsToAdopt == NULL) {
currency = UCurrency::forLocale(Locale::getDefault(), status);
} else {
setCurrencyForSymbols();
}
applyPattern(*pattern, FALSE /*not localized*/,parseErr, status);
}
@ -1402,9 +1408,43 @@ void
DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
{
adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
setCurrencyForSymbols();
expandAffixes();
}
/**
* Update the currency object to match the symbols. This method
* is used only when the caller has passed in a symbols object
* that may not be the default object for its locale.
*/
void
DecimalFormat::setCurrencyForSymbols() {
/*Bug 4212072
Update the affix strings accroding to symbols in order to keep
the affix strings up to date.
[Richard/GCL]
*/
// With the introduction of the Currency object, the currency
// symbols in the DFS object are ignored. For backward
// compatibility, we check any explicitly set DFS object. If it
// is a default symbols object for its locale, we change the
// currency object to one for that locale. If it is custom,
// we set the currency to null.
UErrorCode ec = U_ZERO_ERROR;
DecimalFormatSymbols def(fSymbols->getLocale(), ec);
if (fSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
def.getSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
fSymbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
def.getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)) {
currency = UCurrency::forLocale(fSymbols->getLocale(), ec);
} else {
currency.truncate(0); // Use DFS currency info
}
}
//------------------------------------------------------------------------------
// Gets the positive prefix of the number pattern.
@ -1885,17 +1925,27 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
if (c == kQuote) {
c = pattern.char32At(i++);
switch (c) {
case kCurrencySign:
{
if (i<pattern.length() &&
pattern.char32At(i) == kCurrencySign) {
++i;
affix += fSymbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
} else {
affix += fSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
}
case kCurrencySign: {
// As of ICU 2.2 we use the currency object, and
// ignore the currency symbols in the DFS, unless
// we have a null currency object. This occurs if
// resurrecting a pre-2.2 object or if the user
// sets a custom DFS.
UBool intl = i<pattern.length() &&
pattern.char32At(i) == kCurrencySign;
if (intl) {
++i;
}
continue;
UnicodeString s;
if (currency.length() != 0) {
s = intl ? currency
: UCurrency::getSymbol(currency, fSymbols->getLocale());
} else {
s = intl ? fSymbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)
: fSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
}
affix += s; }
break;
case kPatternPercent:
affix.append(fSymbols->getSymbol(DecimalFormatSymbols::kPercentSymbol));
break;
@ -2872,6 +2922,48 @@ void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
NumberFormat::setMinimumFractionDigits(uprv_min(newValue, kDoubleFractionDigits));
}
/**
* Sets the <tt>Currency</tt> object used to display currency
* amounts. This takes effect immediately, if this format is a
* currency format. If this format is not a currency format, then
* the currency object is used if and when this object becomes a
* currency format through the application of a new pattern.
* @param theCurrency new currency object to use. Must not be
* null.
* @since ICU 2.2
*/
void DecimalFormat::setCurrency(const UnicodeString& theCurrency) {
// If we are a currency format, then modify our affixes to
// encode the currency symbol for the given currency in our
// locale, and adjust the decimal digits and rounding for the
// given currency.
currency = theCurrency;
if (fIsCurrencyFormat) {
setRoundingIncrement(UCurrency::getRoundingIncrement(currency));
int32_t d = UCurrency::getDefaultFractionDigits(currency);
setMinimumFractionDigits(d);
setMaximumFractionDigits(d);
expandAffixes();
}
}
/**
* Gets the <tt>Currency</tt> object used to display currency
* amounts. This will be null if a object is resurrected with a
* custom DecimalFormatSymbols object, or if the user sets a
* custom DecimalFormatSymbols object. A custom
* DecimalFormatSymbols object has currency symbols that are not
* the standard ones for its locale.
* @since ICU 2.2
*/
UnicodeString DecimalFormat::getCurrency() const {
return currency;
}
U_NAMESPACE_END
//eof

View File

@ -44,8 +44,8 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /c
# ADD CPP /nologo /G6 /MD /Za /W3 /GX /Zi /O2 /Ob2 /I "..\..\include" /I "..\..\source\common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /D "U_I18N_IMPLEMENTATION" /FR /FD /GF /c
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /c
# ADD CPP /nologo /G6 /MD /Za /W3 /GX /Zi /O2 /Ob2 /I "..\..\include" /I "..\..\source\common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /D "U_I18N_IMPLEMENTATION" /FR /FD /GF /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -71,8 +71,8 @@ LINK32=link.exe
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /GZ /c
# ADD CPP /nologo /G6 /MDd /Za /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\source\common" /D "_WINDOWS" /D "_USRDLL" /D "I18N_EXPORTS" /D "U_I18N_IMPLEMENTATION" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "UDATA_MAP" /FR /FD /GF /GZ /c
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /GZ /c
# ADD CPP /nologo /G6 /MDd /Za /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\source\common" /D "_WINDOWS" /D "_USRDLL" /D "I18N_EXPORTS" /D "U_I18N_IMPLEMENTATION" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "UDATA_MAP" /FR /FD /GF /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
@ -98,7 +98,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /c
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN64" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /c
# ADD CPP /nologo /MD /Za /W3 /I "..\..\include" /I "..\..\source\common" /D"WIN64" /D"NDEBUG" /D"_WINDOWS" /D"_MBCS" /D"_USRDLL" /D"I18N_EXPORTS" /D"U_I18N_IMPLEMENTATION" /FR /FD /GF /c /O2 /GX /Op /QIA64_fmaopt /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Wp64 /Zm600
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win64
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win64
@ -110,7 +110,7 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:IA64
# ADD LINK32 icuuc.lib /nologo /base:"0x4a900000" /dll /machine:IA64 /out:"..\..\bin\icuin21.dll" /implib:"..\..\lib\icuin.lib" /libpath:"..\..\lib" /incremental:no
# SUBTRACT LINK32 /debug
# SUBTRACT LINK32 /debug
!ELSEIF "$(CFG)" == "i18n - Win64 Debug"
@ -125,7 +125,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /GZ /c
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN64" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "I18N_EXPORTS" /FD /GZ /c
# ADD CPP /nologo /MDd /Za /W3 /Gm /I "..\..\include" /I "..\..\source\common" /D"_WINDOWS" /D"_USRDLL" /D"I18N_EXPORTS" /D"U_I18N_IMPLEMENTATION" /D"WIN64" /D"_DEBUG" /D"_MBCS" /D"UDATA_MAP" /FR /FD /GF /GZ /c /Od /GX /Op /QIA64_fmaopt /D"_IA64_" /Zi /D"WIN64" /D"WIN32" /D"_AFX_NO_DAO_SUPPORT" /Wp64 /Zm600
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win64
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win64
@ -180,6 +180,10 @@ SOURCE=.\cpdtrans.cpp
# End Source File
# Begin Source File
SOURCE=.\currency.cpp
# End Source File
# Begin Source File
SOURCE=.\datefmt.cpp
# End Source File
# Begin Source File
@ -691,6 +695,53 @@ InputPath=.\unicode\cpdtrans.h
# End Source File
# Begin Source File
SOURCE=.\unicode\currency.h
!IF "$(CFG)" == "i18n - Win32 Release"
# Begin Custom Build
InputPath=.\unicode\currency.h
"..\..\include\unicode\currency.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(InputPath) ..\..\include\unicode
# End Custom Build
!ELSEIF "$(CFG)" == "i18n - Win32 Debug"
# Begin Custom Build
InputPath=.\unicode\currency.h
"..\..\include\unicode\currency.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(InputPath) ..\..\include\unicode
# End Custom Build
!ELSEIF "$(CFG)" == "i18n - Win64 Release"
# Begin Custom Build
InputPath=.\unicode\currency.h
"..\..\include\unicode\currency.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(InputPath) ..\..\include\unicode
# End Custom Build
!ELSEIF "$(CFG)" == "i18n - Win64 Debug"
# Begin Custom Build
InputPath=.\unicode\currency.h
"..\..\include\unicode\currency.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(InputPath) ..\..\include\unicode
# End Custom Build
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\unicode\datefmt.h
!IF "$(CFG)" == "i18n - Win32 Release"

View File

@ -0,0 +1,56 @@
/*
**********************************************************************
* Copyright (c) 2002, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* $Source: /xsrl/Nsvn/icu/icu/source/i18n/unicode/Attic/currency.h,v $
* $Revision: 1.1 $
**********************************************************************
*/
#ifndef UCURRENCY_H
#define UCURRENCY_H
#include "unicode/unistr.h"
U_NAMESPACE_BEGIN
class Locale;
class U_I18N_API UCurrency {
public:
/**
* Returns a currency object for the default currency in the given
* locale.
*/
static UnicodeString forLocale(const Locale& locale,
UErrorCode& ec);
/**
* Returns the display string for this currency object in the
* given locale. For example, the display string for the USD
* currency object in the en_US locale is "$".
*/
static UnicodeString getSymbol(const UnicodeString& currency,
const Locale& locale);
/**
* Returns the number of the number of fraction digits that should
* be displayed for this currency.
* @return a non-negative number of fraction digits to be
* displayed
*/
static int32_t getDefaultFractionDigits(const UnicodeString& currency);
/**
* Returns the rounding increment for this currency, or 0.0 if no
* rounding is done by this currency.
* @return the non-negative rounding increment, or 0.0 if none
*/
static double getRoundingIncrement(const UnicodeString& currency);
};
U_NAMESPACE_END
#endif

View File

@ -180,6 +180,11 @@ public:
*/
void setSymbol(ENumberFormatSymbol symbol, UnicodeString value);
/**
* Returns the locale for which this object was constructed.
*/
inline Locale getLocale() const;
#ifdef ICU_DECIMALFORMATSYMBOLS_USE_DEPRECATES
/**
* character used for zero. Different for Arabic, etc.
@ -483,8 +488,12 @@ private:
*/
void initialize();
void setCurrencyForSymbols();
UnicodeString fSymbols[kFormatSymbolCount];
Locale locale;
static const char fgNumberElements[];
static const char fgCurrencyElements[];
};
@ -511,6 +520,13 @@ DecimalFormatSymbols::setSymbol(ENumberFormatSymbol symbol, UnicodeString value)
}
}
// -------------------------------------
inline Locale
DecimalFormatSymbols::getLocale() const {
return locale;
}
#ifdef ICU_DECIMALFORMATSYMBOLS_USE_DEPRECATES
// -------------------------------------

View File

@ -986,6 +986,29 @@ public:
*/
virtual void setMinimumFractionDigits(int32_t newValue);
/**
* Sets the <tt>Currency</tt> object used to display currency
* amounts. This takes effect immediately, if this format is a
* currency format. If this format is not a currency format, then
* the currency object is used if and when this object becomes a
* currency format through the application of a new pattern.
* @param theCurrency new currency object to use. Must not be
* null.
* @since ICU 2.2
*/
void setCurrency(const UnicodeString& theCurrency);
/**
* Gets the <tt>Currency</tt> object used to display currency
* amounts. This will be null if a object is resurrected with a
* custom DecimalFormatSymbols object, or if the user sets a
* custom DecimalFormatSymbols object. A custom
* DecimalFormatSymbols object has currency symbols that are not
* the standard ones for its locale.
* @since ICU 2.2
*/
UnicodeString getCurrency() const;
/**
* The resource tags we use to retrieve decimal format data from
* locale resource bundles.
@ -1029,8 +1052,7 @@ private:
void construct(UErrorCode& status,
UParseError& parseErr,
const UnicodeString* pattern = 0,
DecimalFormatSymbols* symbolsToAdopt = 0,
const Locale& locale = Locale::getDefault()
DecimalFormatSymbols* symbolsToAdopt = 0
);
/**
@ -1106,6 +1128,8 @@ private:
UBool isGroupingPosition(int32_t pos) const;
void setCurrencyForSymbols();
/**
* Constants.
*/
@ -1144,6 +1168,9 @@ private:
int32_t fFormatWidth;
EPadPosition fPadPosition;
// ISO currency code
UnicodeString currency;
// Constants for characters used in programmatic (unlocalized) patterns.
static const UChar kPatternZeroDigit;
static const UChar kPatternGroupingSeparator;