ucurr.cpp revision 50294ead5e5d23f5bbfed76e00e6b510bd41eee1
1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (c) 2002-2010, International Business Machines
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Corporation and others.  All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ucurr.h"
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/locid.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ures.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/choicfmt.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/parsepos.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ustr_imp.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uenumimp.h"
25b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "uhash.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h"
27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "ulist.h"
2850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ureslocs.h"
29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
3050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// #define UCURR_DEBUG 1
31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
32b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "stdio.h"
33b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Constants
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Default currency meta data of last resort.  We try to use the
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// defaults encoded in the meta data resource bundle.  If there is a
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// configuration/build error and these are not available, we use these
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// hard-coded defaults (which should be identical).
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t LAST_RESORT_DATA[] = { 2, 0 };
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// POW10[i] = 10^i, i=0..MAX_POW10
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t POW10[] = { 1, 10, 100, 1000, 10000, 100000,
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 1000000, 10000000, 100000000, 1000000000 };
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t MAX_POW10 = (sizeof(POW10)/sizeof(POW10[0])) - 1;
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ISO_COUNTRY_CODE_LENGTH 3
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Resource tags
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCY_DATA[] = "supplementalData";
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for meta-data, in root.
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCY_META[] = "CurrencyMeta";
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for map from countries to currencies, in root.
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCY_MAP[] = "CurrencyMap";
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for default meta-data, in CURRENCY_META
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DEFAULT_META[] = "DEFAULT";
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant for legacy pre-euro mapping in CurrencyMap
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_PRE_EURO[] = "PREEURO";
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant for legacy euro mapping in CurrencyMap
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_EURO[] = "EURO";
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant delimiter
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_DELIM = '_';
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_DELIM_STR[] = "_";
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant for legacy euro mapping in CurrencyMap
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//static const char VAR_DELIM_EURO[] = "_EURO";
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define VARIANT_IS_EMPTY    0
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define VARIANT_IS_EURO     0x1
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define VARIANT_IS_PREEURO  0x2
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for localized display names (symbols) of currencies
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCIES[] = "Currencies";
85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char CURRENCYPLURALS[] = "CurrencyPlurals";
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Marker character indicating that a display name is a ChoiceFormat
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// pattern.  Strings that start with one mark are ChoiceFormat
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// patterns.  Strings that start with 2 marks are static strings, and
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the first mark is deleted.
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar CHOICE_FORMAT_MARK = 0x003D; // Equals sign
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0};
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Code
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Unfortunately, we have to convert the UChar* currency code to char*
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to use it as a resource key.
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic inline char*
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerumyUCharsToChars(char* resultOfLen4, const UChar* currency) {
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    u_UCharsToChars(currency, resultOfLen4, ISO_COUNTRY_CODE_LENGTH);
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    resultOfLen4[ISO_COUNTRY_CODE_LENGTH] = 0;
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return resultOfLen4;
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Internal function to look up currency data.  Result is an array of
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * two integers.  The first is the fraction digits.  The second is the
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * rounding increment, or 0 if none.  The rounding increment is in
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * units of 10^(-fraction_digits).
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t*
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_findMetaData(const UChar* currency, UErrorCode& ec) {
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (currency == 0 || *currency == 0) {
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ec = U_ILLEGAL_ARGUMENT_ERROR;
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return LAST_RESORT_DATA;
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Get CurrencyMeta resource out of root locale file.  [This may
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move out of the root locale file later; if it does, update this
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // code.]
12850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle* currencyData = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &ec);
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle* currencyMeta = ures_getByKey(currencyData, CURRENCY_META, currencyData, &ec);
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(currencyMeta);
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Config/build error; return hard-coded defaults
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return LAST_RESORT_DATA;
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Look up our currency, or if that's not available, then DEFAULT
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buf[ISO_COUNTRY_CODE_LENGTH+1];
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR; // local error code: soft failure
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle* rb = ures_getByKey(currencyMeta, myUCharsToChars(buf, currency), NULL, &ec2);
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (U_FAILURE(ec2)) {
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(rb);
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rb = ures_getByKey(currencyMeta,DEFAULT_META, NULL, &ec);
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(ec)) {
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(currencyMeta);
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(rb);
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Config/build error; return hard-coded defaults
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return LAST_RESORT_DATA;
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t *data = ures_getIntVector(rb, &len, &ec);
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec) || len != 2) {
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Config/build error; return hard-coded defaults
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ec = U_INVALID_FORMAT_ERROR;
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(currencyMeta);
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(rb);
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return LAST_RESORT_DATA;
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(currencyMeta);
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(rb);
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return data;
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @see VARIANT_IS_EURO
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @see VARIANT_IS_PREEURO
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint32_t
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruidForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec)
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t variantType = 0;
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // !!! this is internal only, assumes buffer is not null and capacity is sufficient
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Extract the country name and variant name.  We only
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // recognize two variant names, EURO and PREEURO.
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char variant[ULOC_FULLNAME_CAPACITY];
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getCountry(locale, countryAndVariant, capacity, ec);
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getVariant(locale, variant, sizeof(variant), ec);
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (variant[0] != 0) {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        variantType = (0 == uprv_strcmp(variant, VAR_EURO))
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   | ((0 == uprv_strcmp(variant, VAR_PRE_EURO)) << 1);
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (variantType)
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(countryAndVariant, VAR_DELIM_STR);
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(countryAndVariant, variant);
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return variantType;
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------------
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Registration
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// don't use ICUService since we don't need fallback
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV currency_cleanup(void);
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct CReg;
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UMTX gCRegLock = 0;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic CReg* gCRegHead = 0;
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct CReg : public U_NAMESPACE_QUALIFIER UMemory {
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CReg *next;
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar iso[ISO_COUNTRY_CODE_LENGTH+1];
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char  id[ULOC_FULLNAME_CAPACITY];
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CReg(const UChar* _iso, const char* _id)
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        : next(0)
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t len = (int32_t)uprv_strlen(_id);
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (len > (int32_t)(sizeof(id)-1)) {
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len = (sizeof(id)-1);
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strncpy(id, _id, len);
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        id[len] = 0;
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memcpy(iso, _iso, ISO_COUNTRY_CODE_LENGTH * sizeof(const UChar));
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        iso[ISO_COUNTRY_CODE_LENGTH] = 0;
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UCurrRegistryKey reg(const UChar* _iso, const char* _id, UErrorCode* status)
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (status && U_SUCCESS(*status) && _iso && _id) {
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            CReg* n = new CReg(_iso, _id);
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (n) {
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                umtx_lock(&gCRegLock);
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!gCRegHead) {
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* register for the first time */
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                n->next = gCRegHead;
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                gCRegHead = n;
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                umtx_unlock(&gCRegLock);
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return n;
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UBool unreg(UCurrRegistryKey key) {
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool found = FALSE;
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&gCRegLock);
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CReg** p = &gCRegHead;
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (*p) {
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (*p == key) {
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *p = ((CReg*)key)->next;
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete (CReg*)key;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                found = TRUE;
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            p = &((*p)->next);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&gCRegLock);
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return found;
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const UChar* get(const char* id) {
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar* result = NULL;
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&gCRegLock);
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CReg* p = gCRegHead;
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* register cleanup of the mutex */
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (p) {
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (uprv_strcmp(id, p->id) == 0) {
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result = p->iso;
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            p = p->next;
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&gCRegLock);
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return result;
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* This doesn't need to be thread safe. It's for u_cleanup only. */
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static void cleanup(void) {
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (gCRegHead) {
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            CReg* n = gCRegHead;
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            gCRegHead = gCRegHead->next;
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete n;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_destroy(&gCRegLock);
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Release all static memory held by currency.
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/*The declaration here is needed so currency_cleanup(void)
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * can call this function.
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
30650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool U_CALLCONV
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querucurrency_cache_cleanup(void);
308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV currency_cleanup(void) {
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CReg::cleanup();
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    /*
315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     * There might be some cached currency data.
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru     */
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    currency_cache_cleanup();
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UCurrRegistryKey U_EXPORT2
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_register(const UChar* isoCode, const char* locale, UErrorCode *status)
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (status && U_SUCCESS(*status)) {
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char id[ULOC_FULLNAME_CAPACITY];
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idForLocale(locale, id, sizeof(id), status);
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return CReg::reg(isoCode, id, status);
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_unregister(UCurrRegistryKey key, UErrorCode* status)
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (status && U_SUCCESS(*status)) {
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return CReg::unreg(key);
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* UCONFIG_NO_SERVICE */
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_forLocale(const char* locale,
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UChar* buff,
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t buffCapacity,
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode* ec)
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t resLen = 0;
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* s = NULL;
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (ec != NULL && U_SUCCESS(*ec)) {
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((buff && buffCapacity) || !buffCapacity) {
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode localStatus = U_ZERO_ERROR;
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char id[ULOC_FULLNAME_CAPACITY];
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // there is a currency keyword. Try to see if it's valid
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(buffCapacity > resLen) {
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    u_charsToUChars(id, buff, resLen);
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // get country or country_variant in `id'
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(*ec)) {
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return 0;
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const UChar* result = CReg::get(id);
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (result) {
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(buffCapacity > u_strlen(result)) {
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        u_strcpy(buff, result);
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return u_strlen(result);
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Remove variants, which is only needed for registration.
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                char *idDelim = strchr(id, VAR_DELIM);
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (idDelim) {
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    idDelim[0] = 0;
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Look up the CurrencyMap element in the root bundle.
39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /*
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                Get the second item when PREEURO is requested, and this is a known Euro country.
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                If the requested variant is PREEURO, and this isn't a Euro country, assume
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                that the country changed over to the Euro in the future. This is probably
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                an old version of ICU that hasn't been updated yet. The latest currency is
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                probably correct.
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                */
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_SUCCESS(localStatus)) {
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    else if ((variantType & VARIANT_IS_EURO)) {
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        s = EUR_STR;
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ures_close(countryArray);
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ures_close(currencyReq);
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // We don't know about it.  Check to see if we support the variant.
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uloc_getParent(locale, id, sizeof(id), ec);
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *ec = U_USING_FALLBACK_WARNING;
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return ucurr_forLocale(id, buff, buffCapacity, ec);
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // There is nothing to fallback to. Report the failure/warning if possible.
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *ec = localStatus;
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_SUCCESS(*ec)) {
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(buffCapacity > resLen) {
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        u_strcpy(buff, s);
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return u_terminateUChars(buff, buffCapacity, resLen, ec);
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *ec = U_ILLEGAL_ARGUMENT_ERROR;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return resLen;
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// end registration
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Modify the given locale name by removing the rightmost _-delimited
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * element.  If there is none, empty the string ("" == root).
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: The string "root" is not recognized; do not use it.
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return TRUE if the fallback happened; FALSE if locale is already
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * root ("").
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool fallback(char *loc) {
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!*loc) {
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getParent(loc, loc, (int32_t)uprv_strlen(loc), &status);
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /*
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *i = uprv_strrchr(loc, '_');
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (i == NULL) {
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i = loc;
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *i = 0;
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const UChar* U_EXPORT2
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_getName(const UChar* currency,
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const char* locale,
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UCurrNameStyle nameStyle,
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UBool* isChoiceFormat, // fillin
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t* len, // fillin
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UErrorCode* ec) {
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Look up the Currencies resource for the given locale.  The
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currencies locale data looks like this:
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|en {
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|  Currencies {
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    USD { "US$", "US Dollar" }
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    CHF { "Sw F", "Swiss Franc" }
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    //...
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|  }
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|}
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*ec)) {
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t choice = (int32_t) nameStyle;
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (choice < 0 || choice > 1) {
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *ec = U_ILLEGAL_ARGUMENT_ERROR;
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // In the future, resource bundles may implement multi-level
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fallback.  That is, if a currency is not found in the en_US
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currencies data, then the en Currencies data will be searched.
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currently, if a Currencies datum exists in en_US and en, the
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // en_US entry hides that in en.
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We want multi-level fallback for this resource, so we implement
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // it manually.
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Use a separate UErrorCode here that does not propagate out of
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this function.
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR;
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char loc[ULOC_FULLNAME_CAPACITY];
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getName(locale, loc, sizeof(loc), &ec2);
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) {
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *ec = U_ILLEGAL_ARGUMENT_ERROR;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buf[ISO_COUNTRY_CODE_LENGTH+1];
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myUCharsToChars(buf, currency);
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* s = NULL;
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ec2 = U_ZERO_ERROR;
52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2);
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rb = ures_getByKey(rb, CURRENCIES, rb, &ec2);
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Fetch resource with multi-level resource inheritance fallback
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rb = ures_getByKeyWithFallback(rb, buf, rb, &ec2);
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    s = ures_getStringByIndex(rb, choice, len, &ec2);
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(rb);
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we've succeeded we're done.  Otherwise, try to fallback.
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If that fails (because we are already at root) then exit.
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec2)) {
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ec2 == U_USING_DEFAULT_WARNING
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            || (ec2 == U_USING_FALLBACK_WARNING && *ec != U_USING_DEFAULT_WARNING)) {
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *ec = ec2;
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Determine if this is a ChoiceFormat pattern.  One leading mark
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // indicates a ChoiceFormat.  Two indicates a static string that
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // starts with a mark.  In either case, the first mark is ignored,
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if present.  Marks in the rest of the string have no special
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // meaning.
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *isChoiceFormat = FALSE;
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec2)) {
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_ASSERT(s != NULL);
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i=0;
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (i < *len && s[i] == CHOICE_FORMAT_MARK && i < 2) {
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++i;
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *isChoiceFormat = (i == 1);
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (i != 0) ++s; // Skip over first mark
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return s;
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we fail to find a match, use the ISO 4217 code
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *len = u_strlen(currency); // Should == ISO_COUNTRY_CODE_LENGTH, but maybe not...?
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *ec = U_USING_DEFAULT_WARNING;
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return currency;
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI const UChar* U_EXPORT2
563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruucurr_getPluralName(const UChar* currency,
564b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const char* locale,
565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UBool* isChoiceFormat,
566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const char* pluralCount,
567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t* len, // fillin
568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UErrorCode* ec) {
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Look up the Currencies resource for the given locale.  The
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currencies locale data looks like this:
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|en {
572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|  CurrencyPlurals {
573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|    USD{
574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|      one{"US dollar"}
575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|      other{"US dollars"}
576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|    }
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|  }
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|}
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(*ec)) {
581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 0;
582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Use a separate UErrorCode here that does not propagate out of
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this function.
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR;
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char loc[ULOC_FULLNAME_CAPACITY];
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getName(locale, loc, sizeof(loc), &ec2);
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) {
591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *ec = U_ILLEGAL_ARGUMENT_ERROR;
592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 0;
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char buf[ISO_COUNTRY_CODE_LENGTH+1];
596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    myUCharsToChars(buf, currency);
597b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* s = NULL;
599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ec2 = U_ZERO_ERROR;
60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2);
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    rb = ures_getByKey(rb, CURRENCYPLURALS, rb, &ec2);
603b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Fetch resource with multi-level resource inheritance fallback
605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    rb = ures_getByKeyWithFallback(rb, buf, rb, &ec2);
606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    s = ures_getStringByKeyWithFallback(rb, pluralCount, len, &ec2);
608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec2)) {
609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        //  fall back to "other"
610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ec2 = U_ZERO_ERROR;
611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        s = ures_getStringByKeyWithFallback(rb, "other", len, &ec2);
612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(ec2)) {
613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(rb);
614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // fall back to long name in Currencies
615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return ucurr_getName(currency, locale, UCURR_LONG_NAME,
616b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                 isChoiceFormat, len, ec);
617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(rb);
620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we've succeeded we're done.  Otherwise, try to fallback.
622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If that fails (because we are already at root) then exit.
623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_SUCCESS(ec2)) {
624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (ec2 == U_USING_DEFAULT_WARNING
625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            || (ec2 == U_USING_FALLBACK_WARNING && *ec != U_USING_DEFAULT_WARNING)) {
626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *ec = ec2;
627b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
628b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        U_ASSERT(s != NULL);
629b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return s;
630b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
631b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
632b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we fail to find a match, use the ISO 4217 code
633b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *len = u_strlen(currency); // Should == ISO_COUNTRY_CODE_LENGTH, but maybe not...?
634b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *ec = U_USING_DEFAULT_WARNING;
635b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return currency;
636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
637b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
638b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================================================
640b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Following are structure and function for parsing currency names
641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
642b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define NEED_TO_BE_DELETED 0x1
643b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
644b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// TODO: a better way to define this?
645b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_CURRENCY_NAME_LEN 100
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
647b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct {
648b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const char* IsoCode;  // key
649b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar* currencyName;  // value
650b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t currencyNameLen;  // value length
651b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t flag;  // flags
652b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} CurrencyNameStruct;
653b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
654b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
655b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifndef MIN
656b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MIN(a,b) (((a)<(b)) ? (a) : (b))
657b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
658b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
659b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifndef MAX
660b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX(a,b) (((a)<(b)) ? (b) : (a))
661b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
662b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
663b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
664b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Comparason function used in quick sort.
66550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int U_CALLCONV currencyNameComparator(const void* a, const void* b) {
666b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const CurrencyNameStruct* currName_1 = (const CurrencyNameStruct*)a;
667b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const CurrencyNameStruct* currName_2 = (const CurrencyNameStruct*)b;
668b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t i = 0;
669b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru         i < MIN(currName_1->currencyNameLen, currName_2->currencyNameLen);
670b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru         ++i) {
671b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currName_1->currencyName[i] < currName_2->currencyName[i]) {
672b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return -1;
673b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
674b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currName_1->currencyName[i] > currName_2->currencyName[i]) {
675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return 1;
676b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
677b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
678b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (currName_1->currencyNameLen < currName_2->currencyNameLen) {
679b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return -1;
680b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if (currName_1->currencyNameLen > currName_2->currencyNameLen) {
681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 1;
682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
683b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return 0;
684b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
685b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
687b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Give a locale, return the maximum number of currency names associated with
688b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// this locale.
689b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// It gets currency names from resource bundles using fallback.
690b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// It is the maximum number because in the fallback chain, some of the
691b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// currency names are duplicated.
692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// For example, given locale as "en_US", the currency names get from resource
693b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// bundle in "en_US" and "en" are duplicated. The fallback mechanism will count
694b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// all currency names in "en_US" and "en".
695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
696b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerugetCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_t* total_currency_symbol_count) {
69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    U_NAMESPACE_USE
698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_name_count = 0;
699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_symbol_count = 0;
700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UChar* s = NULL;
701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char locale[ULOC_FULLNAME_CAPACITY];
702b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_strcpy(locale, loc);
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;) {
704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UErrorCode ec2 = U_ZERO_ERROR;
705b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // TODO: ures_openDirect?
70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale, &ec2);
707b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, NULL, &ec2);
708b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t n = ures_getSize(curr);
709b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr, i, NULL, &ec2);
711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t len;
712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2);
713b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UBool isChoice = FALSE;
714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (len > 0 && s[0] == CHOICE_FORMAT_MARK) {
715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ++s;
716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                --len;
717b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (len > 0 && s[0] != CHOICE_FORMAT_MARK) {
718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    isChoice = TRUE;
719b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
720b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (isChoice) {
722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ChoiceFormat fmt(s, ec2);
723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t fmt_count;
724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                fmt.getFormats(fmt_count);
725b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *total_currency_symbol_count += fmt_count;
726b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
727b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ++(*total_currency_symbol_count);  // currency symbol
728b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
729b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
730b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ++(*total_currency_symbol_count); // iso code
731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ++(*total_currency_name_count); // long name
732b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(names);
733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
734b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // currency plurals
736b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UErrorCode ec3 = U_ZERO_ERROR;
737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, NULL, &ec3);
738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        n = ures_getSize(curr_p);
739b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr_p, i, NULL, &ec3);
741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *total_currency_name_count += ures_getSize(names);
742b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(names);
743b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
744b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(curr_p);
745b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(curr);
746b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(rb);
747b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (!fallback(locale)) {
749b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
750b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
751b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
752b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
753b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
754b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// TODO: locale dependent
755b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UChar*
756b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerutoUpperCase(const UChar* source, int32_t len) {
757b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar* dest = NULL;
758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
759b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t destLen = u_strToUpper(dest, 0, source, len, NULL, &ec);
760b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
761b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ec = U_ZERO_ERROR;
762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dest = (UChar*)uprv_malloc(sizeof(UChar) * MAX(destLen, len));
763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    u_strToUpper(dest, destLen, source, len, NULL, &ec);
764b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec)) {
765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_memcpy(dest, source, sizeof(UChar) * len);
766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
767b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return dest;
768b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
769b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
770b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
771b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Collect all available currency names associated with the give locale
772b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// (enable fallback chain).
773b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Read currenc names defined in resource bundle "Currencies" and
774b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// "CurrencyPlural", enable fallback chain.
775b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// return the malloc-ed currency name arrays and the total number of currency
776b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// names in the array.
777b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
778b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerucollectCurrencyNames(const char* locale,
779b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     CurrencyNameStruct** currencyNames,
780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     int32_t* total_currency_name_count,
781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     CurrencyNameStruct** currencySymbols,
782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     int32_t* total_currency_symbol_count,
783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     UErrorCode& ec) {
78450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    U_NAMESPACE_USE
785b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Look up the Currencies resource for the given locale.
786b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR;
787b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
788b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char loc[ULOC_FULLNAME_CAPACITY];
789b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uloc_getName(locale, loc, sizeof(loc), &ec2);
790b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) {
791b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
793b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
794b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Get maximum currency name count first.
795b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    getCurrencyNameCount(loc, total_currency_name_count, total_currency_symbol_count);
796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *currencyNames = (CurrencyNameStruct*)uprv_malloc
798b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (sizeof(CurrencyNameStruct) * (*total_currency_name_count));
799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *currencySymbols = (CurrencyNameStruct*)uprv_malloc
800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (sizeof(CurrencyNameStruct) * (*total_currency_symbol_count));
801b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UChar* s = NULL;  // currency name
803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char* iso = NULL;  // currency ISO code
804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_name_count = 0;
806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_symbol_count = 0;
807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec3 = U_ZERO_ERROR;
809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec4 = U_ZERO_ERROR;
810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Using hash to remove duplicates caused by locale fallback
812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UHashtable* currencyIsoCodes = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &ec3);
813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UHashtable* currencyPluralIsoCodes = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &ec4);
814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t localeLevel = 0; ; ++localeLevel) {
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ec2 = U_ZERO_ERROR;
816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // TODO: ures_openDirect
81750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2);
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, NULL, &ec2);
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t n = ures_getSize(curr);
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr, i, NULL, &ec2);
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t len;
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2);
824b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // TODO: uhash_put wont change key/value?
825b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            iso = (char*)ures_getKey(names);
826b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (localeLevel == 0) {
827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uhash_put(currencyIsoCodes, iso, iso, &ec3);
828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
829b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (uhash_get(currencyIsoCodes, iso) != NULL) {
830b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(names);
831b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    continue;
832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } else {
833b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    uhash_put(currencyIsoCodes, iso, iso, &ec3);
834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
835b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool isChoice = FALSE;
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (len > 0 && s[0] == CHOICE_FORMAT_MARK) {
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++s;
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --len;
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (len > 0 && s[0] != CHOICE_FORMAT_MARK) {
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    isChoice = TRUE;
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (isChoice) {
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ChoiceFormat fmt(s, ec2);
846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t fmt_count;
847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                const UnicodeString* formats = fmt.getFormats(fmt_count);
848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                for (int i = 0; i < fmt_count; ++i) {
849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // put iso, formats[i]; into array
850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t length = formats[i].length();
851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UChar* name = (UChar*)uprv_malloc(sizeof(UChar)*length);
852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    formats[i].extract(0, length, name);
853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[*total_currency_symbol_count].currencyName = name;
855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[*total_currency_symbol_count].flag = NEED_TO_BE_DELETED;
856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = length;
857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Add currency symbol.
860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[*total_currency_symbol_count].currencyName = (UChar*)s;
862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[*total_currency_symbol_count].flag = 0;
863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = len;
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Add currency long name.
867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            s = ures_getStringByIndex(names, UCURR_LONG_NAME, &len, &ec2);
868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[*total_currency_name_count].IsoCode = iso;
869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UChar* upperName = toUpperCase(s, len);
870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[*total_currency_name_count].currencyName = upperName;
871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[*total_currency_name_count].flag = NEED_TO_BE_DELETED;
872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[(*total_currency_name_count)++].currencyNameLen = len;
873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // put (iso, 3, and iso) in to array
875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Add currency ISO code.
876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].currencyName = (UChar*)uprv_malloc(sizeof(UChar)*3);
878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].currencyName[0] = iso[0];
879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].currencyName[1] = iso[1];
880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].currencyName[2] = iso[2];
881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].flag = NEED_TO_BE_DELETED;
882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = 3;
883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(names);
885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // currency plurals
888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UErrorCode ec3 = U_ZERO_ERROR;
889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, NULL, &ec3);
890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        n = ures_getSize(curr_p);
891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr_p, i, NULL, &ec3);
893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            iso = (char*)ures_getKey(names);
894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Using hash to remove duplicated ISO codes in fallback chain.
895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (localeLevel == 0) {
896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uhash_put(currencyPluralIsoCodes, iso, iso, &ec4);
897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (uhash_get(currencyPluralIsoCodes, iso) != NULL) {
899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(names);
900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    continue;
901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } else {
902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    uhash_put(currencyPluralIsoCodes, iso, iso, &ec4);
903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t num = ures_getSize(names);
906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t len;
907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            for (int32_t j = 0; j < num; ++j) {
908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // TODO: remove duplicates between singular name and
909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // currency long name?
910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                s = ures_getStringByIndex(names, j, &len, &ec3);
911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[*total_currency_name_count].IsoCode = iso;
912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UChar* upperName = toUpperCase(s, len);
913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[*total_currency_name_count].currencyName = upperName;
914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[*total_currency_name_count].flag = NEED_TO_BE_DELETED;
915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[(*total_currency_name_count)++].currencyNameLen = len;
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(names);
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(curr_p);
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(curr);
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(rb);
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (!fallback(loc)) {
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uhash_close(currencyIsoCodes);
929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uhash_close(currencyPluralIsoCodes);
930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // quick sort the struct
932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    qsort(*currencyNames, *total_currency_name_count,
933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru          sizeof(CurrencyNameStruct), currencyNameComparator);
934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    qsort(*currencySymbols, *total_currency_symbol_count,
935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru          sizeof(CurrencyNameStruct), currencyNameComparator);
936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("currency name count: %d\n", *total_currency_name_count);
939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < *total_currency_name_count; ++index) {
940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("index: %d\n", index);
941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("iso: %s\n", (*currencyNames)[index].IsoCode);
942b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("currencyName:");
943b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i = 0; i < (*currencyNames)[index].currencyNameLen; ++i) {
944b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            printf("%c", (unsigned char)(*currencyNames)[index].currencyName[i]);
945b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
946b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("\n");
947b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("len: %d\n", (*currencyNames)[index].currencyNameLen);
948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
949b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("currency symbol count: %d\n", *total_currency_symbol_count);
950b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < *total_currency_symbol_count; ++index) {
951b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("index: %d\n", index);
952b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("iso: %s\n", (*currencySymbols)[index].IsoCode);
953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("currencySymbol:");
954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i = 0; i < (*currencySymbols)[index].currencyNameLen; ++i) {
955b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            printf("%c", (unsigned char)(*currencySymbols)[index].currencyName[i]);
956b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
957b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("\n");
958b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("len: %d\n", (*currencySymbols)[index].currencyNameLen);
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  currencyNames: currency names array
964b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  indexInCurrencyNames: the index of the character in currency names
965b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//         array against which the comparison is done
966b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  key: input text char to compare against
967b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  begin(IN/OUT): the begin index of matching range in currency names array
968b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  end(IN/OUT): the end index of matching range in currency names array.
969b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t
970b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerubinarySearch(const CurrencyNameStruct* currencyNames,
971b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t indexInCurrencyNames,
972b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             const UChar key,
973b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t* begin, int32_t* end) {
974b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
975b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("key = %x\n", key);
976b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   int32_t first = *begin;
978b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   int32_t last = *end;
979b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   while (first <= last) {
980b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       int32_t mid = (first + last) / 2;  // compute mid point.
981b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       if (indexInCurrencyNames >= currencyNames[mid].currencyNameLen) {
982b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           first = mid + 1;
983b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       } else {
984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           if (key > currencyNames[mid].currencyName[indexInCurrencyNames]) {
985b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               first = mid + 1;
986b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
987b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           else if (key < currencyNames[mid].currencyName[indexInCurrencyNames]) {
988b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               last = mid - 1;
989b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
990b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           else {
991b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Find a match, and looking for ranges
992b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Now do two more binary searches. First, on the left side for
993b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // the greatest L such that CurrencyNameStruct[L] < key.
994b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t L = *begin;
995b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t R = mid;
996b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
997b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
998b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                printf("mid = %d\n", mid);
999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1000b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                while (L < R) {
1001b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t M = (L + R) / 2;
1002b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1003b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    printf("L = %d, R = %d, M = %d\n", L, R, M);
1004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1005b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (indexInCurrencyNames >= currencyNames[M].currencyNameLen) {
1006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        L = M + 1;
1007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    } else {
1008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (currencyNames[M].currencyName[indexInCurrencyNames] < key) {
1009b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            L = M + 1;
1010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        } else {
1011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            U_ASSERT(currencyNames[M].currencyName[indexInCurrencyNames] == key);
1013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1014b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            R = M;
1015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
1016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1019b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                U_ASSERT(L == R);
1020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1021b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *begin = L;
1022b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1023b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                printf("begin = %d\n", *begin);
1024b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                U_ASSERT(currencyNames[*begin].currencyName[indexInCurrencyNames] == key);
1025b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1026b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1027b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Now for the second search, finding the least R such that
1028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // key < CurrencyNameStruct[R].
1029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                L = mid;
1030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                R = *end;
1031b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                while (L < R) {
1032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t M = (L + R) / 2;
1033b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    printf("L = %d, R = %d, M = %d\n", L, R, M);
1035b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (currencyNames[M].currencyNameLen < indexInCurrencyNames) {
1037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        L = M + 1;
1038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    } else {
1039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (currencyNames[M].currencyName[indexInCurrencyNames] > key) {
1040b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            R = M;
1041b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        } else {
1042b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1043b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            U_ASSERT(currencyNames[M].currencyName[indexInCurrencyNames] == key);
1044b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1045b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            L = M + 1;
1046b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
1047b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1048b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                U_ASSERT(L == R);
1051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1052b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (currencyNames[R].currencyName[indexInCurrencyNames] > key) {
1053b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    *end = R - 1;
1054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } else {
1055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    *end = R;
1056b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1057b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                printf("end = %d\n", *end);
1059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // now, found the range. check whether there is exact match
1062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (currencyNames[*begin].currencyNameLen == indexInCurrencyNames + 1) {
1063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    return *begin;  // find range and exact match.
1064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return -1;  // find range, but no exact match.
1066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
1067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       }
1068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   }
1069b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   *begin = -1;
1070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   *end = -1;
1071b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   return -1;    // failed to find range.
1072b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1073b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Linear search "text" in "currencyNames".
1076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  begin, end: the begin and end index in currencyNames, within which
1077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//         range should the search be performed.
1078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  textLen: the length of the text to be compared
1079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchLen(IN/OUT): passing in the computed max matching length
1080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                              pass out the new max  matching length
1081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchIndex: the index in currencyName which has the longest
1082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                        match with input text.
1083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerulinearSearch(const CurrencyNameStruct* currencyNames,
1085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t begin, int32_t end,
1086b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             const UChar* text, int32_t textLen,
1087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t *maxMatchLen, int32_t* maxMatchIndex) {
1088b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = begin; index <= end; ++index) {
1089b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t len = currencyNames[index].currencyNameLen;
1090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (len > *maxMatchLen && len <= textLen &&
1091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memcmp(currencyNames[index].currencyName, text, len * sizeof(UChar)) == 0) {
1092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchIndex = index;
1093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchLen = len;
1094b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1095b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            printf("maxMatchIndex = %d, maxMatchLen = %d\n",
1096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   *maxMatchIndex, *maxMatchLen);
1097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LINEAR_SEARCH_THRESHOLD 10
1103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Find longest match between "text" and currency names in "currencyNames".
1105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  total_currency_count: total number of currency names in CurrencyNames.
1106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  textLen: the length of the text to be compared
1107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchLen: passing in the computed max matching length
1108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                              pass out the new max  matching length
1109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchIndex: the index in currencyName which has the longest
1110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                        match with input text.
1111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerusearchCurrencyName(const CurrencyNameStruct* currencyNames,
1113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   int32_t total_currency_count,
1114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   const UChar* text, int32_t textLen,
1115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   int32_t* maxMatchLen, int32_t* maxMatchIndex) {
1116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *maxMatchIndex = -1;
1117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *maxMatchLen = 0;
1118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t matchIndex = -1;
1119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t binarySearchBegin = 0;
1120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t binarySearchEnd = total_currency_count - 1;
1121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // It is a variant of binary search.
1122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // For example, given the currency names in currencyNames array are:
1123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // A AB ABC AD AZ B BB BBEX BBEXYZ BS C D E....
1124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // and the input text is BBEXST
1125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The first round binary search search "B" in the text against
1126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // the first char in currency names, and find the first char matching range
1127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // to be "B BB BBEX BBEXYZ BS" (and the maximum matching "B").
1128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 2nd round binary search search the second "B" in the text against
1129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // the 2nd char in currency names, and narrow the matching range to
1130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // "BB BBEX BBEXYZ" (and the maximum matching "BB").
1131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 3rd round returnes the range as "BBEX BBEXYZ" (without changing
1132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // maximum matching).
1133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 4th round returns the same range (the maximum matching is "BBEX").
1134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 5th round returns no matching range.
1135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < textLen; ++index) {
1136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // matchIndex saves the one with exact match till the current point.
1137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // [binarySearchBegin, binarySearchEnd] saves the matching range.
1138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        matchIndex = binarySearch(currencyNames, index,
1139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                  text[index],
1140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                  &binarySearchBegin, &binarySearchEnd);
1141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (binarySearchBegin == -1) { // did not find the range
1142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
1143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (matchIndex != -1) {
1145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // find an exact match for text from text[0] to text[index]
1146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // in currencyNames array.
1147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchLen = index + 1;
1148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchIndex = matchIndex;
1149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (binarySearchEnd - binarySearchBegin < LINEAR_SEARCH_THRESHOLD) {
1151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // linear search if within threshold.
1152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            linearSearch(currencyNames, binarySearchBegin, binarySearchEnd,
1153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                         text, textLen,
1154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                         maxMatchLen, maxMatchIndex);
1155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
1156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return;
1159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================= currency name cache =====================
1162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct {
1163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char locale[ULOC_FULLNAME_CAPACITY];  //key
1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // currency names, case insensitive
1165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencyNames;  // value
1166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t totalCurrencyNameCount;  // currency name count
1167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // currency symbols and ISO code, case sensitive
1168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencySymbols; // value
1169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t totalCurrencySymbolCount;  // count
1170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // reference count.
1171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // reference count is set to 1 when an entry is put to cache.
1172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // it increases by 1 before accessing, and decreased by 1 after accessing.
1173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The entry is deleted when ref count is zero, which means
1174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // the entry is replaced out of cache and no process is accessing it.
1175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t refCount;
1176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} CurrencyNameCacheEntry;
1177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define CURRENCY_NAME_CACHE_NUM 10
1180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Reserve 10 cache entries.
1182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic CurrencyNameCacheEntry* currCache[CURRENCY_NAME_CACHE_NUM] = {NULL};
1183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Using an index to indicate which entry to be replaced when cache is full.
1184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// It is a simple round-robin replacement strategy.
1185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int8_t currentCacheEntryIndex = 0;
1186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Cache deletion
1188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteCurrencyNames(CurrencyNameStruct* currencyNames, int32_t count) {
1190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < count; ++index) {
1191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( (currencyNames[index].flag & NEED_TO_BE_DELETED) ) {
1192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_free(currencyNames[index].currencyName);
1193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_free(currencyNames);
1196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteCacheEntry(CurrencyNameCacheEntry* entry) {
1201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    deleteCurrencyNames(entry->currencyNames, entry->totalCurrencyNameCount);
1202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    deleteCurrencyNames(entry->currencySymbols, entry->totalCurrencySymbolCount);
1203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_free(entry);
1204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Cache clean up
120850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool U_CALLCONV
1209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querucurrency_cache_cleanup(void) {
1210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
1211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currCache[i]) {
1212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            deleteCacheEntry(currCache[i]);
1213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currCache[i] = 0;
1214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return TRUE;
1217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CFUNC void
1221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuprv_parseCurrency(const char* locale,
1222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   const U_NAMESPACE_QUALIFIER UnicodeString& text,
1223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   U_NAMESPACE_QUALIFIER ParsePosition& pos,
1224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   int8_t type,
1225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   UChar* result,
1226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   UErrorCode& ec)
1227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
1228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    U_NAMESPACE_USE
1229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec)) {
1231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
1232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t total_currency_name_count = 0;
1235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencyNames = NULL;
1236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t total_currency_symbol_count = 0;
1237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencySymbols = NULL;
1238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameCacheEntry* cacheEntry = NULL;
1239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    umtx_lock(NULL);
1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // in order to handle racing correctly,
1242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // not putting 'search' in a separate function and using UMTX.
1243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int8_t  found = -1;
1244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
1245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currCache[i]!= NULL &&
1246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_strcmp(locale, currCache[i]->locale) == 0) {
1247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            found = i;
1248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
1249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (found != -1) {
1252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        cacheEntry = currCache[found];
1253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        currencyNames = cacheEntry->currencyNames;
1254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        total_currency_name_count = cacheEntry->totalCurrencyNameCount;
1255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        currencySymbols = cacheEntry->currencySymbols;
1256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
1257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ++(cacheEntry->refCount);
1258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    umtx_unlock(NULL);
1260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (found == -1) {
1261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        collectCurrencyNames(locale, &currencyNames, &total_currency_name_count, &currencySymbols, &total_currency_symbol_count, ec);
1262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(ec)) {
1263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
1264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        umtx_lock(NULL);
1266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // check again.
1267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int8_t  found = -1;
1268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
1269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (currCache[i]!= NULL &&
1270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uprv_strcmp(locale, currCache[i]->locale) == 0) {
1271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                found = i;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (found == -1) {
1276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // insert new entry to
1277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // currentCacheEntryIndex % CURRENCY_NAME_CACHE_NUM
1278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // and remove the existing entry
1279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // currentCacheEntryIndex % CURRENCY_NAME_CACHE_NUM
1280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // from cache.
1281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry = currCache[currentCacheEntryIndex];
1282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (cacheEntry) {
1283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                --(cacheEntry->refCount);
1284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // delete if the ref count is zero
1285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (cacheEntry->refCount == 0) {
1286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    deleteCacheEntry(cacheEntry);
1287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
1289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry = (CurrencyNameCacheEntry*)uprv_malloc(sizeof(CurrencyNameCacheEntry));
1290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currCache[currentCacheEntryIndex] = cacheEntry;
1291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_strcpy(cacheEntry->locale, locale);
1292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->currencyNames = currencyNames;
1293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->totalCurrencyNameCount = total_currency_name_count;
1294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->currencySymbols = currencySymbols;
1295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->totalCurrencySymbolCount = total_currency_symbol_count;
1296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->refCount = 2; // one for cache, one for reference
1297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currentCacheEntryIndex = (currentCacheEntryIndex + 1) % CURRENCY_NAME_CACHE_NUM;
1298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cache_cleanup);
1299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
1301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            deleteCurrencyNames(currencyNames, total_currency_name_count);
1302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            deleteCurrencyNames(currencySymbols, total_currency_symbol_count);
1303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry = currCache[found];
1304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currencyNames = cacheEntry->currencyNames;
1305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            total_currency_name_count = cacheEntry->totalCurrencyNameCount;
1306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currencySymbols = cacheEntry->currencySymbols;
1307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
1308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ++(cacheEntry->refCount);
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        umtx_unlock(NULL);
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t start = pos.getIndex();
1314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar inputText[MAX_CURRENCY_NAME_LEN];
1316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar upperText[MAX_CURRENCY_NAME_LEN];
1317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t textLen = MIN(MAX_CURRENCY_NAME_LEN, text.length() - start);
1318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    text.extract(start, textLen, inputText);
1319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec1 = U_ZERO_ERROR;
1320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    textLen = u_strToUpper(upperText, MAX_CURRENCY_NAME_LEN, inputText, textLen, NULL, &ec1);
1321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t max = 0;
1323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t matchIndex = -1;
1324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // case in-sensitive comparision against currency names
1325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    searchCurrencyName(currencyNames, total_currency_name_count,
1326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       upperText, textLen, &max, &matchIndex);
1327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("search in names, max = %d, matchIndex = %d\n", max, matchIndex);
1330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t maxInSymbol = 0;
1333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t matchIndexInSymbol = -1;
1334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (type != UCURR_LONG_NAME) {  // not name only
1335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // case sensitive comparison against currency symbols and ISO code.
1336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        searchCurrencyName(currencySymbols, total_currency_symbol_count,
1337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           inputText, textLen,
1338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           &maxInSymbol, &matchIndexInSymbol);
1339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("search in symbols, maxInSymbol = %d, matchIndexInSymbol = %d\n", maxInSymbol, matchIndexInSymbol);
1343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (max >= maxInSymbol && matchIndex != -1) {
1346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_charsToUChars(currencyNames[matchIndex].IsoCode, result, 4);
1347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        pos.setIndex(start + max);
1348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if (maxInSymbol >= max && matchIndexInSymbol != -1) {
1349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_charsToUChars(currencySymbols[matchIndexInSymbol].IsoCode, result, 4);
1350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        pos.setIndex(start + maxInSymbol);
1351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // decrease reference count
1354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    umtx_lock(NULL);
1355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    --(cacheEntry->refCount);
1356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (cacheEntry->refCount == 0) {  // remove
1357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        deleteCacheEntry(cacheEntry);
1358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    umtx_unlock(NULL);
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Internal method.  Given a currency ISO code and a locale, return
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the "static" currency name.  This is usually the same as the
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * format is applied to the number 2.0 (to yield the more common
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * plural) to return a static name.
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is used for backward compatibility with old currency logic in
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * DecimalFormat and DecimalFormatSymbols.
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CFUNC void
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getStaticCurrencyName(const UChar* iso, const char* loc,
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           U_NAMESPACE_QUALIFIER UnicodeString& result, UErrorCode& ec)
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_NAMESPACE_USE
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isChoiceFormat;
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME,
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                          &isChoiceFormat, &len, &ec);
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // If this is a ChoiceFormat currency, then format an
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // arbitrary value; pick something != 1; more common.
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.truncate(0);
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (isChoiceFormat) {
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ChoiceFormat f(currname, ec);
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(ec)) {
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                f.format(2.0, result);
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result = iso;
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result = currname;
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_getDefaultFractionDigits(const UChar* currency, UErrorCode* ec) {
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (_findMetaData(currency, *ec))[0];
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_getRoundingIncrement(const UChar* currency, UErrorCode* ec) {
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t *data = _findMetaData(currency, *ec);
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If the meta data is invalid, return 0.0.
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (data[0] < 0 || data[0] > MAX_POW10) {
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(*ec)) {
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *ec = U_INVALID_FORMAT_ERROR;
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0.0;
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If there is no rounding, return 0.0 to indicate no rounding.  A
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // rounding value (data[1]) of 0 or 1 indicates no rounding.
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (data[1] < 2) {
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0.0;
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Return data[1] / 10^(data[0]).  The only actual rounding data,
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // as of this writing, is CHF { 2, 5 }.
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return double(data[1]) / POW10[data[0]];
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct UCurrencyContext {
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t currType; /* UCurrCurrencyType */
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t listIdx;
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} UCurrencyContext;
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPlease keep this list in alphabetical order.
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruYou can look at the CLDR supplemental data or ISO-4217 for the meaning of some
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruof these items.
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruISO-4217: http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const struct CurrencyList {
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *currency;
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t currType;
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} gCurrencyList[] = {
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ADP", UCURR_COMMON|UCURR_DEPRECATED},
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AED", UCURR_COMMON|UCURR_NON_DEPRECATED},
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AFA", UCURR_COMMON|UCURR_DEPRECATED},
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AFN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ALK", UCURR_COMMON|UCURR_DEPRECATED},
1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ALL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ANG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AOA", UCURR_COMMON|UCURR_NON_DEPRECATED},
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AOK", UCURR_COMMON|UCURR_DEPRECATED},
1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AON", UCURR_COMMON|UCURR_DEPRECATED},
1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AOR", UCURR_COMMON|UCURR_DEPRECATED},
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ARA", UCURR_COMMON|UCURR_DEPRECATED},
1458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ARL", UCURR_COMMON|UCURR_DEPRECATED},
1459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ARM", UCURR_COMMON|UCURR_DEPRECATED},
1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ARP", UCURR_COMMON|UCURR_DEPRECATED},
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ARS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ATS", UCURR_COMMON|UCURR_DEPRECATED},
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AUD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AWG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AZM", UCURR_COMMON|UCURR_DEPRECATED},
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AZN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BAD", UCURR_COMMON|UCURR_DEPRECATED},
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BAM", UCURR_COMMON|UCURR_NON_DEPRECATED},
1469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BAN", UCURR_COMMON|UCURR_DEPRECATED},
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BBD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BDT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BEC", UCURR_UNCOMMON|UCURR_DEPRECATED},
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BEF", UCURR_COMMON|UCURR_DEPRECATED},
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BEL", UCURR_UNCOMMON|UCURR_DEPRECATED},
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BGL", UCURR_COMMON|UCURR_DEPRECATED},
1476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"BGM", UCURR_COMMON|UCURR_DEPRECATED},
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BGN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BGO", UCURR_COMMON|UCURR_DEPRECATED},
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BHD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BIF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BND", UCURR_COMMON|UCURR_NON_DEPRECATED},
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BOB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BOL", UCURR_COMMON|UCURR_DEPRECATED},
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BOP", UCURR_COMMON|UCURR_DEPRECATED},
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BOV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRB", UCURR_COMMON|UCURR_DEPRECATED},
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRC", UCURR_COMMON|UCURR_DEPRECATED},
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRE", UCURR_COMMON|UCURR_DEPRECATED},
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRN", UCURR_COMMON|UCURR_DEPRECATED},
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRR", UCURR_COMMON|UCURR_DEPRECATED},
1493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BRZ", UCURR_COMMON|UCURR_DEPRECATED},
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BSD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BTN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BUK", UCURR_COMMON|UCURR_DEPRECATED},
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BWP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BYB", UCURR_COMMON|UCURR_DEPRECATED},
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BYR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BZD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CAD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CDF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CHE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CHF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CHW", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"CLE", UCURR_COMMON|UCURR_DEPRECATED},
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CLF", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CLP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CNX", UCURR_UNCOMMON|UCURR_DEPRECATED},
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CNY", UCURR_COMMON|UCURR_NON_DEPRECATED},
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"COP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"COU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CRC", UCURR_COMMON|UCURR_NON_DEPRECATED},
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CSD", UCURR_COMMON|UCURR_DEPRECATED},
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CSK", UCURR_COMMON|UCURR_DEPRECATED},
1516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"CUC", UCURR_COMMON|UCURR_NON_DEPRECATED},
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CUP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CVE", UCURR_COMMON|UCURR_NON_DEPRECATED},
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CYP", UCURR_COMMON|UCURR_DEPRECATED},
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CZK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DDM", UCURR_COMMON|UCURR_DEPRECATED},
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DEM", UCURR_COMMON|UCURR_DEPRECATED},
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DJF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DKK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DOP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DZD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ECS", UCURR_COMMON|UCURR_DEPRECATED},
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ECV", UCURR_UNCOMMON|UCURR_DEPRECATED},
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EEK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EGP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EQE", UCURR_COMMON|UCURR_DEPRECATED},
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ERN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ESA", UCURR_UNCOMMON|UCURR_DEPRECATED},
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ESB", UCURR_UNCOMMON|UCURR_DEPRECATED},
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ESP", UCURR_COMMON|UCURR_DEPRECATED},
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ETB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EUR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FIM", UCURR_COMMON|UCURR_DEPRECATED},
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FJD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FKP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FRF", UCURR_COMMON|UCURR_DEPRECATED},
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GBP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GEK", UCURR_COMMON|UCURR_DEPRECATED},
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GEL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GHC", UCURR_COMMON|UCURR_DEPRECATED},
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GHS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GIP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GNF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GNS", UCURR_COMMON|UCURR_DEPRECATED},
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GQE", UCURR_COMMON|UCURR_DEPRECATED},
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GRD", UCURR_COMMON|UCURR_DEPRECATED},
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GTQ", UCURR_COMMON|UCURR_NON_DEPRECATED},
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GWE", UCURR_COMMON|UCURR_DEPRECATED},
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GWP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GYD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HKD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HNL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HRD", UCURR_COMMON|UCURR_DEPRECATED},
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HRK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HTG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HUF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IDR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IEP", UCURR_COMMON|UCURR_DEPRECATED},
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ILP", UCURR_COMMON|UCURR_DEPRECATED},
1566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ILR", UCURR_COMMON|UCURR_DEPRECATED},
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ILS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"INR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IQD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IRR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ISJ", UCURR_COMMON|UCURR_DEPRECATED},
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ISK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ITL", UCURR_COMMON|UCURR_DEPRECATED},
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"JMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"JOD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"JPY", UCURR_COMMON|UCURR_NON_DEPRECATED},
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KES", UCURR_COMMON|UCURR_NON_DEPRECATED},
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KGS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KHR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KMF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KPW", UCURR_COMMON|UCURR_NON_DEPRECATED},
1582b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"KRH", UCURR_COMMON|UCURR_DEPRECATED},
1583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"KRO", UCURR_COMMON|UCURR_DEPRECATED},
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KRW", UCURR_COMMON|UCURR_NON_DEPRECATED},
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KWD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KYD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KZT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LAK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LBP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LKR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LRD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LSL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LSM", UCURR_COMMON|UCURR_DEPRECATED},
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LTL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LTT", UCURR_COMMON|UCURR_DEPRECATED},
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LUC", UCURR_UNCOMMON|UCURR_DEPRECATED},
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LUF", UCURR_COMMON|UCURR_DEPRECATED},
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LUL", UCURR_UNCOMMON|UCURR_DEPRECATED},
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LVL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LVR", UCURR_COMMON|UCURR_DEPRECATED},
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LYD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MAD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MAF", UCURR_COMMON|UCURR_DEPRECATED},
1604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MCF", UCURR_COMMON|UCURR_DEPRECATED},
1605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MDC", UCURR_COMMON|UCURR_DEPRECATED},
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MDL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MGA", UCURR_COMMON|UCURR_NON_DEPRECATED},
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MGF", UCURR_COMMON|UCURR_DEPRECATED},
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MKD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MKN", UCURR_COMMON|UCURR_DEPRECATED},
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MLF", UCURR_COMMON|UCURR_DEPRECATED},
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MMK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MNT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MOP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MRO", UCURR_COMMON|UCURR_NON_DEPRECATED},
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MTL", UCURR_COMMON|UCURR_DEPRECATED},
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MTP", UCURR_COMMON|UCURR_DEPRECATED},
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MUR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MVP", UCURR_COMMON|UCURR_DEPRECATED},
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MVR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MWK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MXN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MXP", UCURR_COMMON|UCURR_DEPRECATED},
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MXV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MYR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MZE", UCURR_COMMON|UCURR_NON_DEPRECATED},
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MZM", UCURR_COMMON|UCURR_DEPRECATED},
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MZN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NAD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NGN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NIC", UCURR_COMMON|UCURR_DEPRECATED},
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NIO", UCURR_COMMON|UCURR_NON_DEPRECATED},
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NLG", UCURR_COMMON|UCURR_DEPRECATED},
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NOK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NPR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NZD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"OMR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PAB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PEI", UCURR_COMMON|UCURR_DEPRECATED},
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PEN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PES", UCURR_COMMON|UCURR_DEPRECATED},
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PGK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PHP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PKR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PLN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PLZ", UCURR_COMMON|UCURR_DEPRECATED},
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PTE", UCURR_COMMON|UCURR_DEPRECATED},
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PYG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"QAR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RHD", UCURR_COMMON|UCURR_DEPRECATED},
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ROL", UCURR_COMMON|UCURR_DEPRECATED},
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RON", UCURR_COMMON|UCURR_NON_DEPRECATED},
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RSD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RUB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RUR", UCURR_COMMON|UCURR_DEPRECATED},
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RWF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SAR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SBD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SCR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SDD", UCURR_COMMON|UCURR_DEPRECATED},
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SDG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SDP", UCURR_COMMON|UCURR_DEPRECATED},
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SEK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SGD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SHP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SIT", UCURR_COMMON|UCURR_DEPRECATED},
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SKK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SLL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SOS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SRD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SRG", UCURR_COMMON|UCURR_DEPRECATED},
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"STD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SUR", UCURR_COMMON|UCURR_DEPRECATED},
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SVC", UCURR_COMMON|UCURR_NON_DEPRECATED},
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SYP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SZL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"THB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TJR", UCURR_COMMON|UCURR_DEPRECATED},
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TJS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1680b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"TMM", UCURR_COMMON|UCURR_DEPRECATED},
1681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"TMT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TND", UCURR_COMMON|UCURR_NON_DEPRECATED},
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TOP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TPE", UCURR_COMMON|UCURR_DEPRECATED},
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TRL", UCURR_COMMON|UCURR_DEPRECATED},
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TRY", UCURR_COMMON|UCURR_NON_DEPRECATED},
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TTD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TWD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TZS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UAH", UCURR_COMMON|UCURR_NON_DEPRECATED},
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UAK", UCURR_COMMON|UCURR_DEPRECATED},
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UGS", UCURR_COMMON|UCURR_DEPRECATED},
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UGX", UCURR_COMMON|UCURR_NON_DEPRECATED},
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"USD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"USN", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"USS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UYI", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1698b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"UYP", UCURR_COMMON|UCURR_DEPRECATED},
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UYU", UCURR_COMMON|UCURR_NON_DEPRECATED},
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UZS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VEB", UCURR_COMMON|UCURR_DEPRECATED},
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VEF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VND", UCURR_COMMON|UCURR_NON_DEPRECATED},
1704b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"VNN", UCURR_COMMON|UCURR_DEPRECATED},
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VUV", UCURR_COMMON|UCURR_NON_DEPRECATED},
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"WST", UCURR_COMMON|UCURR_NON_DEPRECATED},
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XAF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XAG", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XAU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBA", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBB", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBC", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XCD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XDR", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XEU", UCURR_UNCOMMON|UCURR_DEPRECATED},
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XFO", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XFU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XOF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XPD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XPF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XPT", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XRE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XTS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XXX", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YDD", UCURR_COMMON|UCURR_DEPRECATED},
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YER", UCURR_COMMON|UCURR_NON_DEPRECATED},
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YUD", UCURR_COMMON|UCURR_DEPRECATED},
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YUM", UCURR_COMMON|UCURR_DEPRECATED},
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YUN", UCURR_COMMON|UCURR_DEPRECATED},
1731b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"YUR", UCURR_COMMON|UCURR_DEPRECATED},
1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZAL", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZAR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZMK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZRN", UCURR_COMMON|UCURR_DEPRECATED},
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZRZ", UCURR_COMMON|UCURR_DEPRECATED},
1737b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ZWL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1738b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ZWR", UCURR_COMMON|UCURR_DEPRECATED},
1739b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ZWD", UCURR_COMMON|UCURR_DEPRECATED},
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { NULL, 0 } // Leave here to denote the end of the list.
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define UCURR_MATCHES_BITMASK(variable, typeToMatch) \
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((typeToMatch) == UCURR_ALL || ((variable) & (typeToMatch)) == (typeToMatch))
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_countCurrencyList(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context);
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t currType = myContext->currType;
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t count = 0;
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Count the number of items matching the type we are looking for. */
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t idx = 0; gCurrencyList[idx].currency != NULL; idx++) {
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (UCURR_MATCHES_BITMASK(gCurrencyList[idx].currType, currType)) {
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            count++;
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return count;
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* U_CALLCONV
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_nextCurrencyList(UEnumeration *enumerator,
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        int32_t* resultLength,
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UErrorCode * /*pErrorCode*/)
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context);
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Find the next in the list that matches the type we are looking for. */
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (myContext->listIdx < (sizeof(gCurrencyList)/sizeof(gCurrencyList[0]))-1) {
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const struct CurrencyList *currItem = &gCurrencyList[myContext->listIdx++];
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (UCURR_MATCHES_BITMASK(currItem->currType, myContext->currType))
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (resultLength) {
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *resultLength = 3; /* Currency codes are only 3 chars long */
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return currItem->currency;
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We enumerated too far. */
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (resultLength) {
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *resultLength = 0;
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_resetCurrencyList(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UCurrencyContext *)(enumerator->context))->listIdx = 0;
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_closeCurrencyList(UEnumeration *enumerator) {
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(enumerator->context);
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(enumerator);
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UEnumeration gEnumCurrencyList = {
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NULL,
1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NULL,
1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_closeCurrencyList,
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_countCurrencyList,
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uenum_unextDefault,
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_nextCurrencyList,
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_resetCurrencyList
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration * U_EXPORT2
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode) {
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UEnumeration *myEnum = NULL;
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCurrencyContext *myContext;
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myEnum = (UEnumeration*)uprv_malloc(sizeof(UEnumeration));
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (myEnum == NULL) {
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memcpy(myEnum, &gEnumCurrencyList, sizeof(UEnumeration));
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myContext = (UCurrencyContext*)uprv_malloc(sizeof(UCurrencyContext));
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (myContext == NULL) {
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(myEnum);
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myContext->currType = currType;
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myContext->listIdx = 0;
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myEnum->context = myContext;
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return myEnum;
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1831c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1832c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruucurr_countCurrencies(const char* locale,
1833c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UDate date,
1834c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UErrorCode* ec)
1835c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t currCount = 0;
1837c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t resLen = 0;
1838c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar* s = NULL;
1839c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1840c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (ec != NULL && U_SUCCESS(*ec))
1841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {
1842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // local variables
1843c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
1844c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        char id[ULOC_FULLNAME_CAPACITY];
1845c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
1846b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // get country or country_variant in `id'
1847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /*uint32_t variantType =*/ idForLocale(locale, id, sizeof(id), ec);
1848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(*ec))
1850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
1851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return 0;
1852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Remove variants, which is only needed for registration.
1855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        char *idDelim = strchr(id, VAR_DELIM);
1856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (idDelim)
1857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
1858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            idDelim[0] = 0;
1859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Look up the CurrencyMap element in the root bundle.
186250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
1863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
1864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1865b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Using the id derived from the local, get the currency data
1866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
1867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // process each currency to see which one is valid for the given date
1869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_SUCCESS(localStatus))
1870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
1871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            for (int32_t i=0; i<ures_getSize(countryArray); i++)
1872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
1873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // get the currency resource
1874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, NULL, &localStatus);
1875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                s = ures_getStringByKey(currencyRes, "id", &resLen, &localStatus);
1876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // get the from date
1878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t fromLength = 0;
1879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
1880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
1881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int64_t currDate64 = (int64_t)fromArray[0] << 32;
1883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
1884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UDate fromDate = (UDate)currDate64;
1885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (ures_getSize(currencyRes)> 2)
1887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
1888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t toLength = 0;
1889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
1890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
1891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    currDate64 = (int64_t)toArray[0] << 32;
1893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
1894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UDate toDate = (UDate)currDate64;
1895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if ((fromDate <= date) && (date < toDate))
1897b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
1898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currCount++;
1899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(toRes);
1902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1903b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                else
1904b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
1905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (fromDate <= date)
1906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
1907b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currCount++;
1908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // close open resources
1912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ures_close(currencyRes);
1913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ures_close(fromRes);
1914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } // end For loop
1916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } // end if (U_SUCCESS(localStatus))
1917c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1918b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(countryArray);
1919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Check for errors
1921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR)
1922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
1923b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // There is nothing to fallback to.
1924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Report the failure/warning if possible.
1925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *ec = localStatus;
1926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_SUCCESS(*ec))
1929b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
1930b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // no errors
1931b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return currCount;
1932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1933c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1934c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1935c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we got here, either error code is invalid or
1937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // some argument passed is no good.
1938c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return 0;
1939c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1940c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1941c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1942c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruucurr_forLocaleAndDate(const char* locale,
1943c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                UDate date,
1944c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t index,
1945c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                UChar* buff,
1946c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t buffCapacity,
1947c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                UErrorCode* ec)
1948c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1949c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t resLen = 0;
1950c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	int32_t currIndex = 0;
1951c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar* s = NULL;
1952c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (ec != NULL && U_SUCCESS(*ec))
1954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {
1955b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // check the arguments passed
1956b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ((buff && buffCapacity) || !buffCapacity )
1957b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
1958b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // local variables
1959c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UErrorCode localStatus = U_ZERO_ERROR;
1960c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            char id[ULOC_FULLNAME_CAPACITY];
1961c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
1962c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // get country or country_variant in `id'
1964b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /*uint32_t variantType =*/ idForLocale(locale, id, sizeof(id), ec);
1965b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_FAILURE(*ec))
1966b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
1967b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return 0;
1968b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
1969b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1970b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Remove variants, which is only needed for registration.
1971b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            char *idDelim = strchr(id, VAR_DELIM);
1972b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (idDelim)
1973b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
1974b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                idDelim[0] = 0;
1975b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
1976b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Look up the CurrencyMap element in the root bundle.
197850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
1979b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
1980b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1981b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Using the id derived from the local, get the currency data
1982b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
1983b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // process each currency to see which one is valid for the given date
1985b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            bool matchFound = false;
1986b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_SUCCESS(localStatus))
1987b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
1988b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if ((index <= 0) || (index> ures_getSize(countryArray)))
1989b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
1990c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    // requested index is out of bounds
1991c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    ures_close(countryArray);
1992b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    return 0;
1993b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1994b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1995b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                for (int32_t i=0; i<ures_getSize(countryArray); i++)
1996b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
1997b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // get the currency resource
1998b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, NULL, &localStatus);
1999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    s = ures_getStringByKey(currencyRes, "id", &resLen, &localStatus);
2000b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2001b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // get the from date
2002b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t fromLength = 0;
2003b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
2004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
2005b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int64_t currDate64 = (int64_t)fromArray[0] << 32;
2007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UDate fromDate = (UDate)currDate64;
2009b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (ures_getSize(currencyRes)> 2)
2011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        int32_t toLength = 0;
2013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
2014b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
2015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currDate64 = (int64_t)toArray[0] << 32;
2017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        UDate toDate = (UDate)currDate64;
2019b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if ((fromDate <= date) && (date < toDate))
2021b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        {
2022b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            currIndex++;
2023b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            if (currIndex == index)
2024b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            {
2025b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                matchFound = true;
2026b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            }
2027b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
2028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        ures_close(toRes);
2030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2031b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    else
2032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2033b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (fromDate <= date)
2034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        {
2035b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            currIndex++;
2036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            if (currIndex == index)
2037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            {
2038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                matchFound = true;
2039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            }
2040b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
2041b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2042b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2043b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // close open resources
2044b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(currencyRes);
2045b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(fromRes);
2046b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2047b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // check for loop exit
2048b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (matchFound)
2049b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        break;
2051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2052b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2053b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } // end For loop
2054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2056b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(countryArray);
2057b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Check for errors
2059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR)
2060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // There is nothing to fallback to.
2062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Report the failure/warning if possible.
2063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *ec = localStatus;
2064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_SUCCESS(*ec))
2067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2068b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // no errors
2069b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if((buffCapacity> resLen) && matchFound)
2070b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2071b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // write out the currency value
2072b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    u_strcpy(buff, s);
2073b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2074b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                else
2075b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2076b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    return 0;
2077b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // return null terminated currency string
2081c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return u_terminateUChars(buff, buffCapacity, resLen, ec);
2082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        else
2084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // illegal argument encountered
2086c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *ec = U_ILLEGAL_ARGUMENT_ERROR;
2087c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
2088c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2089c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2090c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we got here, either error code is invalid or
2092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // some argument passed is no good.
2093c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return resLen;
2094c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2095c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UEnumeration defaultKeywordValues = {
2097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    NULL,
2098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    NULL,
2099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_close_keyword_values_iterator,
2100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_count_keyword_values,
2101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uenum_unextDefault,
2102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_next_keyword_value,
2103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_reset_keyword_values_iterator
2104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru};
2105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) {
2107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Resolve region
2108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char prefRegion[ULOC_FULLNAME_CAPACITY] = "";
2109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t prefRegionLength = 0;
2110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    prefRegionLength = uloc_getCountry(locale, prefRegion, sizeof(prefRegion), status);
2111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (prefRegionLength == 0) {
2112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        char loc[ULOC_FULLNAME_CAPACITY] = "";
2113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t locLength = 0;
2114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        locLength = uloc_addLikelySubtags(locale, loc, sizeof(loc), status);
2115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        prefRegionLength = uloc_getCountry(loc, prefRegion, sizeof(prefRegion), status);
2117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Read value from supplementalData
2120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UList *values = ulist_createEmptyList(status);
2121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UList *otherValues = ulist_createEmptyList(status);
2122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
2123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(*status) || en == NULL) {
2124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (en == NULL) {
2125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
2126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
2127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_free(en);
2128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_deleteList(values);
2130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_deleteList(otherValues);
2131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
2132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
2134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    en->context = values;
2135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
213650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *bundle = ures_openDirect(U_ICUDATA_CURR, "supplementalData", status);
2137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_getByKey(bundle, "CurrencyMap", bundle, status);
2138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UResourceBundle bundlekey, regbndl, curbndl, to;
2139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&bundlekey);
2140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&regbndl);
2141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&curbndl);
2142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&to);
2143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    while (U_SUCCESS(*status) && ures_hasNext(bundle)) {
2145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_getNextResource(bundle, &bundlekey, status);
2146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(*status)) {
2147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
2148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        const char *region = ures_getKey(&bundlekey);
2150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UBool isPrefRegion = uprv_strcmp(region, prefRegion) == 0 ? TRUE : FALSE;
2151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (!isPrefRegion && commonlyUsed) {
2152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // With commonlyUsed=true, we do not put
215350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // currencies for other regions in the
2154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // result list.
2155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            continue;
2156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_getByKey(bundle, region, &regbndl, status);
2158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(*status)) {
2159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
2160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        while (U_SUCCESS(*status) && ures_hasNext(&regbndl)) {
2162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_getNextResource(&regbndl, &curbndl, status);
2163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (ures_getType(&curbndl) != URES_TABLE) {
2164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Currently, an empty ARRAY is mixed in.
2165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                continue;
2166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            char *curID = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY);
2168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t curIDLength = ULOC_KEYWORDS_CAPACITY;
2169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (curID == NULL) {
2170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *status = U_MEMORY_ALLOCATION_ERROR;
2171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                break;
2172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
217350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
217450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if U_CHARSET_FAMILY==U_ASCII_FAMILY
2175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_getUTF8StringByKey(&curbndl, "id", curID, &curIDLength, TRUE, status);
217650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* optimize - use the utf-8 string */
217750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
217850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            {
217950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       const UChar* defString = ures_getStringByKey(&curbndl, "id", &curIDLength, status);
218050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       if(U_SUCCESS(*status)) {
218150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			   if(curIDLength+1 > ULOC_KEYWORDS_CAPACITY) {
218250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho				*status = U_BUFFER_OVERFLOW_ERROR;
218350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			   } else {
218450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                           	u_UCharsToChars(defString, curID, curIDLength+1);
218550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			   }
218650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       }
218750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
218850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
218950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_FAILURE(*status)) {
2191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                break;
2192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UBool hasTo = FALSE;
2194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_getByKey(&curbndl, "to", &to, status);
2195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_FAILURE(*status)) {
2196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Do nothing here...
2197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *status = U_ZERO_ERROR;
2198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
2199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                hasTo = TRUE;
2200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
220150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (isPrefRegion && !hasTo && !ulist_containsString(values, curID, (int32_t)uprv_strlen(curID))) {
2202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Currently active currency for the target country
2203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ulist_addItemEndList(values, curID, TRUE, status);
220450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } else if (!ulist_containsString(otherValues, curID, (int32_t)uprv_strlen(curID)) && !commonlyUsed) {
2205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ulist_addItemEndList(otherValues, curID, TRUE, status);
2206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
2207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uprv_free(curID);
2208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_SUCCESS(*status)) {
2213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (commonlyUsed) {
2214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (ulist_getListSize(values) == 0) {
2215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // This could happen if no valid region is supplied in the input
2216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // locale. In this case, we use the CLDR's default.
2217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uenum_close(en);
2218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                en = ucurr_getKeywordValuesForLocale(key, "und", TRUE, status);
2219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
2221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Consolidate the list
2222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            char *value = NULL;
2223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ulist_resetList(otherValues);
2224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            while ((value = (char *)ulist_getNext(otherValues)) != NULL) {
222550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (!ulist_containsString(values, value, (int32_t)uprv_strlen(value))) {
2226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    char *tmpValue = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY);
2227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    uprv_memcpy(tmpValue, value, uprv_strlen(value) + 1);
2228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ulist_addItemEndList(values, tmpValue, TRUE, status);
2229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (U_FAILURE(*status)) {
2230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        break;
2231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_resetList((UList *)(en->context));
2237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else {
2238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_deleteList(values);
2239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_free(en);
2240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        values = NULL;
2241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        en = NULL;
2242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&to);
2244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&curbndl);
2245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&regbndl);
2246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&bundlekey);
2247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(bundle);
2248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_deleteList(otherValues);
2250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return en;
2252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
2253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
2255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
2257