mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-20 20:19:32 +00:00
ICU-2821 service registration for currency
X-SVN-Rev: 11706
This commit is contained in:
parent
d72b0318f0
commit
4dc960f3a4
6 changed files with 244 additions and 9 deletions
|
@ -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&
|
||||
|
|
|
@ -339,6 +339,7 @@ public:
|
|||
virtual ~NFFactory()
|
||||
{
|
||||
delete _delegate;
|
||||
delete _ids;
|
||||
}
|
||||
|
||||
virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue