#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 "mutex.h"
#include "ucln_in.h"
#include "uenumimp.h"
static const int32_t LAST_RESORT_DATA[] = { 2, 0 };
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
static const char CURRENCY_DATA[] = "CurrencyData";
static const char CURRENCY_META[] = "CurrencyMeta";
static const char CURRENCY_MAP[] = "CurrencyMap";
static const char DEFAULT_META[] = "DEFAULT";
static const char VAR_PRE_EURO[] = "PREEURO";
static const char VAR_EURO[] = "EURO";
static const char VAR_DELIM[] = "_";
static const char VAR_DELIM_EURO[] = "_EURO";
#define VARIANT_IS_EMPTY 0
#define VARIANT_IS_EURO 0x1
#define VARIANT_IS_PREEURO 0x2
static const char CURRENCIES[] = "Currencies";
static const UChar CHOICE_FORMAT_MARK = 0x003D;
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;
}
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;
}
UResourceBundle* currencyData = ures_openDirect(NULL, CURRENCY_DATA, &ec);
UResourceBundle* currencyMeta = ures_getByKey(currencyData, CURRENCY_META, currencyData, &ec);
if (U_FAILURE(ec)) {
ures_close(currencyMeta);
return LAST_RESORT_DATA;
}
char buf[ISO_COUNTRY_CODE_LENGTH+1];
UErrorCode ec2 = U_ZERO_ERROR; 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);
return LAST_RESORT_DATA;
}
}
int32_t len;
const int32_t *data = ures_getIntVector(rb, &len, &ec);
if (U_FAILURE(ec) || len != 2) {
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;
}
static uint32_t
idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec)
{
uint32_t variantType = 0;
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);
uprv_strcat(countryAndVariant, variant);
}
}
return variantType;
}
#if !UCONFIG_NO_SERVICE
U_CDECL_BEGIN
static UBool U_CALLCONV currency_cleanup(void);
U_CDECL_END
struct CReg;
static UMTX gCRegLock = 0;
static CReg* gCRegHead = 0;
struct CReg : public 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);
Mutex mutex(&gCRegLock);
if (!gCRegHead) {
ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
}
n->next = gCRegHead;
gCRegHead = n;
return n;
}
*status = U_MEMORY_ALLOCATION_ERROR;
}
return 0;
}
static UBool unreg(UCurrRegistryKey key) {
umtx_init(&gCRegLock);
Mutex mutex(&gCRegLock);
if (gCRegHead == key) {
gCRegHead = gCRegHead->next;
delete (CReg*)key;
return TRUE;
}
CReg* p = gCRegHead;
while (p) {
if (p->next == key) {
p->next = ((CReg*)key)->next;
delete (CReg*)key;
return TRUE;
}
p = p->next;
}
return FALSE;
}
static const UChar* get(const char* id) {
umtx_init(&gCRegLock);
Mutex mutex(&gCRegLock);
CReg* p = gCRegHead;
ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
while (p) {
if (uprv_strcmp(id, p->id) == 0) {
return p->iso;
}
p = p->next;
}
return NULL;
}
static void cleanup(void) {
while (gCRegHead) {
CReg* n = gCRegHead;
gCRegHead = gCRegHead->next;
delete n;
}
umtx_destroy(&gCRegLock);
}
};
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
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))) {
if(buffCapacity > resLen) {
u_charsToUChars(id, buff, resLen);
}
} else {
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
UResourceBundle *rb = ures_openDirect(NULL, CURRENCY_DATA, &localStatus);
UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
s = ures_getStringByKey(cm, id, &resLen, &localStatus);
if ((s == NULL || U_FAILURE(localStatus)) && variantType != VARIANT_IS_EMPTY
&& (id[0] != 0))
{
if (variantType & VARIANT_IS_EURO) {
s = ures_getStringByKey(cm, VAR_DELIM_EURO, &resLen, ec);
}
else {
uloc_getParent(locale, id, sizeof(id), ec);
*ec = U_USING_FALLBACK_WARNING;
ures_close(cm);
return ucurr_forLocale(id, buff, buffCapacity, ec);
}
}
else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
*ec = localStatus;
}
if (U_SUCCESS(*ec)) {
if(buffCapacity > resLen) {
u_strcpy(buff, s);
}
}
ures_close(cm);
}
return u_terminateUChars(buff, buffCapacity, resLen, ec);
} else {
*ec = U_ILLEGAL_ARGUMENT_ERROR;
}
}
return resLen;
}
static UBool fallback(char *loc) {
if (!*loc) {
return FALSE;
}
UErrorCode status = U_ZERO_ERROR;
uloc_getParent(loc, loc, (int32_t)uprv_strlen(loc), &status);
return TRUE;
}
U_CAPI const UChar* U_EXPORT2
ucurr_getName(const UChar* currency,
const char* locale,
UCurrNameStyle nameStyle,
UBool* isChoiceFormat, int32_t* len, UErrorCode* ec) {
if (U_FAILURE(*ec)) {
return 0;
}
int32_t choice = (int32_t) nameStyle;
if (choice < 0 || choice > 1) {
*ec = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
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;
for (;;) {
ec2 = U_ZERO_ERROR;
UResourceBundle* rb = ures_open(NULL, loc, &ec2);
rb = ures_getByKey(rb, CURRENCIES, rb, &ec2);
rb = ures_getByKey(rb, buf, rb, &ec2);
s = ures_getStringByIndex(rb, choice, len, &ec2);
ures_close(rb);
if (U_SUCCESS(ec2) || !fallback(loc)) {
if (ec2 == U_USING_DEFAULT_WARNING
|| (ec2 == U_USING_FALLBACK_WARNING && *ec != U_USING_DEFAULT_WARNING)) {
*ec = ec2;
}
break;
} else if (strlen(loc) == 0) {
*ec = U_USING_DEFAULT_WARNING;
} else if (*ec != U_USING_DEFAULT_WARNING) {
*ec = U_USING_FALLBACK_WARNING;
}
}
*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; return s;
}
*len = u_strlen(currency); *ec = U_USING_DEFAULT_WARNING;
return currency;
}
U_NAMESPACE_BEGIN
void
uprv_parseCurrency(const char* locale,
const UnicodeString& text,
ParsePosition& pos,
UChar* result,
UErrorCode& ec) {
if (U_FAILURE(ec)) {
return;
}
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;
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);
if (!fallback(loc)) {
break;
}
}
if (iso != NULL) {
u_charsToUChars(iso, result, 4);
}
if (max < 3 && (text.length() - start) >= 3) {
UBool valid = TRUE;
for (int32_t k=0; k<3; ++k) {
UChar ch = text.charAt(start + k); if (ch < 0x41 || ch > 0x5A) {
valid = FALSE;
break;
}
}
if (valid) {
text.extract(start, 3, result);
result[3] = 0;
max = 3;
}
}
pos.setIndex(start + max);
}
U_NAMESPACE_END
U_CAPI void
uprv_getStaticCurrencyName(const UChar* iso, const char* loc,
UnicodeString& result, UErrorCode& ec)
{
UBool isChoiceFormat;
int32_t len;
const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME,
&isChoiceFormat, &len, &ec);
if (U_SUCCESS(ec)) {
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 (data[0] < 0 || data[0] > MAX_POW10) {
if (U_SUCCESS(*ec)) {
*ec = U_INVALID_FORMAT_ERROR;
}
return 0.0;
}
if (data[1] < 2) {
return 0.0;
}
return double(data[1]) / POW10[data[0]];
}
U_CDECL_BEGIN
typedef struct UCurrencyContext {
uint32_t currType;
uint32_t listIdx;
} UCurrencyContext;
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_NON_DEPRECATED},
{"CSK", UCURR_COMMON|UCURR_DEPRECATED},
{"CUP", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"CVE", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"CYP", UCURR_COMMON|UCURR_NON_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_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_NON_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},
{"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_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},
{"UYU", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"UZS", UCURR_COMMON|UCURR_NON_DEPRECATED},
{"VEB", 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 } };
#define UCURR_MATCHES_BITMASK(variable, typeToMatch) \
((typeToMatch) == UCURR_ALL || ((variable) & (typeToMatch)) == (typeToMatch))
static int32_t U_CALLCONV
ucurr_countCurrencyList(UEnumeration *enumerator, UErrorCode * ) {
UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context);
uint32_t currType = myContext->currType;
int32_t count = 0;
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 * )
{
UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context);
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;
}
return currItem->currency;
}
}
if (resultLength) {
*resultLength = 0;
}
return NULL;
}
static void U_CALLCONV
ucurr_resetCurrencyList(UEnumeration *enumerator, UErrorCode * ) {
((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