ICU-1097 move currency.* to ucurr.* and change ISO code parameters from char* to UChar*
X-SVN-Rev: 9049
This commit is contained in:
parent
62039179f9
commit
29f886f412
@ -55,7 +55,7 @@ nultrans.o remtrans.o titletrn.o tolowtrn.o toupptrn.o anytrans.o \
|
||||
name2uni.o uni2name.o unitohex.o nortrans.o quant.o transreg.o \
|
||||
nfrs.o nfrule.o nfsubs.o rbnf.o esctrn.o unesctrn.o \
|
||||
funcrepl.o strrepl.o tridpars.o caniter.o \
|
||||
currency.o
|
||||
ucurr.o
|
||||
|
||||
|
||||
STATIC_OBJECTS = $(OBJECTS:.o=.$(STATIC_O))
|
||||
|
@ -44,7 +44,8 @@
|
||||
#include "unicode/uchar.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "unicode/currency.h"
|
||||
#include "unicode/ucurr.h"
|
||||
#include "unicode/ustring.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
@ -244,7 +245,7 @@ DecimalFormat::construct(UErrorCode& status,
|
||||
}
|
||||
|
||||
if (symbolsToAdopt == NULL) {
|
||||
ucurr_forLocale(uloc_getDefault(), currency, &status);
|
||||
setCurrencyForLocale(uloc_getDefault(), status);
|
||||
} else {
|
||||
setCurrencyForSymbols();
|
||||
}
|
||||
@ -252,6 +253,19 @@ DecimalFormat::construct(UErrorCode& status,
|
||||
applyPattern(*pattern, FALSE /*not localized*/,parseErr, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets our currency to be the default currency for the given locale.
|
||||
*/
|
||||
void DecimalFormat::setCurrencyForLocale(const char* locale, UErrorCode& ec) {
|
||||
const UChar* c = ucurr_forLocale(locale, &ec);
|
||||
if (c == NULL) {
|
||||
*currency = 0;
|
||||
} else {
|
||||
u_strncpy(currency, c, 3);
|
||||
currency[3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DecimalFormat::~DecimalFormat()
|
||||
@ -1453,11 +1467,7 @@ DecimalFormat::setCurrencyForSymbols() {
|
||||
def.getSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
|
||||
fSymbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
|
||||
def.getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)) {
|
||||
ucurr_forLocale(fSymbols->getLocale().getName(), currency, &ec);
|
||||
/* test for buffer overflows */
|
||||
if (U_FAILURE(ec)) {
|
||||
currency[0] = 0; // Use DFS currency info
|
||||
}
|
||||
setCurrencyForLocale(fSymbols->getLocale().getName(), ec);
|
||||
} else {
|
||||
currency[0] = 0; // Use DFS currency info
|
||||
}
|
||||
@ -1957,8 +1967,10 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
||||
}
|
||||
UnicodeString s;
|
||||
if (currency[0] != 0) {
|
||||
s = intl ? UnicodeString(currency, "")
|
||||
: ucurr_getSymbolAsUnicodeString(currency, fSymbols->getLocale());
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
int32_t len;
|
||||
s = UnicodeString(intl ? currency
|
||||
: ucurr_getSymbol(currency, fSymbols->getLocale().getName(), &len, &ec));
|
||||
} else {
|
||||
s = intl ? fSymbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)
|
||||
: fSymbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
|
||||
@ -2996,13 +3008,13 @@ void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
|
||||
* null.
|
||||
* @since ICU 2.2
|
||||
*/
|
||||
void DecimalFormat::setCurrency(const char* theCurrency) {
|
||||
void DecimalFormat::setCurrency(const UChar* 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.
|
||||
|
||||
uprv_strncpy(currency, theCurrency, 3);
|
||||
u_strncpy(currency, theCurrency, 3);
|
||||
currency[3] = 0;
|
||||
|
||||
if (fIsCurrencyFormat) {
|
||||
@ -3025,7 +3037,7 @@ void DecimalFormat::setCurrency(const char* theCurrency) {
|
||||
* the standard ones for its locale.
|
||||
* @since ICU 2.2
|
||||
*/
|
||||
const char* DecimalFormat::getCurrency() const {
|
||||
const UChar* DecimalFormat::getCurrency() const {
|
||||
return currency;
|
||||
}
|
||||
|
||||
|
201
icu4c/source/i18n/ucurr.cpp
Normal file
201
icu4c/source/i18n/ucurr.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
* Copyright (c) 2002, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*/
|
||||
#include "unicode/ucurr.h"
|
||||
#include "cstring.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/resbund.h"
|
||||
#include "unicode/ustring.h"
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Constants
|
||||
|
||||
// Default currency meta data of last resort. We try to use the
|
||||
// defaults encoded in the meta data resource bundle. If there is a
|
||||
// configuration/build error and these are not available, we use these
|
||||
// hard-coded defaults (which should be identical).
|
||||
static const int32_t LAST_RESORT_DATA[] = { 2, 0 };
|
||||
|
||||
// POW10[i] = 10^i, i=0..MAX_POW10
|
||||
static const int32_t POW10[] = { 1, 10, 100, 1000, 10000, 100000,
|
||||
1000000, 10000000, 100000000, 1000000000 };
|
||||
|
||||
static const int32_t MAX_POW10 = (sizeof(POW10)/sizeof(POW10[0])) - 1;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Resource tags
|
||||
|
||||
// Tag for meta-data, in root.
|
||||
static const char CURRENCY_META[] = "CurrencyMeta";
|
||||
|
||||
// Tag for default meta-data, in CURRENCY_META
|
||||
static const char DEFAULT_META[] = "DEFAULT";
|
||||
|
||||
// Tag for legacy currency elements data
|
||||
static const char CURRENCY_ELEMENTS[] = "CurrencyElements";
|
||||
|
||||
// Tag for localized display names (symbols) of currencies
|
||||
static const char CURRENCIES[] = "Currencies";
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Code
|
||||
|
||||
/**
|
||||
* Unfortunately, we have to convert the UChar* currency code to char*
|
||||
* to use it as a resource key.
|
||||
*/
|
||||
static inline char*
|
||||
_16to8(char* resultOfLen4, const UChar* currency) {
|
||||
u_austrncpy(resultOfLen4, currency, 3);
|
||||
resultOfLen4[3] = 0;
|
||||
return resultOfLen4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to look up currency data. Result is an array of
|
||||
* two integers. The first is the fraction digits. The second is the
|
||||
* rounding increment, or 0 if none. The rounding increment is in
|
||||
* units of 10^(-fraction_digits).
|
||||
*/
|
||||
static const int32_t*
|
||||
_findData(const UChar* currency) {
|
||||
|
||||
// Get CurrencyMeta resource out of root locale file. [This may
|
||||
// move out of the root locale file later; if it does, update this
|
||||
// code.]
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
ResourceBundle currencyMeta =
|
||||
ResourceBundle((char*)0, Locale(""), ec).get(CURRENCY_META, ec);
|
||||
|
||||
if (U_FAILURE(ec)) {
|
||||
// Config/build error; return hard-coded defaults
|
||||
return LAST_RESORT_DATA;
|
||||
}
|
||||
|
||||
// Look up our currency, or if that's not available, then DEFAULT
|
||||
char buf[4];
|
||||
ResourceBundle rb = currencyMeta.get(_16to8(buf, currency), ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
rb = currencyMeta.get(DEFAULT_META, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
// Config/build error; return hard-coded defaults
|
||||
return LAST_RESORT_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t len;
|
||||
const int32_t *data = rb.getIntVector(len, ec);
|
||||
if (U_FAILURE(ec) || len < 2) {
|
||||
// Config/build error; return hard-coded defaults
|
||||
return LAST_RESORT_DATA;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
U_CAPI const UChar* U_EXPORT2
|
||||
ucurr_forLocale(const char* locale,
|
||||
UErrorCode* ec) {
|
||||
|
||||
// TODO: ? Establish separate resource for locale->currency mapping
|
||||
// ? <IF> we end up deleting the CurrencyElements resource.
|
||||
// ? In the meantime the CurrencyElements tag has exactly the
|
||||
// ? data we want.
|
||||
|
||||
// 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 (ec != NULL && U_SUCCESS(*ec)) {
|
||||
UResourceBundle* rb = ures_open(NULL, locale, ec);
|
||||
UResourceBundle* ce = ures_getByKey(rb, CURRENCY_ELEMENTS, NULL, ec);
|
||||
int32_t len;
|
||||
const UChar* s = ures_getStringByIndex(ce, 1, &len, ec);
|
||||
ures_close(ce);
|
||||
ures_close(rb);
|
||||
// All resource data SHOULD be of length 3. If it is not,
|
||||
// then the resource data is in error and we don't return it.
|
||||
if (U_SUCCESS(*ec) && len == 3) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U_CAPI const UChar* U_EXPORT2
|
||||
ucurr_getSymbol(const UChar* currency,
|
||||
const char* locale,
|
||||
int32_t* len, // fillin
|
||||
UErrorCode* ec) {
|
||||
|
||||
if (ec == NULL || U_FAILURE(*ec)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Look up the Currencies resource for the given locale. The
|
||||
// Currencies locale data looks like this:
|
||||
//|en {
|
||||
//| Currencies {
|
||||
//| USD { "$" }
|
||||
//| CHF { "sFr" }
|
||||
//| //...
|
||||
//| }
|
||||
//|}
|
||||
|
||||
const UChar* s = NULL;
|
||||
char buf[4];
|
||||
UResourceBundle* rb = ures_open(NULL, locale, ec);
|
||||
UResourceBundle* rb_c = ures_getByKey(rb, CURRENCIES, NULL, ec);
|
||||
s = ures_getStringByKey(rb_c, _16to8(buf, currency), len, ec);
|
||||
ures_close(rb_c);
|
||||
UBool found = U_SUCCESS(*ec);
|
||||
|
||||
if (!found) {
|
||||
// Since the Currencies resource is not fully populated yet,
|
||||
// check to see if we can find the currency in the
|
||||
// CurrencyElements resource.
|
||||
*ec = U_ZERO_ERROR;
|
||||
rb_c = ures_getByKey(rb, CURRENCY_ELEMENTS, NULL, ec);
|
||||
const UChar* elem1 = ures_getStringByIndex(rb_c, 1, len, ec);
|
||||
if (U_SUCCESS(*ec) && u_strcmp(elem1, currency) == 0) {
|
||||
s = ures_getStringByIndex(rb_c, 0, len, ec);
|
||||
found = U_SUCCESS(*ec);
|
||||
}
|
||||
ures_close(rb_c);
|
||||
|
||||
if (!found) {
|
||||
// If we fail to find a match, use the full ISO code
|
||||
s = currency;
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(rb);
|
||||
return s;
|
||||
}
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
ucurr_getDefaultFractionDigits(const UChar* currency) {
|
||||
return (_findData(currency))[0];
|
||||
}
|
||||
|
||||
U_CAPI double U_EXPORT2
|
||||
ucurr_getRoundingIncrement(const UChar* currency) {
|
||||
const int32_t *data = _findData(currency);
|
||||
|
||||
// If there is no rounding, or if the meta data is invalid,
|
||||
// return 0.0 to indicate no rounding.
|
||||
if (data[1] == 0 || data[0] < 0 || data[0] > MAX_POW10) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Return data[1] / 10^(data[0]). The only actual rounding data,
|
||||
// as of this writing, is CHF { 2, 25 }.
|
||||
return double(data[1]) / POW10[data[0]];
|
||||
}
|
||||
|
||||
//eof
|
83
icu4c/source/i18n/unicode/ucurr.h
Normal file
83
icu4c/source/i18n/unicode/ucurr.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
* Copyright (c) 2002, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
* $Source: /xsrl/Nsvn/icu/icu/source/i18n/unicode/ucurr.h,v $
|
||||
* $Revision: 1.1 $
|
||||
**********************************************************************
|
||||
*/
|
||||
#ifndef _UCURR_H_
|
||||
#define _UCURR_H_
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
/**
|
||||
* The ucurr API encapsulates information about a currency, as defined by
|
||||
* ISO 4217. A currency is represented by a 3-character string
|
||||
* containing its ISO 4217 code. This API can return various data
|
||||
* necessary the proper display of a currency:
|
||||
*
|
||||
* <ul><li>A display symbol, for a specific locale
|
||||
* <li>The number of fraction digits to display
|
||||
* <li>A rounding increment
|
||||
* </ul>
|
||||
*
|
||||
* The <tt>DecimalFormat</tt> class uses these data to display
|
||||
* currencies.
|
||||
* @author Alan Liu
|
||||
* @since ICU 2.2
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a currency code for the default currency in the given
|
||||
* locale.
|
||||
* @param locale the locale for which to retrieve a currency code
|
||||
* @param ec error code
|
||||
* @return a pointer to a 3-character ISO 4217 currency code, or
|
||||
* NULL if none is found. The result string may NOT be null
|
||||
* terminated.
|
||||
*/
|
||||
U_CAPI const UChar* U_EXPORT2
|
||||
ucurr_forLocale(const char* locale,
|
||||
UErrorCode* ec);
|
||||
|
||||
/**
|
||||
* Returns the display string for the given currency in the
|
||||
* given locale. For example, the display string for the USD
|
||||
* currency object in the en_US locale is "$".
|
||||
* @param currency null-terminated 3-letter ISO 4217 code
|
||||
* @param locale locale in which to display currency
|
||||
* @param len fill-in parameter to receive length of result
|
||||
* @param ec error code
|
||||
* @return pointer to display string of 'len' UChars. If the
|
||||
* resource data contains no entry for 'currency', then
|
||||
* 'currency' itself is returned. The result string may NOT be
|
||||
* null terminated.
|
||||
*/
|
||||
U_CAPI const UChar* U_EXPORT2
|
||||
ucurr_getSymbol(const UChar* currency,
|
||||
const char* locale,
|
||||
int32_t* len,
|
||||
UErrorCode* ec);
|
||||
|
||||
/**
|
||||
* Returns the number of the number of fraction digits that should
|
||||
* be displayed for the given currency.
|
||||
* @param currency null-terminated 3-letter ISO 4217 code
|
||||
* @return a non-negative number of fraction digits to be
|
||||
* displayed
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
ucurr_getDefaultFractionDigits(const UChar* currency);
|
||||
|
||||
/**
|
||||
* Returns the rounding increment for the given currency, or 0.0 if no
|
||||
* rounding is done by the currency.
|
||||
* @param currency null-terminated 3-letter ISO 4217 code
|
||||
* @return the non-negative rounding increment, or 0.0 if none
|
||||
*/
|
||||
U_CAPI double U_EXPORT2
|
||||
ucurr_getRoundingIncrement(const UChar* currency);
|
||||
|
||||
#endif
|
@ -541,7 +541,7 @@ unum_getTextAttribute(const UNumberFormat* fmt,
|
||||
return 1;
|
||||
|
||||
case UNUM_CURRENCY_CODE:
|
||||
res = UnicodeString(((DecimalFormat*)fmt)->getCurrency(), "");
|
||||
res = UnicodeString(((DecimalFormat*)fmt)->getCurrency());
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -586,11 +586,8 @@ unum_setTextAttribute( UNumberFormat* fmt,
|
||||
((DecimalFormat*)fmt)->setPadCharacter(*newValue);
|
||||
break;
|
||||
|
||||
case UNUM_CURRENCY_CODE: {
|
||||
char currency[4];
|
||||
val.extract(0, 3, currency, "");
|
||||
currency[3] = 0;
|
||||
((DecimalFormat*)fmt)->setCurrency(currency); }
|
||||
case UNUM_CURRENCY_CODE:
|
||||
((DecimalFormat*)fmt)->setCurrency(newValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "numfmtst.h"
|
||||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/currency.h"
|
||||
#include "unicode/ucurr.h"
|
||||
#include <float.h>
|
||||
|
||||
// *****************************************************************************
|
||||
@ -494,9 +494,10 @@ void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
|
||||
double value, const UnicodeString& string) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
DecimalFormat& fmt = * (DecimalFormat*) &nf;
|
||||
char curr[4] = {'-','-','-',0};
|
||||
const UChar DEFAULT_CURR[] = {45/*-*/,0};
|
||||
const UChar* curr = DEFAULT_CURR;
|
||||
if (*locale.getLanguage() != 0) {
|
||||
ucurr_forLocale(locale.getName(), curr, &ec);
|
||||
curr = ucurr_forLocale(locale.getName(), &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("FAIL: UCurrency::forLocale");
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user