2002-07-08 17:57:10 +00:00
|
|
|
/*
|
|
|
|
**********************************************************************
|
|
|
|
* Copyright (c) 2002, International Business Machines
|
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
**********************************************************************
|
|
|
|
*/
|
2002-09-20 01:54:48 +00:00
|
|
|
|
|
|
|
#include "unicode/utypes.h"
|
|
|
|
|
|
|
|
#if !UCONFIG_NO_FORMATTING
|
|
|
|
|
2002-07-08 17:57:10 +00:00
|
|
|
#include "unicode/ucurr.h"
|
|
|
|
#include "unicode/locid.h"
|
|
|
|
#include "unicode/resbund.h"
|
|
|
|
#include "unicode/ustring.h"
|
2002-07-12 21:42:24 +00:00
|
|
|
#include "cstring.h"
|
2002-07-08 17:57:10 +00:00
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
// 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*
|
2002-09-20 17:44:40 +00:00
|
|
|
myUCharsToChars(char* resultOfLen4, const UChar* currency) {
|
|
|
|
u_UCharsToChars(currency, resultOfLen4, 3);
|
2002-07-08 17:57:10 +00:00
|
|
|
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];
|
2002-09-20 17:44:40 +00:00
|
|
|
ResourceBundle rb = currencyMeta.get(myUCharsToChars(buf, currency), ec);
|
2002-07-08 17:57:10 +00:00
|
|
|
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);
|
2002-09-20 17:44:40 +00:00
|
|
|
s = ures_getStringByKey(rb_c, myUCharsToChars(buf, currency), len, ec);
|
2002-07-08 17:57:10 +00:00
|
|
|
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]];
|
|
|
|
}
|
|
|
|
|
2002-09-20 01:54:48 +00:00
|
|
|
#endif /* #if !UCONFIG_NO_FORMATTING */
|
|
|
|
|
2002-07-08 17:57:10 +00:00
|
|
|
//eof
|