ICU-2821 service registration for currency

X-SVN-Rev: 11706
This commit is contained in:
Doug Felt 2003-04-25 18:02:09 +00:00
parent d72b0318f0
commit 4dc960f3a4
6 changed files with 244 additions and 9 deletions

View file

@ -875,8 +875,11 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC
const Hashtable*
ICUService::getVisibleIDMap(UErrorCode& status) const {
if (U_SUCCESS(status) && idCache == NULL) {
ICUService* ncthis = (ICUService*)this; // cast away semantic const
if (U_FAILURE(status)) return NULL;
ICUService* ncthis = (ICUService*)this; // cast away semantic const
Mutex mutex(&ncthis->lock);
if (idCache == NULL) {
ncthis->idCache = new Hashtable();
if (idCache == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
@ -899,7 +902,7 @@ ICUService::getVisibleIDMap(UErrorCode& status) const {
UnicodeString&
ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result) const
{
return getDisplayName(id, result, Locale::getDefault());
return getDisplayName(id, result, Locale::getDefault());
}
UnicodeString&

View file

@ -339,6 +339,7 @@ public:
virtual ~NFFactory()
{
delete _delegate;
delete _ids;
}
virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const

View file

@ -15,6 +15,7 @@
#include "unicode/ustring.h"
#include "cstring.h"
#include "uassert.h"
#include "iculserv.h"
//------------------------------------------------------------
// Constants
@ -117,11 +118,9 @@ _findMetaData(const UChar* currency) {
return data;
}
U_CAPI const UChar* U_EXPORT2
ucurr_forLocale(const char* locale,
UErrorCode* ec) {
const UChar*
internal_ucurr_forLocale(const char* locale, UErrorCode* ec) {
if (ec != NULL && U_SUCCESS(*ec)) {
// Extract the country name and variant name. We only
// recognize two variant names, EURO and PREEURO.
char country[12];
@ -145,11 +144,152 @@ ucurr_forLocale(const char* locale,
if (U_SUCCESS(*ec)) {
return s;
}
}
return NULL;
}
// ------------------------------------------
//
// Registration
//
//-------------------------------------------
static ICULocaleService* gService = NULL;
// -------------------------------------
class CurrencyRef : public UObject {
public:
const UChar* str;
CurrencyRef(const UChar* isoCode) : str(isoCode) {}
inline virtual UClassID getDynamicClassID() const {
return (UClassID)&fgClassID;
}
inline static UClassID getStaticClassID() {
return (UClassID)&fgClassID;
}
private:
/**
* Class ID
*/
static const char fgClassID;
};
const char CurrencyRef::fgClassID = 0;
// -------------------------------------
CurrencyRef*
makeCurrencyRef(const Locale& loc, UErrorCode& status) {
const UChar* isoCode = internal_ucurr_forLocale(loc.getName(), &status);
if (isoCode) {
return new CurrencyRef(isoCode);
}
return NULL;
}
// -------------------------------------
class ICUCurrencyFactory : public ICUResourceBundleFactory {
protected:
virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* service, UErrorCode& status) const {
return makeCurrencyRef(loc, status);
}
};
// -------------------------------------
class ICUCurrencyService : public ICULocaleService {
public:
ICUCurrencyService()
: ICULocaleService("Currency")
{
UErrorCode status = U_ZERO_ERROR;
registerFactory(new ICUCurrencyFactory(), status);
}
virtual UObject* cloneInstance(UObject* instance) const {
return new CurrencyRef(((CurrencyRef*)instance)->str);
}
virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const {
LocaleKey& lkey = (LocaleKey&)key;
Locale loc;
lkey.currentLocale(loc);
return makeCurrencyRef(loc, status);
}
virtual UBool isDefault() const {
return countFactories() == 1;
}
};
// -------------------------------------
static UMTX gLock = 0;
static ICULocaleService*
getService(void)
{
Mutex mutex(&gLock);
if (gService == NULL) {
gService = new ICUCurrencyService();
}
return gService;
}
// -------------------------------------
U_CAPI UCurrRegistryKey U_EXPORT2
ucurr_register(const UChar* isoCode, const char* locale, UErrorCode *status)
{
URegistryKey result = NULL;
if (status && U_SUCCESS(*status)) {
CurrencyRef* ref = new CurrencyRef(isoCode);
Locale loc(locale);
result = getService()->registerInstance(ref, loc, *status);
}
return result;
}
// -------------------------------------
U_CAPI UBool U_EXPORT2
ucurr_unregister(UCurrRegistryKey key, UErrorCode* status)
{
if (status && U_SUCCESS(*status)) {
if (gService != NULL) {
return gService->unregister(key, *status);
}
*status = U_ILLEGAL_ARGUMENT_ERROR;
}
return FALSE;
}
// -------------------------------------
U_CAPI const UChar* U_EXPORT2
ucurr_forLocale(const char* locale,
UErrorCode* ec) {
if (ec != NULL && U_SUCCESS(*ec)) {
if (gService) {
const UChar* result = NULL;
Locale loc(locale);
CurrencyRef* ref = (CurrencyRef*)gService->get(loc, *ec);
if (ref) {
result = ref->str; // points to original
delete ref;
}
return result;
}
return internal_ucurr_forLocale(locale, ec);
}
return NULL;
}
/**
* Modify the given locale name by removing the rightmost _-delimited
* element. If there is none, empty the string ("" == root).
@ -302,6 +442,18 @@ ucurr_getRoundingIncrement(const UChar* currency) {
return double(data[1]) / POW10[data[0]];
}
/**
* Release all static memory held by breakiterator.
*/
U_CFUNC UBool currency_cleanup(void) {
if (gService) {
delete gService;
gService = NULL;
}
umtx_destroy(&gLock);
return TRUE;
}
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof

View file

@ -4,7 +4,7 @@
* Corporation and others. All Rights Reserved.
**********************************************************************
* $Source: /xsrl/Nsvn/icu/icu/source/i18n/unicode/ucurr.h,v $
* $Revision: 1.6 $
* $Revision: 1.7 $
**********************************************************************
*/
#ifndef _UCURR_H_
@ -14,6 +14,8 @@
#if !UCONFIG_NO_FORMATTING
typedef const void* UCurrRegistryKey;
/**
* The ucurr API encapsulates information about a currency, as defined by
* ISO 4217. A currency is represented by a 3-character string
@ -66,6 +68,29 @@ typedef enum UCurrNameStyle {
UCURR_LONG_NAME
} UCurrNameStyle;
/**
* Register an (existing) ISO 4217 currency code for the given locale.
* @param isoCode the three-letter ISO 4217 currency code
* @param locale the locale for which to register this currency code
* @param status the in/out status code, no special meanings are assigned
* @return a registry key that can be used to unregister this currency code
* @draft ICU 2.6
*/
U_CAPI UCurrRegistryKey U_EXPORT2
ucurr_register(const UChar* isoCode,
const char* locale,
UErrorCode* status);
/**
* Unregister the previously-registered currency definitions using the
* URegistryKey returned from ucurr_register. Key becomes invalid after
* a successful call and should not be used again.
* @param key the retgistry key returned by a previous call to ucurr_register
* @param status the in/out status code, no special meanings are assigned
* @return TRUE if the currency for this key was successfully unregistered
*/
U_CAPI UBool U_EXPORT2
ucurr_unregister(UCurrRegistryKey key, UErrorCode* status);
/**
* Returns the display name for the given currency in the
* given locale. For example, the display name for the USD

View file

@ -58,6 +58,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
CASE(17,TestWhiteSpaceParsing);
CASE(18,TestComplexCurrency);
CASE(19,TestRegCurrency);
default: name = ""; break;
}
}
@ -1159,6 +1160,54 @@ void NumberFormatTest::TestCurrencyPatterns(void) {
}
}
void NumberFormatTest::TestRegCurrency(void) {
UErrorCode status = U_ZERO_ERROR;
const UChar* USD = ucurr_forLocale("en_US", &status);
const UChar* YEN = ucurr_forLocale("ja_JP", &status);
UCurrRegistryKey enkey = ucurr_register(YEN, "en", &status);
UCurrRegistryKey enUSEUROkey = ucurr_register(EUR, "en_US_EURO", &status);
if (u_strcmp(YEN, ucurr_forLocale("en", &status)) != 0) {
errln("FAIL: didn't return YEN registered for en");
}
if (u_strcmp(USD, ucurr_forLocale("en_US", &status)) != 0) {
errln("FAIL: didn't return USD for en_US");
}
if (u_strcmp(EUR, ucurr_forLocale("en_US_EURO", &status)) != 0) {
errln("FAIL: didn't return EUR for en_US_EURO");
}
if (u_strcmp(YEN, ucurr_forLocale("en_XX_BAR", &status)) != 0) {
errln("FAIL: didn't return YEN as fallback for en_XX_BAR");
}
if (!ucurr_unregister(enkey, &status)) {
errln("FAIL: couldn't unregister enkey");
}
if (ucurr_forLocale("en", &status) != NULL) {
errln("FAIL: didn't return NULL for en after unregister");
}
status = U_ZERO_ERROR; // reset
if (u_strcmp(EUR, ucurr_forLocale("en_US_EURO", &status)) != 0) {
errln("FAIL: didn't return EUR for en_US_EURO after unregister of en");
}
if (u_strcmp(USD, ucurr_forLocale("en_US_BLAH", &status)) != 0) {
errln("FAIL: didn't return USD for en_US_BLAH");
}
if (!ucurr_unregister(enUSEUROkey, &status)) {
errln("FAIL: couldn't unregister enUSEUROkey");
}
if (ucurr_forLocale("en_US_EURO", &status) != NULL) {
errln("FAIL: didn't return NULL for en_US_EURO after unregister of en_US_EURO");
}
status = U_ZERO_ERROR; // reset
}
//----------------------------------------------------------------------
// Support methods
//----------------------------------------------------------------------

View file

@ -89,6 +89,11 @@ class NumberFormatTest: public CalendarTimeZoneTest {
void TestPad(void);
void TestPatterns2(void);
/**
* Test currency registration.
*/
void TestRegCurrency(void);
private:
static UBool equalValue(const Formattable& a, const Formattable& b);