diff options
Diffstat (limited to 'Build/source/libs/icu/icu-xetex/i18n/ucurr.cpp')
-rw-r--r-- | Build/source/libs/icu/icu-xetex/i18n/ucurr.cpp | 1124 |
1 files changed, 1124 insertions, 0 deletions
diff --git a/Build/source/libs/icu/icu-xetex/i18n/ucurr.cpp b/Build/source/libs/icu/icu-xetex/i18n/ucurr.cpp new file mode 100644 index 00000000000..d6b7f432fda --- /dev/null +++ b/Build/source/libs/icu/icu-xetex/i18n/ucurr.cpp @@ -0,0 +1,1124 @@ +/* +********************************************************************** +* Copyright (c) 2002-2007, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/ucurr.h" +#include "unicode/locid.h" +#include "unicode/ures.h" +#include "unicode/ustring.h" +#include "unicode/choicfmt.h" +#include "unicode/parsepos.h" +#include "ustr_imp.h" +#include "cmemory.h" +#include "cstring.h" +#include "uassert.h" +#include "umutex.h" +#include "ucln_in.h" +#include "uenumimp.h" +#include "uresimp.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; + +#define ISO_COUNTRY_CODE_LENGTH 3 + +//------------------------------------------------------------ +// Resource tags +// + +static const char CURRENCY_DATA[] = "supplementalData"; +// Tag for meta-data, in root. +static const char CURRENCY_META[] = "CurrencyMeta"; + +// Tag for map from countries to currencies, in root. +static const char CURRENCY_MAP[] = "CurrencyMap"; + +// Tag for default meta-data, in CURRENCY_META +static const char DEFAULT_META[] = "DEFAULT"; + +// Variant for legacy pre-euro mapping in CurrencyMap +static const char VAR_PRE_EURO[] = "PREEURO"; + +// Variant for legacy euro mapping in CurrencyMap +static const char VAR_EURO[] = "EURO"; + +// Variant delimiter +static const char VAR_DELIM = '_'; +static const char VAR_DELIM_STR[] = "_"; + +// Variant for legacy euro mapping in CurrencyMap +//static const char VAR_DELIM_EURO[] = "_EURO"; + +#define VARIANT_IS_EMPTY 0 +#define VARIANT_IS_EURO 0x1 +#define VARIANT_IS_PREEURO 0x2 + +// Tag for localized display names (symbols) of currencies +static const char CURRENCIES[] = "Currencies"; + +// Marker character indicating that a display name is a ChoiceFormat +// pattern. Strings that start with one mark are ChoiceFormat +// patterns. Strings that start with 2 marks are static strings, and +// the first mark is deleted. +static const UChar CHOICE_FORMAT_MARK = 0x003D; // Equals sign + +static const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0}; + +//------------------------------------------------------------ +// Code + +/** + * Unfortunately, we have to convert the UChar* currency code to char* + * to use it as a resource key. + */ +static inline char* +myUCharsToChars(char* resultOfLen4, const UChar* currency) { + u_UCharsToChars(currency, resultOfLen4, ISO_COUNTRY_CODE_LENGTH); + resultOfLen4[ISO_COUNTRY_CODE_LENGTH] = 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* +_findMetaData(const UChar* currency, UErrorCode& ec) { + + if (currency == 0 || *currency == 0) { + if (U_SUCCESS(ec)) { + ec = U_ILLEGAL_ARGUMENT_ERROR; + } + return LAST_RESORT_DATA; + } + + // Get CurrencyMeta resource out of root locale file. [This may + // move out of the root locale file later; if it does, update this + // code.] + UResourceBundle* currencyData = ures_openDirect(NULL, CURRENCY_DATA, &ec); + UResourceBundle* currencyMeta = ures_getByKey(currencyData, CURRENCY_META, currencyData, &ec); + + if (U_FAILURE(ec)) { + ures_close(currencyMeta); + // 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[ISO_COUNTRY_CODE_LENGTH+1]; + UErrorCode ec2 = U_ZERO_ERROR; // local error code: soft failure + UResourceBundle* rb = ures_getByKey(currencyMeta, myUCharsToChars(buf, currency), NULL, &ec2); + if (U_FAILURE(ec2)) { + ures_close(rb); + rb = ures_getByKey(currencyMeta,DEFAULT_META, NULL, &ec); + if (U_FAILURE(ec)) { + ures_close(currencyMeta); + ures_close(rb); + // Config/build error; return hard-coded defaults + return LAST_RESORT_DATA; + } + } + + int32_t len; + const int32_t *data = ures_getIntVector(rb, &len, &ec); + if (U_FAILURE(ec) || len != 2) { + // Config/build error; return hard-coded defaults + if (U_SUCCESS(ec)) { + ec = U_INVALID_FORMAT_ERROR; + } + ures_close(currencyMeta); + ures_close(rb); + return LAST_RESORT_DATA; + } + + ures_close(currencyMeta); + ures_close(rb); + return data; +} + +// ------------------------------------- + +/** + * @see VARIANT_IS_EURO + * @see VARIANT_IS_PREEURO + */ +static uint32_t +idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec) +{ + uint32_t variantType = 0; + // !!! this is internal only, assumes buffer is not null and capacity is sufficient + // Extract the country name and variant name. We only + // recognize two variant names, EURO and PREEURO. + char variant[ULOC_FULLNAME_CAPACITY]; + uloc_getCountry(locale, countryAndVariant, capacity, ec); + uloc_getVariant(locale, variant, sizeof(variant), ec); + if (variant[0] != 0) { + variantType = (0 == uprv_strcmp(variant, VAR_EURO)) + | ((0 == uprv_strcmp(variant, VAR_PRE_EURO)) << 1); + if (variantType) + { + uprv_strcat(countryAndVariant, VAR_DELIM_STR); + uprv_strcat(countryAndVariant, variant); + } + } + return variantType; +} + +// ------------------------------------------ +// +// Registration +// +//------------------------------------------- + +// don't use ICUService since we don't need fallback + +#if !UCONFIG_NO_SERVICE +U_CDECL_BEGIN +static UBool U_CALLCONV currency_cleanup(void); +U_CDECL_END +struct CReg; + +/* Remember to call umtx_init(&gCRegLock) before using it! */ +static UMTX gCRegLock = 0; +static CReg* gCRegHead = 0; + +struct CReg : public U_NAMESPACE_QUALIFIER UMemory { + CReg *next; + UChar iso[ISO_COUNTRY_CODE_LENGTH+1]; + char id[ULOC_FULLNAME_CAPACITY]; + + CReg(const UChar* _iso, const char* _id) + : next(0) + { + int32_t len = (int32_t)uprv_strlen(_id); + if (len > (int32_t)(sizeof(id)-1)) { + len = (sizeof(id)-1); + } + uprv_strncpy(id, _id, len); + id[len] = 0; + uprv_memcpy(iso, _iso, ISO_COUNTRY_CODE_LENGTH * sizeof(const UChar)); + iso[ISO_COUNTRY_CODE_LENGTH] = 0; + } + + static UCurrRegistryKey reg(const UChar* _iso, const char* _id, UErrorCode* status) + { + if (status && U_SUCCESS(*status) && _iso && _id) { + CReg* n = new CReg(_iso, _id); + if (n) { + umtx_init(&gCRegLock); + umtx_lock(&gCRegLock); + if (!gCRegHead) { + /* register for the first time */ + ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup); + } + n->next = gCRegHead; + gCRegHead = n; + umtx_unlock(&gCRegLock); + return n; + } + *status = U_MEMORY_ALLOCATION_ERROR; + } + return 0; + } + + static UBool unreg(UCurrRegistryKey key) { + UBool found = FALSE; + umtx_init(&gCRegLock); + umtx_lock(&gCRegLock); + + CReg** p = &gCRegHead; + while (*p) { + if (*p == key) { + *p = ((CReg*)key)->next; + delete (CReg*)key; + found = TRUE; + break; + } + p = &((*p)->next); + } + + umtx_unlock(&gCRegLock); + return found; + } + + static const UChar* get(const char* id) { + const UChar* result = NULL; + umtx_init(&gCRegLock); + umtx_lock(&gCRegLock); + CReg* p = gCRegHead; + + /* register cleanup of the mutex */ + ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup); + while (p) { + if (uprv_strcmp(id, p->id) == 0) { + result = p->iso; + break; + } + p = p->next; + } + umtx_unlock(&gCRegLock); + return result; + } + + /* This doesn't need to be thread safe. It's for u_cleanup only. */ + static void cleanup(void) { + while (gCRegHead) { + CReg* n = gCRegHead; + gCRegHead = gCRegHead->next; + delete n; + } + umtx_destroy(&gCRegLock); + } +}; + +/** + * Release all static memory held by currency. + */ +U_CDECL_BEGIN +static UBool U_CALLCONV currency_cleanup(void) { +#if !UCONFIG_NO_SERVICE + CReg::cleanup(); +#endif + return TRUE; +} +U_CDECL_END + +// ------------------------------------- + +U_CAPI UCurrRegistryKey U_EXPORT2 +ucurr_register(const UChar* isoCode, const char* locale, UErrorCode *status) +{ + if (status && U_SUCCESS(*status)) { + char id[ULOC_FULLNAME_CAPACITY]; + idForLocale(locale, id, sizeof(id), status); + return CReg::reg(isoCode, id, status); + } + return NULL; +} + +// ------------------------------------- + +U_CAPI UBool U_EXPORT2 +ucurr_unregister(UCurrRegistryKey key, UErrorCode* status) +{ + if (status && U_SUCCESS(*status)) { + return CReg::unreg(key); + } + return FALSE; +} +#endif /* UCONFIG_NO_SERVICE */ + +// ------------------------------------- + +U_CAPI int32_t U_EXPORT2 +ucurr_forLocale(const char* locale, + UChar* buff, + int32_t buffCapacity, + UErrorCode* ec) +{ + int32_t resLen = 0; + const UChar* s = NULL; + if (ec != NULL && U_SUCCESS(*ec)) { + if ((buff && buffCapacity) || !buffCapacity) { + UErrorCode localStatus = U_ZERO_ERROR; + char id[ULOC_FULLNAME_CAPACITY]; + if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) { + // there is a currency keyword. Try to see if it's valid + if(buffCapacity > resLen) { + u_charsToUChars(id, buff, resLen); + } + } else { + // get country or country_variant in `id' + uint32_t variantType = idForLocale(locale, id, sizeof(id), ec); + + if (U_FAILURE(*ec)) { + return 0; + } + +#if !UCONFIG_NO_SERVICE + const UChar* result = CReg::get(id); + if (result) { + if(buffCapacity > u_strlen(result)) { + u_strcpy(buff, result); + } + return u_strlen(result); + } +#endif + // Remove variants, which is only needed for registration. + char *idDelim = strchr(id, VAR_DELIM); + if (idDelim) { + idDelim[0] = 0; + } + + // Look up the CurrencyMap element in the root bundle. + UResourceBundle *rb = ures_openDirect(NULL, CURRENCY_DATA, &localStatus); + UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); + UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); + UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus); + s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus); + + /* + Get the second item when PREEURO is requested, and this is a known Euro country. + If the requested variant is PREEURO, and this isn't a Euro country, assume + that the country changed over to the Euro in the future. This is probably + an old version of ICU that hasn't been updated yet. The latest currency is + probably correct. + */ + if (U_SUCCESS(localStatus)) { + if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) { + currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus); + s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus); + } + else if ((variantType & VARIANT_IS_EURO)) { + s = EUR_STR; + } + } + ures_close(countryArray); + ures_close(currencyReq); + + if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) + { + // We don't know about it. Check to see if we support the variant. + uloc_getParent(locale, id, sizeof(id), ec); + *ec = U_USING_FALLBACK_WARNING; + return ucurr_forLocale(id, buff, buffCapacity, ec); + } + else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) { + // There is nothing to fallback to. Report the failure/warning if possible. + *ec = localStatus; + } + if (U_SUCCESS(*ec)) { + if(buffCapacity > resLen) { + u_strcpy(buff, s); + } + } + } + return u_terminateUChars(buff, buffCapacity, resLen, ec); + } else { + *ec = U_ILLEGAL_ARGUMENT_ERROR; + } + } + return resLen; +} + +// end registration + +/** + * Modify the given locale name by removing the rightmost _-delimited + * element. If there is none, empty the string ("" == root). + * NOTE: The string "root" is not recognized; do not use it. + * @return TRUE if the fallback happened; FALSE if locale is already + * root (""). + */ +static UBool fallback(char *loc) { + if (!*loc) { + return FALSE; + } + UErrorCode status = U_ZERO_ERROR; + uloc_getParent(loc, loc, (int32_t)uprv_strlen(loc), &status); + /* + char *i = uprv_strrchr(loc, '_'); + if (i == NULL) { + i = loc; + } + *i = 0; + */ + return TRUE; +} + + +U_CAPI const UChar* U_EXPORT2 +ucurr_getName(const UChar* currency, + const char* locale, + UCurrNameStyle nameStyle, + UBool* isChoiceFormat, // fillin + int32_t* len, // fillin + UErrorCode* ec) { + + // Look up the Currencies resource for the given locale. The + // Currencies locale data looks like this: + //|en { + //| Currencies { + //| USD { "US$", "US Dollar" } + //| CHF { "Sw F", "Swiss Franc" } + //| INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" } + //| //... + //| } + //|} + + if (U_FAILURE(*ec)) { + return 0; + } + + int32_t choice = (int32_t) nameStyle; + if (choice < 0 || choice > 1) { + *ec = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + // In the future, resource bundles may implement multi-level + // fallback. That is, if a currency is not found in the en_US + // Currencies data, then the en Currencies data will be searched. + // Currently, if a Currencies datum exists in en_US and en, the + // en_US entry hides that in en. + + // We want multi-level fallback for this resource, so we implement + // it manually. + + // Use a separate UErrorCode here that does not propagate out of + // this function. + UErrorCode ec2 = U_ZERO_ERROR; + + char loc[ULOC_FULLNAME_CAPACITY]; + uloc_getName(locale, loc, sizeof(loc), &ec2); + if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { + *ec = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + char buf[ISO_COUNTRY_CODE_LENGTH+1]; + myUCharsToChars(buf, currency); + + const UChar* s = NULL; + ec2 = U_ZERO_ERROR; + UResourceBundle* rb = ures_open(NULL, loc, &ec2); + + rb = ures_getByKey(rb, CURRENCIES, rb, &ec2); + + // Fetch resource with multi-level resource inheritance fallback + rb = ures_getByKeyWithFallback(rb, buf, rb, &ec2); + + s = ures_getStringByIndex(rb, choice, len, &ec2); + ures_close(rb); + + // If we've succeeded we're done. Otherwise, try to fallback. + // If that fails (because we are already at root) then exit. + if (U_SUCCESS(ec2)) { + if (ec2 == U_USING_DEFAULT_WARNING + || (ec2 == U_USING_FALLBACK_WARNING && *ec != U_USING_DEFAULT_WARNING)) { + *ec = ec2; + } + } + + // Determine if this is a ChoiceFormat pattern. One leading mark + // indicates a ChoiceFormat. Two indicates a static string that + // starts with a mark. In either case, the first mark is ignored, + // if present. Marks in the rest of the string have no special + // meaning. + *isChoiceFormat = FALSE; + if (U_SUCCESS(ec2)) { + U_ASSERT(s != NULL); + int32_t i=0; + while (i < *len && s[i] == CHOICE_FORMAT_MARK && i < 2) { + ++i; + } + *isChoiceFormat = (i == 1); + if (i != 0) ++s; // Skip over first mark + return s; + } + + // If we fail to find a match, use the ISO 4217 code + *len = u_strlen(currency); // Should == ISO_COUNTRY_CODE_LENGTH, but maybe not...? + *ec = U_USING_DEFAULT_WARNING; + return currency; +} + +U_CAPI void +uprv_parseCurrency(const char* locale, + const U_NAMESPACE_QUALIFIER UnicodeString& text, + U_NAMESPACE_QUALIFIER ParsePosition& pos, + UChar* result, + UErrorCode& ec) +{ + U_NAMESPACE_USE + + // TODO: There is a slight problem with the pseudo-multi-level + // fallback implemented here. More-specific locales don't + // properly shield duplicate entries in less-specific locales. + // This problem will go away when real multi-level fallback is + // implemented. We could also fix this by recording (in a + // hash) which codes are used at each level of fallback, but + // this doesn't seem warranted. + + if (U_FAILURE(ec)) { + return; + } + + // Look up the Currencies resource for the given locale. The + // Currencies locale data looks like this: + //|en { + //| Currencies { + //| USD { "US$", "US Dollar" } + //| CHF { "Sw F", "Swiss Franc" } + //| INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" } + //| //... + //| } + //|} + + // In the future, resource bundles may implement multi-level + // fallback. That is, if a currency is not found in the en_US + // Currencies data, then the en Currencies data will be searched. + // Currently, if a Currencies datum exists in en_US and en, the + // en_US entry hides that in en. + + // We want multi-level fallback for this resource, so we implement + // it manually. + + // Use a separate UErrorCode here that does not propagate out of + // this function. + UErrorCode ec2 = U_ZERO_ERROR; + + char loc[ULOC_FULLNAME_CAPACITY]; + uloc_getName(locale, loc, sizeof(loc), &ec2); + if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) { + ec = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + int32_t start = pos.getIndex(); + const UChar* s = NULL; + + const char* iso = NULL; + int32_t max = 0; + + // Multi-level resource inheritance fallback loop + for (;;) { + ec2 = U_ZERO_ERROR; + UResourceBundle* rb = ures_open(NULL, loc, &ec2); + UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, NULL, &ec2); + int32_t n = ures_getSize(curr); + for (int32_t i=0; i<n; ++i) { + UResourceBundle* names = ures_getByIndex(curr, i, NULL, &ec2); + int32_t len; + s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2); + UBool isChoice = FALSE; + if (len > 0 && s[0] == CHOICE_FORMAT_MARK) { + ++s; + --len; + if (len > 0 && s[0] != CHOICE_FORMAT_MARK) { + isChoice = TRUE; + } + } + if (isChoice) { + Formattable temp; + ChoiceFormat fmt(s, ec2); + fmt.parse(text, temp, pos); + len = pos.getIndex() - start; + pos.setIndex(start); + } else if (len > max && + text.compare(pos.getIndex(), len, s) != 0) { + len = 0; + } + if (len > max) { + iso = ures_getKey(names); + max = len; + } + ures_close(names); + } + ures_close(curr); + ures_close(rb); + + // Try to fallback. If that fails (because we are already at + // root) then exit. + if (!fallback(loc)) { + break; + } + } + + if (iso != NULL) { + u_charsToUChars(iso, result, 4); + } + + // If display name parse fails or if it matches fewer than 3 + // characters, try to parse 3-letter ISO. Do this after the + // display name processing so 3-letter display names are + // preferred. Consider /[A-Z]{3}/ to be valid ISO, and parse + // it manually--UnicodeSet/regex are too slow and heavy. + if (max < 3 && (text.length() - start) >= 3) { + UBool valid = TRUE; + for (int32_t k=0; k<3; ++k) { + UChar ch = text.charAt(start + k); // 16-bit ok + if (ch < 0x41/*'A'*/ || ch > 0x5A/*'Z'*/) { + valid = FALSE; + break; + } + } + if (valid) { + text.extract(start, 3, result); + result[3] = 0; + max = 3; + } + } + + pos.setIndex(start + max); +} + +/** + * Internal method. Given a currency ISO code and a locale, return + * the "static" currency name. This is usually the same as the + * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the + * format is applied to the number 2.0 (to yield the more common + * plural) to return a static name. + * + * This is used for backward compatibility with old currency logic in + * DecimalFormat and DecimalFormatSymbols. + */ +U_CAPI void +uprv_getStaticCurrencyName(const UChar* iso, const char* loc, + U_NAMESPACE_QUALIFIER UnicodeString& result, UErrorCode& ec) +{ + U_NAMESPACE_USE + + UBool isChoiceFormat; + int32_t len; + const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME, + &isChoiceFormat, &len, &ec); + if (U_SUCCESS(ec)) { + // If this is a ChoiceFormat currency, then format an + // arbitrary value; pick something != 1; more common. + result.truncate(0); + if (isChoiceFormat) { + ChoiceFormat f(currname, ec); + if (U_SUCCESS(ec)) { + f.format(2.0, result); + } else { + result = iso; + } + } else { + result = currname; + } + } +} + +U_CAPI int32_t U_EXPORT2 +ucurr_getDefaultFractionDigits(const UChar* currency, UErrorCode* ec) { + return (_findMetaData(currency, *ec))[0]; +} + +U_CAPI double U_EXPORT2 +ucurr_getRoundingIncrement(const UChar* currency, UErrorCode* ec) { + const int32_t *data = _findMetaData(currency, *ec); + + // If the meta data is invalid, return 0.0. + if (data[0] < 0 || data[0] > MAX_POW10) { + if (U_SUCCESS(*ec)) { + *ec = U_INVALID_FORMAT_ERROR; + } + return 0.0; + } + + // If there is no rounding, return 0.0 to indicate no rounding. A + // rounding value (data[1]) of 0 or 1 indicates no rounding. + if (data[1] < 2) { + return 0.0; + } + + // Return data[1] / 10^(data[0]). The only actual rounding data, + // as of this writing, is CHF { 2, 5 }. + return double(data[1]) / POW10[data[0]]; +} + +U_CDECL_BEGIN + +typedef struct UCurrencyContext { + uint32_t currType; /* UCurrCurrencyType */ + uint32_t listIdx; +} UCurrencyContext; + +/* +Please keep this list in alphabetical order. +You can look at the CLDR supplemental data or ISO-4217 for the meaning of some +of these items. +ISO-4217: http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html +*/ +static const struct CurrencyList { + const char *currency; + uint32_t currType; +} gCurrencyList[] = { + {"ADP", UCURR_COMMON|UCURR_DEPRECATED}, + {"AED", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"AFA", UCURR_COMMON|UCURR_DEPRECATED}, + {"AFN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ALL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"AMD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ANG", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"AOA", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"AOK", UCURR_COMMON|UCURR_DEPRECATED}, + {"AON", UCURR_COMMON|UCURR_DEPRECATED}, + {"AOR", UCURR_COMMON|UCURR_DEPRECATED}, + {"ARA", UCURR_COMMON|UCURR_DEPRECATED}, + {"ARP", UCURR_COMMON|UCURR_DEPRECATED}, + {"ARS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ATS", UCURR_COMMON|UCURR_DEPRECATED}, + {"AUD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"AWG", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"AZM", UCURR_COMMON|UCURR_DEPRECATED}, + {"AZN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BAD", UCURR_COMMON|UCURR_DEPRECATED}, + {"BAM", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BBD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BDT", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BEC", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"BEF", UCURR_COMMON|UCURR_DEPRECATED}, + {"BEL", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"BGL", UCURR_COMMON|UCURR_DEPRECATED}, + {"BGN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BHD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BIF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BMD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BND", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BOB", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BOP", UCURR_COMMON|UCURR_DEPRECATED}, + {"BOV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"BRB", UCURR_COMMON|UCURR_DEPRECATED}, + {"BRC", UCURR_COMMON|UCURR_DEPRECATED}, + {"BRE", UCURR_COMMON|UCURR_DEPRECATED}, + {"BRL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BRN", UCURR_COMMON|UCURR_DEPRECATED}, + {"BRR", UCURR_COMMON|UCURR_DEPRECATED}, + {"BSD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BTN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BUK", UCURR_COMMON|UCURR_DEPRECATED}, + {"BWP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BYB", UCURR_COMMON|UCURR_DEPRECATED}, + {"BYR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BZD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CAD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CDF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CHE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"CHF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CHW", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"CLF", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"CLP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CNX", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"CNY", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"COP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"COU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"CRC", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CSD", UCURR_COMMON|UCURR_DEPRECATED}, + {"CSK", UCURR_COMMON|UCURR_DEPRECATED}, + {"CUP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CVE", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CYP", UCURR_COMMON|UCURR_DEPRECATED}, + {"CZK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"DDM", UCURR_COMMON|UCURR_DEPRECATED}, + {"DEM", UCURR_COMMON|UCURR_DEPRECATED}, + {"DJF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"DKK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"DOP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"DZD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ECS", UCURR_COMMON|UCURR_DEPRECATED}, + {"ECV", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"EEK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"EGP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"EQE", UCURR_COMMON|UCURR_DEPRECATED}, + {"ERN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ESA", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"ESB", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"ESP", UCURR_COMMON|UCURR_DEPRECATED}, + {"ETB", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"EUR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"FIM", UCURR_COMMON|UCURR_DEPRECATED}, + {"FJD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"FKP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"FRF", UCURR_COMMON|UCURR_DEPRECATED}, + {"GBP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GEK", UCURR_COMMON|UCURR_DEPRECATED}, + {"GEL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GHC", UCURR_COMMON|UCURR_DEPRECATED}, + {"GHS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GIP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GMD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GNF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GNS", UCURR_COMMON|UCURR_DEPRECATED}, + {"GQE", UCURR_COMMON|UCURR_DEPRECATED}, + {"GRD", UCURR_COMMON|UCURR_DEPRECATED}, + {"GTQ", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GWE", UCURR_COMMON|UCURR_DEPRECATED}, + {"GWP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GYD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"HKD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"HNL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"HRD", UCURR_COMMON|UCURR_DEPRECATED}, + {"HRK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"HTG", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"HUF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"IDR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"IEP", UCURR_COMMON|UCURR_DEPRECATED}, + {"ILP", UCURR_COMMON|UCURR_DEPRECATED}, + {"ILS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"INR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"IQD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"IRR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ISK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ITL", UCURR_COMMON|UCURR_DEPRECATED}, + {"JMD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"JOD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"JPY", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KES", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KGS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KHR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KMF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KPW", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KRW", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KWD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KYD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"KZT", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LAK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LBP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LKR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LRD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LSL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LSM", UCURR_COMMON|UCURR_DEPRECATED}, + {"LTL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LTT", UCURR_COMMON|UCURR_DEPRECATED}, + {"LUC", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"LUF", UCURR_COMMON|UCURR_DEPRECATED}, + {"LUL", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"LVL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LVR", UCURR_COMMON|UCURR_DEPRECATED}, + {"LYD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MAD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MAF", UCURR_COMMON|UCURR_DEPRECATED}, + {"MDL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MGA", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MGF", UCURR_COMMON|UCURR_DEPRECATED}, + {"MKD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MLF", UCURR_COMMON|UCURR_DEPRECATED}, + {"MMK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MNT", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MOP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MRO", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MTL", UCURR_COMMON|UCURR_DEPRECATED}, + {"MTP", UCURR_COMMON|UCURR_DEPRECATED}, + {"MUR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MVR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MWK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MXN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MXP", UCURR_COMMON|UCURR_DEPRECATED}, + {"MXV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"MYR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MZE", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MZM", UCURR_COMMON|UCURR_DEPRECATED}, + {"MZN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"NAD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"NGN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"NIC", UCURR_COMMON|UCURR_DEPRECATED}, + {"NIO", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"NLG", UCURR_COMMON|UCURR_DEPRECATED}, + {"NOK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"NPR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"NZD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"OMR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PAB", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PEI", UCURR_COMMON|UCURR_DEPRECATED}, + {"PEN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PES", UCURR_COMMON|UCURR_DEPRECATED}, + {"PGK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PHP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PKR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PLN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"PLZ", UCURR_COMMON|UCURR_DEPRECATED}, + {"PTE", UCURR_COMMON|UCURR_DEPRECATED}, + {"PYG", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"QAR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"RHD", UCURR_COMMON|UCURR_DEPRECATED}, + {"ROL", UCURR_COMMON|UCURR_DEPRECATED}, + {"RON", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"RSD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"RUB", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"RUR", UCURR_COMMON|UCURR_DEPRECATED}, + {"RWF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SAR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SBD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SCR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SDD", UCURR_COMMON|UCURR_DEPRECATED}, + {"SDG", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SDP", UCURR_COMMON|UCURR_DEPRECATED}, + {"SEK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SGD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SHP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SIT", UCURR_COMMON|UCURR_DEPRECATED}, + {"SKK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SLL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SOS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SRD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SRG", UCURR_COMMON|UCURR_DEPRECATED}, + {"STD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SUR", UCURR_COMMON|UCURR_DEPRECATED}, + {"SVC", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SYP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SZL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"THB", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TJR", UCURR_COMMON|UCURR_DEPRECATED}, + {"TJS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TMM", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TND", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TOP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TPE", UCURR_COMMON|UCURR_DEPRECATED}, + {"TRL", UCURR_COMMON|UCURR_DEPRECATED}, + {"TRY", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TTD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TWD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"TZS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"UAH", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"UAK", UCURR_COMMON|UCURR_DEPRECATED}, + {"UGS", UCURR_COMMON|UCURR_DEPRECATED}, + {"UGX", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"USD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"USN", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"USS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"UYP", UCURR_COMMON|UCURR_DEPRECATED}, + {"UYI", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"UYU", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"UZS", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"VEB", UCURR_COMMON|UCURR_DEPRECATED}, + {"VEF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"VND", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"VUV", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"WST", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"XAF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"XAG", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XAU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XBA", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XBB", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XBC", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XBD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XCD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"XDR", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XEU", UCURR_UNCOMMON|UCURR_DEPRECATED}, + {"XFO", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XFU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XOF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"XPD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XPF", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"XPT", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XRE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XTS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XXX", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"YDD", UCURR_COMMON|UCURR_DEPRECATED}, + {"YER", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"YUD", UCURR_COMMON|UCURR_DEPRECATED}, + {"YUM", UCURR_COMMON|UCURR_DEPRECATED}, + {"YUN", UCURR_COMMON|UCURR_DEPRECATED}, + {"ZAL", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"ZAR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ZMK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"ZRN", UCURR_COMMON|UCURR_DEPRECATED}, + {"ZRZ", UCURR_COMMON|UCURR_DEPRECATED}, + {"ZWD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + { NULL, 0 } // Leave here to denote the end of the list. +}; + +#define UCURR_MATCHES_BITMASK(variable, typeToMatch) \ + ((typeToMatch) == UCURR_ALL || ((variable) & (typeToMatch)) == (typeToMatch)) + +static int32_t U_CALLCONV +ucurr_countCurrencyList(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) { + UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context); + uint32_t currType = myContext->currType; + int32_t count = 0; + + /* Count the number of items matching the type we are looking for. */ + for (int32_t idx = 0; gCurrencyList[idx].currency != NULL; idx++) { + if (UCURR_MATCHES_BITMASK(gCurrencyList[idx].currType, currType)) { + count++; + } + } + return count; +} + +static const char* U_CALLCONV +ucurr_nextCurrencyList(UEnumeration *enumerator, + int32_t* resultLength, + UErrorCode * /*pErrorCode*/) +{ + UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context); + + /* Find the next in the list that matches the type we are looking for. */ + while (myContext->listIdx < (sizeof(gCurrencyList)/sizeof(gCurrencyList[0]))-1) { + const struct CurrencyList *currItem = &gCurrencyList[myContext->listIdx++]; + if (UCURR_MATCHES_BITMASK(currItem->currType, myContext->currType)) + { + if (resultLength) { + *resultLength = 3; /* Currency codes are only 3 chars long */ + } + return currItem->currency; + } + } + /* We enumerated too far. */ + if (resultLength) { + *resultLength = 0; + } + return NULL; +} + +static void U_CALLCONV +ucurr_resetCurrencyList(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) { + ((UCurrencyContext *)(enumerator->context))->listIdx = 0; +} + +static void U_CALLCONV +ucurr_closeCurrencyList(UEnumeration *enumerator) { + uprv_free(enumerator->context); + uprv_free(enumerator); +} + +static const UEnumeration gEnumCurrencyList = { + NULL, + NULL, + ucurr_closeCurrencyList, + ucurr_countCurrencyList, + uenum_unextDefault, + ucurr_nextCurrencyList, + ucurr_resetCurrencyList +}; +U_CDECL_END + +U_CAPI UEnumeration * U_EXPORT2 +ucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode) { + UEnumeration *myEnum = NULL; + UCurrencyContext *myContext; + + myEnum = (UEnumeration*)uprv_malloc(sizeof(UEnumeration)); + if (myEnum == NULL) { + *pErrorCode = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + uprv_memcpy(myEnum, &gEnumCurrencyList, sizeof(UEnumeration)); + myContext = (UCurrencyContext*)uprv_malloc(sizeof(UCurrencyContext)); + if (myContext == NULL) { + *pErrorCode = U_MEMORY_ALLOCATION_ERROR; + uprv_free(myEnum); + return NULL; + } + myContext->currType = currType; + myContext->listIdx = 0; + myEnum->context = myContext; + return myEnum; +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +//eof |