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