]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/ucurr.cpp
ICU-400.37.tar.gz
[apple/icu.git] / icuSources / i18n / ucurr.cpp
index 29332db154e9224b6b4fb20115667d2230f6ecbe..7705a5bd8d209e60d1080368c7cd46021b34404f 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-* Copyright (c) 2002-2004, International Business Machines
+* Copyright (c) 2002-2008, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 */
 #include "cmemory.h"
 #include "cstring.h"
 #include "uassert.h"
-#include "mutex.h"
+#include "umutex.h"
 #include "ucln_in.h"
+#include "uenumimp.h"
+#include "uresimp.h"
 
 //------------------------------------------------------------
 // Constants
@@ -43,7 +45,7 @@ static const int32_t MAX_POW10 = (sizeof(POW10)/sizeof(POW10[0])) - 1;
 // Resource tags
 //
 
-static const char CURRENCY_DATA[] = "CurrencyData";
+static const char CURRENCY_DATA[] = "supplementalData";
 // Tag for meta-data, in root.
 static const char CURRENCY_META[] = "CurrencyMeta";
 
@@ -60,10 +62,11 @@ static const char VAR_PRE_EURO[] = "PREEURO";
 static const char VAR_EURO[] = "EURO";
 
 // Variant delimiter
-static const char VAR_DELIM[] = "_";
+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";
+//static const char VAR_DELIM_EURO[] = "_EURO";
 
 #define VARIANT_IS_EMPTY    0
 #define VARIANT_IS_EURO     0x1
@@ -78,6 +81,8 @@ static const char CURRENCIES[] = "Currencies";
 // the first mark is deleted.
 static const UChar CHOICE_FORMAT_MARK = 0x003D; // Equals sign
 
+static const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0};
+
 //------------------------------------------------------------
 // Code
 
@@ -173,7 +178,7 @@ idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCod
                    | ((0 == uprv_strcmp(variant, VAR_PRE_EURO)) << 1);
         if (variantType)
         {
-            uprv_strcat(countryAndVariant, VAR_DELIM);
+            uprv_strcat(countryAndVariant, VAR_DELIM_STR);
             uprv_strcat(countryAndVariant, variant);
         }
     }
@@ -198,7 +203,7 @@ struct CReg;
 static UMTX gCRegLock = 0;
 static CReg* gCRegHead = 0;
 
-struct CReg : public UMemory {
+struct CReg : public U_NAMESPACE_QUALIFIER UMemory {
     CReg *next;
     UChar iso[ISO_COUNTRY_CODE_LENGTH+1];
     char  id[ULOC_FULLNAME_CAPACITY];
@@ -222,13 +227,14 @@ struct CReg : public UMemory {
             CReg* n = new CReg(_iso, _id);
             if (n) {
                 umtx_init(&gCRegLock);
-                Mutex mutex(&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;
@@ -237,41 +243,42 @@ struct CReg : public UMemory {
     }
 
     static UBool unreg(UCurrRegistryKey key) {
+        UBool found = FALSE;
         umtx_init(&gCRegLock);
-        Mutex mutex(&gCRegLock);
-        if (gCRegHead == key) {
-            gCRegHead = gCRegHead->next;
-            delete (CReg*)key;
-            return TRUE;
-        }
+        umtx_lock(&gCRegLock);
 
-        CReg* p = gCRegHead;
-        while (p) {
-            if (p->next == key) {
-                p->next = ((CReg*)key)->next;
+        CReg** p = &gCRegHead;
+        while (*p) {
+            if (*p == key) {
+                *p = ((CReg*)key)->next;
                 delete (CReg*)key;
-                return TRUE;
+                found = TRUE;
+                break;
             }
-            p = p->next;
+            p = &((*p)->next);
         }
 
-        return FALSE;
+        umtx_unlock(&gCRegLock);
+        return found;
     }
 
     static const UChar* get(const char* id) {
+        const UChar* result = NULL;
         umtx_init(&gCRegLock);
-        Mutex mutex(&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) {
-                return p->iso;
+                result = p->iso;
+                break;
             }
             p = p->next;
         }
-        return NULL;
+        umtx_unlock(&gCRegLock);
+        return result;
     }
 
     /* This doesn't need to be thread safe. It's for u_cleanup only. */
@@ -358,25 +365,44 @@ ucurr_forLocale(const char* locale,
                     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);
-                s = ures_getStringByKey(cm, id, &resLen, &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 ((s == NULL || U_FAILURE(localStatus)) && variantType != VARIANT_IS_EMPTY
-                    && (id[0] != 0))
+                if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
                 {
                     // We don't know about it.  Check to see if we support the variant.
-                    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);
-                    }
+                    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.
@@ -387,7 +413,6 @@ ucurr_forLocale(const char* locale,
                         u_strcpy(buff, s);
                     }
                 }
-                ures_close(cm);
             }
             return u_terminateUChars(buff, buffCapacity, resLen, ec);
         } else {
@@ -476,28 +501,23 @@ ucurr_getName(const UChar* currency,
     myUCharsToChars(buf, currency);
 
     const UChar* s = NULL;
+    ec2 = U_ZERO_ERROR;
+    UResourceBundle* rb = ures_open(NULL, loc, &ec2);
 
-    // Multi-level resource inheritance fallback loop
-    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);
+    rb = ures_getByKey(rb, CURRENCIES, rb, &ec2);
 
-        // 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) || !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;
+    // 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;
         }
     }
 
@@ -524,14 +544,14 @@ ucurr_getName(const UChar* currency,
     return currency;
 }
 
-U_NAMESPACE_BEGIN
-
-void
+U_CFUNC void
 uprv_parseCurrency(const char* locale,
-                   const UnicodeString& text,
-                   ParsePosition& pos,
+                   const U_NAMESPACE_QUALIFIER UnicodeString& text,
+                   U_NAMESPACE_QUALIFIER ParsePosition& pos,
                    UChar* result,
-                   UErrorCode& ec) {
+                   UErrorCode& ec)
+{
+    U_NAMESPACE_USE
 
     // TODO: There is a slight problem with the pseudo-multi-level
     // fallback implemented here.  More-specific locales don't
@@ -654,8 +674,6 @@ uprv_parseCurrency(const char* locale,
     pos.setIndex(start + max);
 }
 
-U_NAMESPACE_END
-
 /**
  * Internal method.  Given a currency ISO code and a locale, return
  * the "static" currency name.  This is usually the same as the
@@ -666,10 +684,12 @@ U_NAMESPACE_END
  * This is used for backward compatibility with old currency logic in
  * DecimalFormat and DecimalFormatSymbols.
  */
-U_CAPI void
+U_CFUNC void
 uprv_getStaticCurrencyName(const UChar* iso, const char* loc,
-                           UnicodeString& result, UErrorCode& ec)
+                           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,
@@ -719,6 +739,653 @@ ucurr_getRoundingIncrement(const UChar* currency, UErrorCode* ec) {
     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},
+    {"ALK", UCURR_COMMON|UCURR_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},
+    {"BGM", 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;
+}
+
+U_CAPI int32_t U_EXPORT2
+ucurr_countCurrencies(const char* locale, 
+                 UDate date, 
+                 UErrorCode* ec)
+{
+       int32_t currCount = 0;
+    int32_t resLen = 0;
+    const UChar* s = NULL;
+
+    if (ec != NULL && U_SUCCESS(*ec)) 
+       {
+               // local variables
+        UErrorCode localStatus = U_ZERO_ERROR;
+        char id[ULOC_FULLNAME_CAPACITY];
+        resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
+
+               // get country or country_variant in `id'
+               uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
+               if (U_FAILURE(*ec)) 
+               {
+                       return 0;
+               }
+
+               // 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);
+
+               // Using the id derived from the local, get the currency data
+               UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
+
+               // process each currency to see which one is valid for the given date
+               if (U_SUCCESS(localStatus))
+               {
+                       for (int32_t i=0; i<ures_getSize(countryArray); i++)
+                       {
+                               // get the currency resource
+                               UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, NULL, &localStatus);
+                               s = ures_getStringByKey(currencyRes, "id", &resLen, &localStatus);
+
+                               // get the from date
+                               int32_t fromLength = 0;
+                               UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
+                               const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
+
+                               int64_t currDate64 = (int64_t)fromArray[0] << 32;                       
+                               currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
+                               UDate fromDate = (UDate)currDate64;
+                                       
+                               if (ures_getSize(currencyRes) > 2)
+                               {
+                                       int32_t toLength = 0;
+                                       UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
+                                       const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
+                                                       
+                                       currDate64 = (int64_t)toArray[0] << 32;                 
+                                       currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
+                                       UDate toDate = (UDate)currDate64;                       
+
+                                       if ((fromDate <= date) && (date < toDate))
+                                       {
+                                               currCount++;
+                                       }
+
+                                       ures_close(toRes);
+                               }
+                               else
+                               {
+                                       if (fromDate <= date)
+                                       {
+                                               currCount++;
+                                       }
+                               }
+
+                               // close open resources
+                               ures_close(currencyRes);
+                               ures_close(fromRes);
+
+                       } // end For loop
+               } // end if (U_SUCCESS(localStatus))
+
+               ures_close(countryArray);
+
+               // Check for errors
+        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)) 
+               {
+                       // no errors
+                       return currCount;
+               }
+
+    }
+
+       // If we got here, either error code is invalid or
+       // some argument passed is no good.
+    return 0;
+}
+
+U_CAPI int32_t U_EXPORT2 
+ucurr_forLocaleAndDate(const char* locale, 
+                UDate date, 
+                int32_t index,
+                UChar* buff, 
+                int32_t buffCapacity, 
+                UErrorCode* ec)
+{
+    int32_t resLen = 0;
+       int32_t currIndex = 0;
+    const UChar* s = NULL;
+
+    if (ec != NULL && U_SUCCESS(*ec)) 
+       {
+               // check the arguments passed
+        if ((buff && buffCapacity) || !buffCapacity ) 
+               {
+                       // local variables
+            UErrorCode localStatus = U_ZERO_ERROR;
+            char id[ULOC_FULLNAME_CAPACITY];
+            resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
+
+                       // get country or country_variant in `id'
+                       uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
+                       if (U_FAILURE(*ec)) 
+                       {
+                               return 0;
+                       }
+
+                       // 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);
+
+                       // Using the id derived from the local, get the currency data
+                       UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
+
+                       // process each currency to see which one is valid for the given date
+                       bool matchFound = false;
+                       if (U_SUCCESS(localStatus))
+                       {
+                if ((index <= 0) || (index > ures_getSize(countryArray)))
+                               {
+                    // requested index is out of bounds
+                    ures_close(countryArray);
+                                       return 0;
+                               }
+
+                               for (int32_t i=0; i<ures_getSize(countryArray); i++)
+                               {
+                                       // get the currency resource
+                                       UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, NULL, &localStatus);
+                                       s = ures_getStringByKey(currencyRes, "id", &resLen, &localStatus);
+
+                                       // get the from date
+                                       int32_t fromLength = 0;
+                                       UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
+                                       const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
+
+                                       int64_t currDate64 = (int64_t)fromArray[0] << 32;                       
+                                       currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
+                                       UDate fromDate = (UDate)currDate64;
+                                       
+                                       if (ures_getSize(currencyRes) > 2)
+                                       {
+                                               int32_t toLength = 0;
+                                               UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
+                                               const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
+                                                       
+                                               currDate64 = (int64_t)toArray[0] << 32;                 
+                                               currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
+                                               UDate toDate = (UDate)currDate64;                       
+
+                                               if ((fromDate <= date) && (date < toDate))
+                                               {
+                                                       currIndex++;
+                                                       if (currIndex == index)
+                                                       {
+                                                           matchFound = true;
+                                                       }
+                                               }
+
+                                               ures_close(toRes);
+                                       }
+                                       else
+                                       {
+                                               if (fromDate <= date)
+                                               {
+                                                       currIndex++;
+                                                       if (currIndex == index)
+                                                       {
+                                                           matchFound = true;
+                                                       }
+                                               }
+                                       }
+
+                                       // close open resources
+                                       ures_close(currencyRes);
+                                       ures_close(fromRes);
+                                       
+                                       // check for loop exit
+                                       if (matchFound)
+                                       {
+                                               break;
+                                       }
+
+                               } // end For loop
+                       }
+
+                       ures_close(countryArray);
+
+                       // Check for errors
+            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)) 
+                       {
+                               // no errors
+                               if((buffCapacity > resLen) && matchFound)
+                               {
+                                       // write out the currency value
+                                       u_strcpy(buff, s);
+                               }
+                               else
+                               {
+                                       return 0;
+                               }
+                       }
+
+                       // return null terminated currency string
+            return u_terminateUChars(buff, buffCapacity, resLen, ec);
+               }
+        else 
+               {
+                       // illegal argument encountered
+            *ec = U_ILLEGAL_ARGUMENT_ERROR;
+        }
+
+    }
+
+       // If we got here, either error code is invalid or
+       // some argument passed is no good.
+    return resLen;
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 //eof