1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius* Copyright (c) 2002-2013, 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"
2659d709d503bab6e2b61931737e662dd293b40578ccornelius#include "hash.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h"
28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "ulist.h"
2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ureslocs.h"
30b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
3159d709d503bab6e2b61931737e662dd293b40578ccornelius//#define UCURR_DEBUG_EQUIV 1
3259d709d503bab6e2b61931737e662dd293b40578ccornelius#ifdef UCURR_DEBUG_EQUIV
3359d709d503bab6e2b61931737e662dd293b40578ccornelius#include "stdio.h"
3459d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
3559d709d503bab6e2b61931737e662dd293b40578ccornelius//#define UCURR_DEBUG 1
36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "stdio.h"
38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct IsoCodeEntry {
41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *isoCode; /* const because it's a reference to a resource bundle string. */
42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UDate from;
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UDate to;
44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} IsoCodeEntry;
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Constants
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Default currency meta data of last resort.  We try to use the
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// defaults encoded in the meta data resource bundle.  If there is a
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// configuration/build error and these are not available, we use these
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// hard-coded defaults (which should be identical).
5359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic const int32_t LAST_RESORT_DATA[] = { 2, 0, 2, 0 };
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// POW10[i] = 10^i, i=0..MAX_POW10
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t POW10[] = { 1, 10, 100, 1000, 10000, 100000,
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 1000000, 10000000, 100000000, 1000000000 };
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t MAX_POW10 = (sizeof(POW10)/sizeof(POW10[0])) - 1;
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
6159d709d503bab6e2b61931737e662dd293b40578ccornelius// Defines equivalent currency symbols.
6259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic const char *EQUIV_CURRENCY_SYMBOLS[][2] = {
6359d709d503bab6e2b61931737e662dd293b40578ccornelius    {"\\u00a5", "\\uffe5"},
6459d709d503bab6e2b61931737e662dd293b40578ccornelius    {"$", "\\ufe69"},
6559d709d503bab6e2b61931737e662dd293b40578ccornelius    {"$", "\\uff04"},
6659d709d503bab6e2b61931737e662dd293b40578ccornelius    {"\\u20a8", "\\u20b9"},
6759d709d503bab6e2b61931737e662dd293b40578ccornelius    {"\\u00a3", "\\u20a4"}};
6859d709d503bab6e2b61931737e662dd293b40578ccornelius
69103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#define ISO_CURRENCY_CODE_LENGTH 3
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Resource tags
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCY_DATA[] = "supplementalData";
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for meta-data, in root.
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCY_META[] = "CurrencyMeta";
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for map from countries to currencies, in root.
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCY_MAP[] = "CurrencyMap";
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for default meta-data, in CURRENCY_META
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DEFAULT_META[] = "DEFAULT";
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant for legacy pre-euro mapping in CurrencyMap
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_PRE_EURO[] = "PREEURO";
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant for legacy euro mapping in CurrencyMap
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_EURO[] = "EURO";
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant delimiter
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_DELIM = '_';
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char VAR_DELIM_STR[] = "_";
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Variant for legacy euro mapping in CurrencyMap
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//static const char VAR_DELIM_EURO[] = "_EURO";
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define VARIANT_IS_EMPTY    0
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define VARIANT_IS_EURO     0x1
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define VARIANT_IS_PREEURO  0x2
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Tag for localized display names (symbols) of currencies
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char CURRENCIES[] = "Currencies";
104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char CURRENCYPLURALS[] = "CurrencyPlurals";
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Marker character indicating that a display name is a ChoiceFormat
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// pattern.  Strings that start with one mark are ChoiceFormat
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// patterns.  Strings that start with 2 marks are static strings, and
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the first mark is deleted.
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar CHOICE_FORMAT_MARK = 0x003D; // Equals sign
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0};
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ISO codes mapping table
11559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic const UHashtable* gIsoCodes = NULL;
11659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gIsoCodesInitOnce = U_INITONCE_INITIALIZER;
11759d709d503bab6e2b61931737e662dd293b40578ccornelius
11859d709d503bab6e2b61931737e662dd293b40578ccornelius// Currency symbol equivalances
11959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic const icu::Hashtable* gCurrSymbolsEquiv = NULL;
12059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCurrSymbolsEquivInitOnce = U_INITONCE_INITIALIZER;
12159d709d503bab6e2b61931737e662dd293b40578ccornelius
12259d709d503bab6e2b61931737e662dd293b40578ccornelius// EquivIterator iterates over all strings that are equivalent to a given
12359d709d503bab6e2b61931737e662dd293b40578ccornelius// string, s. Note that EquivIterator will never yield s itself.
12459d709d503bab6e2b61931737e662dd293b40578ccorneliusclass EquivIterator : icu::UMemory {
12559d709d503bab6e2b61931737e662dd293b40578ccorneliuspublic:
12659d709d503bab6e2b61931737e662dd293b40578ccornelius    // Constructor. hash stores the equivalence relationships; s is the string
12759d709d503bab6e2b61931737e662dd293b40578ccornelius    // for which we find equivalent strings.
12859d709d503bab6e2b61931737e662dd293b40578ccornelius    inline EquivIterator(const icu::Hashtable& hash, const icu::UnicodeString& s)
12959d709d503bab6e2b61931737e662dd293b40578ccornelius        : _hash(hash) {
13059d709d503bab6e2b61931737e662dd293b40578ccornelius        _start = _current = &s;
13159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
13259d709d503bab6e2b61931737e662dd293b40578ccornelius    inline ~EquivIterator() { }
13359d709d503bab6e2b61931737e662dd293b40578ccornelius
13459d709d503bab6e2b61931737e662dd293b40578ccornelius    // next returns the next equivalent string or NULL if there are no more.
13559d709d503bab6e2b61931737e662dd293b40578ccornelius    // If s has no equivalent strings, next returns NULL on the first call.
13659d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString *next();
13759d709d503bab6e2b61931737e662dd293b40578ccorneliusprivate:
13859d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::Hashtable& _hash;
13959d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString* _start;
14059d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString* _current;
14159d709d503bab6e2b61931737e662dd293b40578ccornelius};
14259d709d503bab6e2b61931737e662dd293b40578ccornelius
14359d709d503bab6e2b61931737e662dd293b40578ccorneliusconst icu::UnicodeString *
14459d709d503bab6e2b61931737e662dd293b40578ccorneliusEquivIterator::next() {
14559d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString* _next = (const icu::UnicodeString*) _hash.get(*_current);
14659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (_next == NULL) {
14759d709d503bab6e2b61931737e662dd293b40578ccornelius        U_ASSERT(_current == _start);
14859d709d503bab6e2b61931737e662dd293b40578ccornelius        return NULL;
14959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
15059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (*_next == *_start) {
15159d709d503bab6e2b61931737e662dd293b40578ccornelius        return NULL;
15259d709d503bab6e2b61931737e662dd293b40578ccornelius    }
15359d709d503bab6e2b61931737e662dd293b40578ccornelius    _current = _next;
15459d709d503bab6e2b61931737e662dd293b40578ccornelius    return _next;
15559d709d503bab6e2b61931737e662dd293b40578ccornelius}
15659d709d503bab6e2b61931737e662dd293b40578ccornelius
15759d709d503bab6e2b61931737e662dd293b40578ccornelius// makeEquivalent makes lhs and rhs equivalent by updating the equivalence
15859d709d503bab6e2b61931737e662dd293b40578ccornelius// relations in hash accordingly.
15959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void makeEquivalent(
16059d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString &lhs,
16159d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString &rhs,
16259d709d503bab6e2b61931737e662dd293b40578ccornelius    icu::Hashtable* hash, UErrorCode &status) {
16359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
16459d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
16559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
16659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (lhs == rhs) {
16759d709d503bab6e2b61931737e662dd293b40578ccornelius        // already equivalent
16859d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
16959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
17059d709d503bab6e2b61931737e662dd293b40578ccornelius    EquivIterator leftIter(*hash, lhs);
17159d709d503bab6e2b61931737e662dd293b40578ccornelius    EquivIterator rightIter(*hash, rhs);
17259d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString *firstLeft = leftIter.next();
17359d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString *firstRight = rightIter.next();
17459d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString *nextLeft = firstLeft;
17559d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::UnicodeString *nextRight = firstRight;
17659d709d503bab6e2b61931737e662dd293b40578ccornelius    while (nextLeft != NULL && nextRight != NULL) {
17759d709d503bab6e2b61931737e662dd293b40578ccornelius        if (*nextLeft == rhs || *nextRight == lhs) {
17859d709d503bab6e2b61931737e662dd293b40578ccornelius            // Already equivalent
17959d709d503bab6e2b61931737e662dd293b40578ccornelius            return;
18059d709d503bab6e2b61931737e662dd293b40578ccornelius        }
18159d709d503bab6e2b61931737e662dd293b40578ccornelius        nextLeft = leftIter.next();
18259d709d503bab6e2b61931737e662dd293b40578ccornelius        nextRight = rightIter.next();
18359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
18459d709d503bab6e2b61931737e662dd293b40578ccornelius    // Not equivalent. Must join.
18559d709d503bab6e2b61931737e662dd293b40578ccornelius    icu::UnicodeString *newFirstLeft;
18659d709d503bab6e2b61931737e662dd293b40578ccornelius    icu::UnicodeString *newFirstRight;
18759d709d503bab6e2b61931737e662dd293b40578ccornelius    if (firstRight == NULL && firstLeft == NULL) {
18859d709d503bab6e2b61931737e662dd293b40578ccornelius        // Neither lhs or rhs belong to an equivalence circle, so we form
18959d709d503bab6e2b61931737e662dd293b40578ccornelius        // a new equivalnce circle of just lhs and rhs.
19059d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstLeft = new icu::UnicodeString(rhs);
19159d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstRight = new icu::UnicodeString(lhs);
19259d709d503bab6e2b61931737e662dd293b40578ccornelius    } else if (firstRight == NULL) {
19359d709d503bab6e2b61931737e662dd293b40578ccornelius        // lhs belongs to an equivalence circle, but rhs does not, so we link
19459d709d503bab6e2b61931737e662dd293b40578ccornelius        // rhs into lhs' circle.
19559d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstLeft = new icu::UnicodeString(rhs);
19659d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstRight = new icu::UnicodeString(*firstLeft);
19759d709d503bab6e2b61931737e662dd293b40578ccornelius    } else if (firstLeft == NULL) {
19859d709d503bab6e2b61931737e662dd293b40578ccornelius        // rhs belongs to an equivlance circle, but lhs does not, so we link
19959d709d503bab6e2b61931737e662dd293b40578ccornelius        // lhs into rhs' circle.
20059d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstLeft = new icu::UnicodeString(*firstRight);
20159d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstRight = new icu::UnicodeString(lhs);
20259d709d503bab6e2b61931737e662dd293b40578ccornelius    } else {
20359d709d503bab6e2b61931737e662dd293b40578ccornelius        // Both lhs and rhs belong to different equivalnce circles. We link
20459d709d503bab6e2b61931737e662dd293b40578ccornelius        // them together to form one single, larger equivalnce circle.
20559d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstLeft = new icu::UnicodeString(*firstRight);
20659d709d503bab6e2b61931737e662dd293b40578ccornelius        newFirstRight = new icu::UnicodeString(*firstLeft);
20759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
20859d709d503bab6e2b61931737e662dd293b40578ccornelius    if (newFirstLeft == NULL || newFirstRight == NULL) {
20959d709d503bab6e2b61931737e662dd293b40578ccornelius        delete newFirstLeft;
21059d709d503bab6e2b61931737e662dd293b40578ccornelius        delete newFirstRight;
21159d709d503bab6e2b61931737e662dd293b40578ccornelius        status = U_MEMORY_ALLOCATION_ERROR;
21259d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
21359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
21459d709d503bab6e2b61931737e662dd293b40578ccornelius    hash->put(lhs, (void *) newFirstLeft, status);
21559d709d503bab6e2b61931737e662dd293b40578ccornelius    hash->put(rhs, (void *) newFirstRight, status);
21659d709d503bab6e2b61931737e662dd293b40578ccornelius}
21759d709d503bab6e2b61931737e662dd293b40578ccornelius
21859d709d503bab6e2b61931737e662dd293b40578ccornelius// countEquivalent counts how many strings are equivalent to s.
21959d709d503bab6e2b61931737e662dd293b40578ccornelius// hash stores all the equivalnce relations.
22059d709d503bab6e2b61931737e662dd293b40578ccornelius// countEquivalent does not include s itself in the count.
22159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic int32_t countEquivalent(const icu::Hashtable &hash, const icu::UnicodeString &s) {
22259d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t result = 0;
22359d709d503bab6e2b61931737e662dd293b40578ccornelius    EquivIterator iter(hash, s);
22459d709d503bab6e2b61931737e662dd293b40578ccornelius    while (iter.next() != NULL) {
22559d709d503bab6e2b61931737e662dd293b40578ccornelius        ++result;
22659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
22759d709d503bab6e2b61931737e662dd293b40578ccornelius#ifdef UCURR_DEBUG_EQUIV
22859d709d503bab6e2b61931737e662dd293b40578ccornelius {
22959d709d503bab6e2b61931737e662dd293b40578ccornelius   char tmp[200];
23059d709d503bab6e2b61931737e662dd293b40578ccornelius   s.extract(0,s.length(),tmp, "UTF-8");
23159d709d503bab6e2b61931737e662dd293b40578ccornelius   printf("CountEquivalent('%s') = %d\n", tmp, result);
23259d709d503bab6e2b61931737e662dd293b40578ccornelius }
23359d709d503bab6e2b61931737e662dd293b40578ccornelius#endif
23459d709d503bab6e2b61931737e662dd293b40578ccornelius    return result;
23559d709d503bab6e2b61931737e662dd293b40578ccornelius}
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
23759d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic const icu::Hashtable* getCurrSymbolsEquiv();
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Code
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Cleanup callback func
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool U_CALLCONV
246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoisoCodes_cleanup(void)
247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (gIsoCodes != NULL) {
24959d709d503bab6e2b61931737e662dd293b40578ccornelius        uhash_close(const_cast<UHashtable *>(gIsoCodes));
250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        gIsoCodes = NULL;
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
25259d709d503bab6e2b61931737e662dd293b40578ccornelius    gIsoCodesInitOnce.reset();
25359d709d503bab6e2b61931737e662dd293b40578ccornelius    return TRUE;
25459d709d503bab6e2b61931737e662dd293b40578ccornelius}
255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
25659d709d503bab6e2b61931737e662dd293b40578ccornelius/**
25759d709d503bab6e2b61931737e662dd293b40578ccornelius * Cleanup callback func
25859d709d503bab6e2b61931737e662dd293b40578ccornelius */
25959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UBool U_CALLCONV
26059d709d503bab6e2b61931737e662dd293b40578ccorneliuscurrSymbolsEquiv_cleanup(void)
26159d709d503bab6e2b61931737e662dd293b40578ccornelius{
26259d709d503bab6e2b61931737e662dd293b40578ccornelius    delete const_cast<icu::Hashtable *>(gCurrSymbolsEquiv);
26359d709d503bab6e2b61931737e662dd293b40578ccornelius    gCurrSymbolsEquiv = NULL;
26459d709d503bab6e2b61931737e662dd293b40578ccornelius    gCurrSymbolsEquivInitOnce.reset();
265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for OlsonToMetaMappingEntry
270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteIsoCodeEntry(void *obj) {
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    IsoCodeEntry *entry = (IsoCodeEntry*)obj;
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(entry);
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
27859d709d503bab6e2b61931737e662dd293b40578ccornelius * Deleter for gCurrSymbolsEquiv.
27959d709d503bab6e2b61931737e662dd293b40578ccornelius */
28059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV
28159d709d503bab6e2b61931737e662dd293b40578ccorneliusdeleteUnicode(void *obj) {
28259d709d503bab6e2b61931737e662dd293b40578ccornelius    icu::UnicodeString *entry = (icu::UnicodeString*)obj;
28359d709d503bab6e2b61931737e662dd293b40578ccornelius    delete entry;
28459d709d503bab6e2b61931737e662dd293b40578ccornelius}
28559d709d503bab6e2b61931737e662dd293b40578ccornelius
28659d709d503bab6e2b61931737e662dd293b40578ccornelius/**
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Unfortunately, we have to convert the UChar* currency code to char*
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to use it as a resource key.
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic inline char*
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerumyUCharsToChars(char* resultOfLen4, const UChar* currency) {
292103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    u_UCharsToChars(currency, resultOfLen4, ISO_CURRENCY_CODE_LENGTH);
293103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    resultOfLen4[ISO_CURRENCY_CODE_LENGTH] = 0;
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return resultOfLen4;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Internal function to look up currency data.  Result is an array of
29959d709d503bab6e2b61931737e662dd293b40578ccornelius * four integers.  The first is the fraction digits.  The second is the
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * rounding increment, or 0 if none.  The rounding increment is in
30159d709d503bab6e2b61931737e662dd293b40578ccornelius * units of 10^(-fraction_digits).  The third and fourth are the same
30259d709d503bab6e2b61931737e662dd293b40578ccornelius * except that they are those used in cash transations ( cashDigits
30359d709d503bab6e2b61931737e662dd293b40578ccornelius * and cashRounding ).
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t*
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru_findMetaData(const UChar* currency, UErrorCode& ec) {
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (currency == 0 || *currency == 0) {
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ec = U_ILLEGAL_ARGUMENT_ERROR;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return LAST_RESORT_DATA;
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Get CurrencyMeta resource out of root locale file.  [This may
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // move out of the root locale file later; if it does, update this
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // code.]
31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle* currencyData = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &ec);
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle* currencyMeta = ures_getByKey(currencyData, CURRENCY_META, currencyData, &ec);
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(currencyMeta);
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Config/build error; return hard-coded defaults
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return LAST_RESORT_DATA;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Look up our currency, or if that's not available, then DEFAULT
328103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char buf[ISO_CURRENCY_CODE_LENGTH+1];
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR; // local error code: soft failure
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle* rb = ures_getByKey(currencyMeta, myUCharsToChars(buf, currency), NULL, &ec2);
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if (U_FAILURE(ec2)) {
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(rb);
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        rb = ures_getByKey(currencyMeta,DEFAULT_META, NULL, &ec);
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(ec)) {
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(currencyMeta);
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(rb);
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Config/build error; return hard-coded defaults
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return LAST_RESORT_DATA;
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t *data = ures_getIntVector(rb, &len, &ec);
34459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(ec) || len != 4) {
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Config/build error; return hard-coded defaults
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ec = U_INVALID_FORMAT_ERROR;
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(currencyMeta);
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(rb);
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return LAST_RESORT_DATA;
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(currencyMeta);
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(rb);
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return data;
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @see VARIANT_IS_EURO
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @see VARIANT_IS_PREEURO
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint32_t
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruidForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCode* ec)
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t variantType = 0;
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // !!! this is internal only, assumes buffer is not null and capacity is sufficient
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Extract the country name and variant name.  We only
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // recognize two variant names, EURO and PREEURO.
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char variant[ULOC_FULLNAME_CAPACITY];
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getCountry(locale, countryAndVariant, capacity, ec);
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getVariant(locale, variant, sizeof(variant), ec);
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (variant[0] != 0) {
37654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        variantType = (uint32_t)(0 == uprv_strcmp(variant, VAR_EURO))
37754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                   | ((uint32_t)(0 == uprv_strcmp(variant, VAR_PRE_EURO)) << 1);
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (variantType)
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(countryAndVariant, VAR_DELIM_STR);
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_strcat(countryAndVariant, variant);
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return variantType;
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------------
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Registration
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//-------------------------------------------
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// don't use ICUService since we don't need fallback
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV currency_cleanup(void);
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if !UCONFIG_NO_SERVICE
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct CReg;
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gCRegLock = U_MUTEX_INITIALIZER;
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic CReg* gCRegHead = 0;
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
405103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstruct CReg : public icu::UMemory {
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CReg *next;
407103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UChar iso[ISO_CURRENCY_CODE_LENGTH+1];
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char  id[ULOC_FULLNAME_CAPACITY];
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CReg(const UChar* _iso, const char* _id)
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        : next(0)
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t len = (int32_t)uprv_strlen(_id);
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (len > (int32_t)(sizeof(id)-1)) {
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            len = (sizeof(id)-1);
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_strncpy(id, _id, len);
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        id[len] = 0;
419103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uprv_memcpy(iso, _iso, ISO_CURRENCY_CODE_LENGTH * sizeof(const UChar));
420103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        iso[ISO_CURRENCY_CODE_LENGTH] = 0;
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UCurrRegistryKey reg(const UChar* _iso, const char* _id, UErrorCode* status)
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (status && U_SUCCESS(*status) && _iso && _id) {
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            CReg* n = new CReg(_iso, _id);
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (n) {
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                umtx_lock(&gCRegLock);
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (!gCRegHead) {
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* register for the first time */
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                n->next = gCRegHead;
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                gCRegHead = n;
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                umtx_unlock(&gCRegLock);
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return n;
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UBool unreg(UCurrRegistryKey key) {
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool found = FALSE;
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&gCRegLock);
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CReg** p = &gCRegHead;
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (*p) {
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (*p == key) {
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *p = ((CReg*)key)->next;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete (CReg*)key;
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                found = TRUE;
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            p = &((*p)->next);
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&gCRegLock);
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return found;
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const UChar* get(const char* id) {
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar* result = NULL;
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_lock(&gCRegLock);
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        CReg* p = gCRegHead;
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* register cleanup of the mutex */
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (p) {
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (uprv_strcmp(id, p->id) == 0) {
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result = p->iso;
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            p = p->next;
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        umtx_unlock(&gCRegLock);
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return result;
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* This doesn't need to be thread safe. It's for u_cleanup only. */
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static void cleanup(void) {
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (gCRegHead) {
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            CReg* n = gCRegHead;
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            gCRegHead = gCRegHead->next;
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete n;
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UCurrRegistryKey U_EXPORT2
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_register(const UChar* isoCode, const char* locale, UErrorCode *status)
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (status && U_SUCCESS(*status)) {
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        char id[ULOC_FULLNAME_CAPACITY];
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        idForLocale(locale, id, sizeof(id), status);
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return CReg::reg(isoCode, id, status);
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBool U_EXPORT2
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_unregister(UCurrRegistryKey key, UErrorCode* status)
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (status && U_SUCCESS(*status)) {
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return CReg::unreg(key);
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* UCONFIG_NO_SERVICE */
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Release all static memory held by currency.
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*The declaration here is needed so currency_cleanup(void)
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * can call this function.
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool U_CALLCONV
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehocurrency_cache_cleanup(void);
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool U_CALLCONV currency_cleanup(void) {
528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if !UCONFIG_NO_SERVICE
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CReg::cleanup();
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif
531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    /*
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     * There might be some cached currency data or isoCodes data.
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho     */
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    currency_cache_cleanup();
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    isoCodes_cleanup();
53659d709d503bab6e2b61931737e662dd293b40578ccornelius    currSymbolsEquiv_cleanup();
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// -------------------------------------
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_forLocale(const char* locale,
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UChar* buff,
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t buffCapacity,
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode* ec)
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t resLen = 0;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* s = NULL;
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (ec != NULL && U_SUCCESS(*ec)) {
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((buff && buffCapacity) || !buffCapacity) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UErrorCode localStatus = U_ZERO_ERROR;
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            char id[ULOC_FULLNAME_CAPACITY];
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) {
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // there is a currency keyword. Try to see if it's valid
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(buffCapacity > resLen) {
55927f654740f2a26ad62a5c155af9199af9e69b889claireho                    /* Normalize the currency keyword value to upper case. */
56027f654740f2a26ad62a5c155af9199af9e69b889claireho                    T_CString_toUpperCase(id);
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    u_charsToUChars(id, buff, resLen);
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // get country or country_variant in `id'
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uint32_t variantType = idForLocale(locale, id, sizeof(id), ec);
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(*ec)) {
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return 0;
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const UChar* result = CReg::get(id);
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (result) {
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(buffCapacity > u_strlen(result)) {
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        u_strcpy(buff, result);
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return u_strlen(result);
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Remove variants, which is only needed for registration.
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                char *idDelim = strchr(id, VAR_DELIM);
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (idDelim) {
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    idDelim[0] = 0;
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // Look up the CurrencyMap element in the root bundle.
58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus);
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /*
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                Get the second item when PREEURO is requested, and this is a known Euro country.
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                If the requested variant is PREEURO, and this isn't a Euro country, assume
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                that the country changed over to the Euro in the future. This is probably
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                an old version of ICU that hasn't been updated yet. The latest currency is
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                probably correct.
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                */
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_SUCCESS(localStatus)) {
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) {
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus);
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus);
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    else if ((variantType & VARIANT_IS_EURO)) {
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        s = EUR_STR;
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ures_close(countryArray);
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ures_close(currencyReq);
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0)
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                {
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // We don't know about it.  Check to see if we support the variant.
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uloc_getParent(locale, id, sizeof(id), ec);
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *ec = U_USING_FALLBACK_WARNING;
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return ucurr_forLocale(id, buff, buffCapacity, ec);
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) {
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // There is nothing to fallback to. Report the failure/warning if possible.
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *ec = localStatus;
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_SUCCESS(*ec)) {
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(buffCapacity > resLen) {
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        u_strcpy(buff, s);
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return u_terminateUChars(buff, buffCapacity, resLen, ec);
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *ec = U_ILLEGAL_ARGUMENT_ERROR;
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return resLen;
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// end registration
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Modify the given locale name by removing the rightmost _-delimited
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * element.  If there is none, empty the string ("" == root).
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * NOTE: The string "root" is not recognized; do not use it.
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return TRUE if the fallback happened; FALSE if locale is already
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * root ("").
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool fallback(char *loc) {
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!*loc) {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getParent(loc, loc, (int32_t)uprv_strlen(loc), &status);
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /*
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char *i = uprv_strrchr(loc, '_');
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (i == NULL) {
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        i = loc;
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *i = 0;
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const UChar* U_EXPORT2
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_getName(const UChar* currency,
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              const char* locale,
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UCurrNameStyle nameStyle,
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UBool* isChoiceFormat, // fillin
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t* len, // fillin
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UErrorCode* ec) {
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Look up the Currencies resource for the given locale.  The
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currencies locale data looks like this:
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|en {
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|  Currencies {
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    USD { "US$", "US Dollar" }
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    CHF { "Sw F", "Swiss Franc" }
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|    //...
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|  }
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(*ec)) {
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t choice = (int32_t) nameStyle;
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (choice < 0 || choice > 1) {
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *ec = U_ILLEGAL_ARGUMENT_ERROR;
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // In the future, resource bundles may implement multi-level
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // fallback.  That is, if a currency is not found in the en_US
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currencies data, then the en Currencies data will be searched.
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currently, if a Currencies datum exists in en_US and en, the
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // en_US entry hides that in en.
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We want multi-level fallback for this resource, so we implement
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // it manually.
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Use a separate UErrorCode here that does not propagate out of
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this function.
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR;
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char loc[ULOC_FULLNAME_CAPACITY];
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getName(locale, loc, sizeof(loc), &ec2);
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) {
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *ec = U_ILLEGAL_ARGUMENT_ERROR;
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
712103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char buf[ISO_CURRENCY_CODE_LENGTH+1];
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myUCharsToChars(buf, currency);
71427f654740f2a26ad62a5c155af9199af9e69b889claireho
71527f654740f2a26ad62a5c155af9199af9e69b889claireho    /* Normalize the keyword value to uppercase */
71627f654740f2a26ad62a5c155af9199af9e69b889claireho    T_CString_toUpperCase(buf);
71727f654740f2a26ad62a5c155af9199af9e69b889claireho
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* s = NULL;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ec2 = U_ZERO_ERROR;
72050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rb = ures_getByKey(rb, CURRENCIES, rb, &ec2);
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Fetch resource with multi-level resource inheritance fallback
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rb = ures_getByKeyWithFallback(rb, buf, rb, &ec2);
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    s = ures_getStringByIndex(rb, choice, len, &ec2);
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(rb);
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we've succeeded we're done.  Otherwise, try to fallback.
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If that fails (because we are already at root) then exit.
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec2)) {
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (ec2 == U_USING_DEFAULT_WARNING
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            || (ec2 == U_USING_FALLBACK_WARNING && *ec != U_USING_DEFAULT_WARNING)) {
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *ec = ec2;
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Determine if this is a ChoiceFormat pattern.  One leading mark
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // indicates a ChoiceFormat.  Two indicates a static string that
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // starts with a mark.  In either case, the first mark is ignored,
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // if present.  Marks in the rest of the string have no special
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // meaning.
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *isChoiceFormat = FALSE;
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec2)) {
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_ASSERT(s != NULL);
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i=0;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (i < *len && s[i] == CHOICE_FORMAT_MARK && i < 2) {
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++i;
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *isChoiceFormat = (i == 1);
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (i != 0) ++s; // Skip over first mark
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return s;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we fail to find a match, use the ISO 4217 code
757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    *len = u_strlen(currency); // Should == ISO_CURRENCY_CODE_LENGTH, but maybe not...?
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *ec = U_USING_DEFAULT_WARNING;
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return currency;
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
762b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI const UChar* U_EXPORT2
763b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruucurr_getPluralName(const UChar* currency,
764b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const char* locale,
765b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UBool* isChoiceFormat,
766b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const char* pluralCount,
767b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t* len, // fillin
768b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UErrorCode* ec) {
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Look up the Currencies resource for the given locale.  The
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Currencies locale data looks like this:
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|en {
772b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|  CurrencyPlurals {
773b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|    USD{
774b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|      one{"US dollar"}
775b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|      other{"US dollars"}
776b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //|    }
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|  }
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //|}
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
780b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(*ec)) {
781b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 0;
782b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Use a separate UErrorCode here that does not propagate out of
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // this function.
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR;
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char loc[ULOC_FULLNAME_CAPACITY];
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uloc_getName(locale, loc, sizeof(loc), &ec2);
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) {
791b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *ec = U_ILLEGAL_ARGUMENT_ERROR;
792b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 0;
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
795103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    char buf[ISO_CURRENCY_CODE_LENGTH+1];
796b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    myUCharsToChars(buf, currency);
797b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* s = NULL;
799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ec2 = U_ZERO_ERROR;
80050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2);
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
802b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    rb = ures_getByKey(rb, CURRENCYPLURALS, rb, &ec2);
803b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
804b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Fetch resource with multi-level resource inheritance fallback
805b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    rb = ures_getByKeyWithFallback(rb, buf, rb, &ec2);
806b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
807b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    s = ures_getStringByKeyWithFallback(rb, pluralCount, len, &ec2);
808b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec2)) {
809b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        //  fall back to "other"
810b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ec2 = U_ZERO_ERROR;
811b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        s = ures_getStringByKeyWithFallback(rb, "other", len, &ec2);
812b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(ec2)) {
813b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(rb);
814b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // fall back to long name in Currencies
815b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return ucurr_getName(currency, locale, UCURR_LONG_NAME,
816b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                 isChoiceFormat, len, ec);
817b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
818b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
819b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(rb);
820b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we've succeeded we're done.  Otherwise, try to fallback.
822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If that fails (because we are already at root) then exit.
823b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_SUCCESS(ec2)) {
824b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (ec2 == U_USING_DEFAULT_WARNING
825b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            || (ec2 == U_USING_FALLBACK_WARNING && *ec != U_USING_DEFAULT_WARNING)) {
826b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *ec = ec2;
827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
828b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        U_ASSERT(s != NULL);
829b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return s;
830b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
831b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
832b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we fail to find a match, use the ISO 4217 code
833103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    *len = u_strlen(currency); // Should == ISO_CURRENCY_CODE_LENGTH, but maybe not...?
834b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *ec = U_USING_DEFAULT_WARNING;
835b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return currency;
836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
837b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
838b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
839b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================================================================
840b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Following are structure and function for parsing currency names
841b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
842b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define NEED_TO_BE_DELETED 0x1
843b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
844b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// TODO: a better way to define this?
845b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX_CURRENCY_NAME_LEN 100
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
847b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct {
848b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const char* IsoCode;  // key
849b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar* currencyName;  // value
850b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t currencyNameLen;  // value length
851b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t flag;  // flags
852b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} CurrencyNameStruct;
853b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
854b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
855b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifndef MIN
856b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MIN(a,b) (((a)<(b)) ? (a) : (b))
857b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
858b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
859b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifndef MAX
860b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define MAX(a,b) (((a)<(b)) ? (b) : (a))
861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Comparason function used in quick sort.
86550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int U_CALLCONV currencyNameComparator(const void* a, const void* b) {
866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const CurrencyNameStruct* currName_1 = (const CurrencyNameStruct*)a;
867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const CurrencyNameStruct* currName_2 = (const CurrencyNameStruct*)b;
868b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t i = 0;
869b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru         i < MIN(currName_1->currencyNameLen, currName_2->currencyNameLen);
870b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru         ++i) {
871b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currName_1->currencyName[i] < currName_2->currencyName[i]) {
872b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return -1;
873b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
874b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currName_1->currencyName[i] > currName_2->currencyName[i]) {
875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return 1;
876b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
877b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
878b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (currName_1->currencyNameLen < currName_2->currencyNameLen) {
879b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return -1;
880b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if (currName_1->currencyNameLen > currName_2->currencyNameLen) {
881b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return 1;
882b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
883b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return 0;
884b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
885b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
886b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
887b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Give a locale, return the maximum number of currency names associated with
888b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// this locale.
889b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// It gets currency names from resource bundles using fallback.
890b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// It is the maximum number because in the fallback chain, some of the
891b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// currency names are duplicated.
892b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// For example, given locale as "en_US", the currency names get from resource
893b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// bundle in "en_US" and "en" are duplicated. The fallback mechanism will count
894b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// all currency names in "en_US" and "en".
895b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
896b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerugetCurrencyNameCount(const char* loc, int32_t* total_currency_name_count, int32_t* total_currency_symbol_count) {
89750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    U_NAMESPACE_USE
898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_name_count = 0;
899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_symbol_count = 0;
900b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UChar* s = NULL;
901b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char locale[ULOC_FULLNAME_CAPACITY];
902b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_strcpy(locale, loc);
90359d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv();
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;) {
905b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UErrorCode ec2 = U_ZERO_ERROR;
906b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // TODO: ures_openDirect?
90750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle* rb = ures_open(U_ICUDATA_CURR, locale, &ec2);
908b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, NULL, &ec2);
909b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t n = ures_getSize(curr);
910b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
911b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr, i, NULL, &ec2);
912b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t len;
913b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2);
914b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UBool isChoice = FALSE;
915b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (len > 0 && s[0] == CHOICE_FORMAT_MARK) {
916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ++s;
917b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                --len;
918b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (len > 0 && s[0] != CHOICE_FORMAT_MARK) {
919b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    isChoice = TRUE;
920b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
921b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (isChoice) {
923103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                ChoiceFormat fmt(UnicodeString(TRUE, s, len), ec2);
924b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t fmt_count;
925b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                fmt.getFormats(fmt_count);
926b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *total_currency_symbol_count += fmt_count;
927b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
928b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ++(*total_currency_symbol_count);  // currency symbol
92959d709d503bab6e2b61931737e662dd293b40578ccornelius                if (currencySymbolsEquiv != NULL) {
93059d709d503bab6e2b61931737e662dd293b40578ccornelius                    *total_currency_symbol_count += countEquivalent(*currencySymbolsEquiv, UnicodeString(TRUE, s, len));
93159d709d503bab6e2b61931737e662dd293b40578ccornelius                }
932b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
933b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
934b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ++(*total_currency_symbol_count); // iso code
935b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ++(*total_currency_name_count); // long name
936b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(names);
937b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
938b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
939b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // currency plurals
940b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UErrorCode ec3 = U_ZERO_ERROR;
941b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, NULL, &ec3);
942b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        n = ures_getSize(curr_p);
943b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
944b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr_p, i, NULL, &ec3);
945b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *total_currency_name_count += ures_getSize(names);
946b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(names);
947b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
948b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(curr_p);
949b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(curr);
950b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(rb);
951b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
952b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (!fallback(locale)) {
953b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
954b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
955b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
956b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
957b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
958b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UChar*
959103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliustoUpperCase(const UChar* source, int32_t len, const char* locale) {
960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar* dest = NULL;
961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
962103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t destLen = u_strToUpper(dest, 0, source, len, locale, &ec);
963b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
964b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ec = U_ZERO_ERROR;
965b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dest = (UChar*)uprv_malloc(sizeof(UChar) * MAX(destLen, len));
966103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    u_strToUpper(dest, destLen, source, len, locale, &ec);
967b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec)) {
968b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_memcpy(dest, source, sizeof(UChar) * len);
969b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
970b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return dest;
971b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
972b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
973b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
974103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Collect all available currency names associated with the given locale
975b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// (enable fallback chain).
976b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Read currenc names defined in resource bundle "Currencies" and
977b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// "CurrencyPlural", enable fallback chain.
978b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// return the malloc-ed currency name arrays and the total number of currency
979b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// names in the array.
980b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
981b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerucollectCurrencyNames(const char* locale,
982b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     CurrencyNameStruct** currencyNames,
983b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     int32_t* total_currency_name_count,
984b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     CurrencyNameStruct** currencySymbols,
985b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     int32_t* total_currency_symbol_count,
986b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                     UErrorCode& ec) {
98750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    U_NAMESPACE_USE
98859d709d503bab6e2b61931737e662dd293b40578ccornelius    const icu::Hashtable *currencySymbolsEquiv = getCurrSymbolsEquiv();
989b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Look up the Currencies resource for the given locale.
990b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec2 = U_ZERO_ERROR;
991b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
992b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char loc[ULOC_FULLNAME_CAPACITY];
993b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uloc_getName(locale, loc, sizeof(loc), &ec2);
994b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec2) || ec2 == U_STRING_NOT_TERMINATED_WARNING) {
995b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
996b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
997b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
998b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Get maximum currency name count first.
999b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    getCurrencyNameCount(loc, total_currency_name_count, total_currency_symbol_count);
1000b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1001b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *currencyNames = (CurrencyNameStruct*)uprv_malloc
1002b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (sizeof(CurrencyNameStruct) * (*total_currency_name_count));
1003b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *currencySymbols = (CurrencyNameStruct*)uprv_malloc
1004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (sizeof(CurrencyNameStruct) * (*total_currency_symbol_count));
1005b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UChar* s = NULL;  // currency name
1007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char* iso = NULL;  // currency ISO code
1008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1009b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_name_count = 0;
1010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *total_currency_symbol_count = 0;
1011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec3 = U_ZERO_ERROR;
1013b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec4 = U_ZERO_ERROR;
1014b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Using hash to remove duplicates caused by locale fallback
1016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UHashtable* currencyIsoCodes = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &ec3);
1017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UHashtable* currencyPluralIsoCodes = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &ec4);
1018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t localeLevel = 0; ; ++localeLevel) {
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ec2 = U_ZERO_ERROR;
1020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // TODO: ures_openDirect
102150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle* rb = ures_open(U_ICUDATA_CURR, loc, &ec2);
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle* curr = ures_getByKey(rb, CURRENCIES, NULL, &ec2);
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t n = ures_getSize(curr);
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr, i, NULL, &ec2);
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t len;
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            s = ures_getStringByIndex(names, UCURR_SYMBOL_NAME, &len, &ec2);
1028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // TODO: uhash_put wont change key/value?
1029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            iso = (char*)ures_getKey(names);
1030b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (localeLevel == 0) {
1031b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uhash_put(currencyIsoCodes, iso, iso, &ec3);
1032b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
1033b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (uhash_get(currencyIsoCodes, iso) != NULL) {
1034b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(names);
1035b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    continue;
1036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } else {
1037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    uhash_put(currencyIsoCodes, iso, iso, &ec3);
1038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1039b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool isChoice = FALSE;
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (len > 0 && s[0] == CHOICE_FORMAT_MARK) {
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++s;
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --len;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (len > 0 && s[0] != CHOICE_FORMAT_MARK) {
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    isChoice = TRUE;
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (isChoice) {
1049103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                ChoiceFormat fmt(UnicodeString(TRUE, s, len), ec2);
1050b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t fmt_count;
1051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                const UnicodeString* formats = fmt.getFormats(fmt_count);
1052b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                for (int i = 0; i < fmt_count; ++i) {
1053b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // put iso, formats[i]; into array
1054b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t length = formats[i].length();
1055b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UChar* name = (UChar*)uprv_malloc(sizeof(UChar)*length);
1056b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    formats[i].extract(0, length, name);
1057b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
1058b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[*total_currency_symbol_count].currencyName = name;
1059b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[*total_currency_symbol_count].flag = NEED_TO_BE_DELETED;
1060b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = length;
1061b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1062b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
1063b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Add currency symbol.
1064b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
1065b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[*total_currency_symbol_count].currencyName = (UChar*)s;
1066b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[*total_currency_symbol_count].flag = 0;
1067b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = len;
106859d709d503bab6e2b61931737e662dd293b40578ccornelius                // Add equivalent symbols
106959d709d503bab6e2b61931737e662dd293b40578ccornelius                if (currencySymbolsEquiv != NULL) {
107059d709d503bab6e2b61931737e662dd293b40578ccornelius                    EquivIterator iter(*currencySymbolsEquiv, UnicodeString(TRUE, s, len));
107159d709d503bab6e2b61931737e662dd293b40578ccornelius                    const UnicodeString *symbol;
107259d709d503bab6e2b61931737e662dd293b40578ccornelius                    while ((symbol = iter.next()) != NULL) {
107359d709d503bab6e2b61931737e662dd293b40578ccornelius                        (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
107459d709d503bab6e2b61931737e662dd293b40578ccornelius                        (*currencySymbols)[*total_currency_symbol_count].currencyName = (UChar*) symbol->getBuffer();
107559d709d503bab6e2b61931737e662dd293b40578ccornelius                        (*currencySymbols)[*total_currency_symbol_count].flag = 0;
107659d709d503bab6e2b61931737e662dd293b40578ccornelius                        (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = symbol->length();
107759d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
107859d709d503bab6e2b61931737e662dd293b40578ccornelius                }
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Add currency long name.
1082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            s = ures_getStringByIndex(names, UCURR_LONG_NAME, &len, &ec2);
1083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[*total_currency_name_count].IsoCode = iso;
1084103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            UChar* upperName = toUpperCase(s, len, locale);
1085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[*total_currency_name_count].currencyName = upperName;
1086b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[*total_currency_name_count].flag = NEED_TO_BE_DELETED;
1087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencyNames)[(*total_currency_name_count)++].currencyNameLen = len;
1088b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1089b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // put (iso, 3, and iso) in to array
1090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Add currency ISO code.
1091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].IsoCode = iso;
1092b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].currencyName = (UChar*)uprv_malloc(sizeof(UChar)*3);
109327f654740f2a26ad62a5c155af9199af9e69b889claireho            // Must convert iso[] into Unicode
109427f654740f2a26ad62a5c155af9199af9e69b889claireho            u_charsToUChars(iso, (*currencySymbols)[*total_currency_symbol_count].currencyName, 3);
1095b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[*total_currency_symbol_count].flag = NEED_TO_BE_DELETED;
1096b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            (*currencySymbols)[(*total_currency_symbol_count)++].currencyNameLen = 3;
1097b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1098b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(names);
1099b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // currency plurals
1102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UErrorCode ec3 = U_ZERO_ERROR;
1103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, NULL, &ec3);
1104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        n = ures_getSize(curr_p);
1105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int32_t i=0; i<n; ++i) {
1106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle* names = ures_getByIndex(curr_p, i, NULL, &ec3);
1107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            iso = (char*)ures_getKey(names);
1108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Using hash to remove duplicated ISO codes in fallback chain.
1109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (localeLevel == 0) {
1110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uhash_put(currencyPluralIsoCodes, iso, iso, &ec4);
1111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
1112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (uhash_get(currencyPluralIsoCodes, iso) != NULL) {
1113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(names);
1114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    continue;
1115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } else {
1116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    uhash_put(currencyPluralIsoCodes, iso, iso, &ec4);
1117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
1119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t num = ures_getSize(names);
1120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t len;
1121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            for (int32_t j = 0; j < num; ++j) {
1122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // TODO: remove duplicates between singular name and
1123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // currency long name?
1124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                s = ures_getStringByIndex(names, j, &len, &ec3);
1125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[*total_currency_name_count].IsoCode = iso;
1126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                UChar* upperName = toUpperCase(s, len, locale);
1127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[*total_currency_name_count].currencyName = upperName;
1128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[*total_currency_name_count].flag = NEED_TO_BE_DELETED;
1129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                (*currencyNames)[(*total_currency_name_count)++].currencyNameLen = len;
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ures_close(names);
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(curr_p);
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(curr);
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(rb);
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (!fallback(loc)) {
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uhash_close(currencyIsoCodes);
1143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uhash_close(currencyPluralIsoCodes);
1144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // quick sort the struct
1146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    qsort(*currencyNames, *total_currency_name_count,
1147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru          sizeof(CurrencyNameStruct), currencyNameComparator);
1148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    qsort(*currencySymbols, *total_currency_symbol_count,
1149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru          sizeof(CurrencyNameStruct), currencyNameComparator);
1150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("currency name count: %d\n", *total_currency_name_count);
1153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < *total_currency_name_count; ++index) {
1154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("index: %d\n", index);
1155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("iso: %s\n", (*currencyNames)[index].IsoCode);
115659d709d503bab6e2b61931737e662dd293b40578ccornelius        char curNameBuf[1024];
115759d709d503bab6e2b61931737e662dd293b40578ccornelius        memset(curNameBuf, 0, 1024);
115859d709d503bab6e2b61931737e662dd293b40578ccornelius        u_austrncpy(curNameBuf, (*currencyNames)[index].currencyName, (*currencyNames)[index].currencyNameLen);
115959d709d503bab6e2b61931737e662dd293b40578ccornelius        printf("currencyName: %s\n", curNameBuf);
1160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("len: %d\n", (*currencyNames)[index].currencyNameLen);
1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("currency symbol count: %d\n", *total_currency_symbol_count);
1163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < *total_currency_symbol_count; ++index) {
1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("index: %d\n", index);
1165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("iso: %s\n", (*currencySymbols)[index].IsoCode);
116659d709d503bab6e2b61931737e662dd293b40578ccornelius        char curNameBuf[1024];
116759d709d503bab6e2b61931737e662dd293b40578ccornelius        memset(curNameBuf, 0, 1024);
116859d709d503bab6e2b61931737e662dd293b40578ccornelius        u_austrncpy(curNameBuf, (*currencySymbols)[index].currencyName, (*currencySymbols)[index].currencyNameLen);
116959d709d503bab6e2b61931737e662dd293b40578ccornelius        printf("currencySymbol: %s\n", curNameBuf);
1170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        printf("len: %d\n", (*currencySymbols)[index].currencyNameLen);
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  currencyNames: currency names array
1176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  indexInCurrencyNames: the index of the character in currency names
1177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//         array against which the comparison is done
1178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  key: input text char to compare against
1179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  begin(IN/OUT): the begin index of matching range in currency names array
1180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  end(IN/OUT): the end index of matching range in currency names array.
1181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int32_t
1182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerubinarySearch(const CurrencyNameStruct* currencyNames,
1183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t indexInCurrencyNames,
1184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             const UChar key,
1185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t* begin, int32_t* end) {
1186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("key = %x\n", key);
1188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   int32_t first = *begin;
1190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   int32_t last = *end;
1191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   while (first <= last) {
1192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       int32_t mid = (first + last) / 2;  // compute mid point.
1193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       if (indexInCurrencyNames >= currencyNames[mid].currencyNameLen) {
1194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           first = mid + 1;
1195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       } else {
1196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           if (key > currencyNames[mid].currencyName[indexInCurrencyNames]) {
1197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               first = mid + 1;
1198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
1199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           else if (key < currencyNames[mid].currencyName[indexInCurrencyNames]) {
1200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               last = mid - 1;
1201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
1202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           else {
1203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Find a match, and looking for ranges
1204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Now do two more binary searches. First, on the left side for
1205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // the greatest L such that CurrencyNameStruct[L] < key.
1206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t L = *begin;
1207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t R = mid;
1208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                printf("mid = %d\n", mid);
1211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                while (L < R) {
1213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t M = (L + R) / 2;
1214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    printf("L = %d, R = %d, M = %d\n", L, R, M);
1216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (indexInCurrencyNames >= currencyNames[M].currencyNameLen) {
1218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        L = M + 1;
1219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    } else {
1220b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (currencyNames[M].currencyName[indexInCurrencyNames] < key) {
1221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            L = M + 1;
1222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        } else {
1223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            U_ASSERT(currencyNames[M].currencyName[indexInCurrencyNames] == key);
1225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            R = M;
1227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
1228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                U_ASSERT(L == R);
1232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *begin = L;
1234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                printf("begin = %d\n", *begin);
1236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                U_ASSERT(currencyNames[*begin].currencyName[indexInCurrencyNames] == key);
1237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Now for the second search, finding the least R such that
1240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // key < CurrencyNameStruct[R].
1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                L = mid;
1242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                R = *end;
1243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                while (L < R) {
1244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t M = (L + R) / 2;
1245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    printf("L = %d, R = %d, M = %d\n", L, R, M);
1247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (currencyNames[M].currencyNameLen < indexInCurrencyNames) {
1249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        L = M + 1;
1250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    } else {
1251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (currencyNames[M].currencyName[indexInCurrencyNames] > key) {
1252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            R = M;
1253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        } else {
1254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            U_ASSERT(currencyNames[M].currencyName[indexInCurrencyNames] == key);
1256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            L = M + 1;
1258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
1259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                U_ASSERT(L == R);
1263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (currencyNames[R].currencyName[indexInCurrencyNames] > key) {
1265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    *end = R - 1;
1266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } else {
1267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    *end = R;
1268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                printf("end = %d\n", *end);
1271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // now, found the range. check whether there is exact match
1274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (currencyNames[*begin].currencyNameLen == indexInCurrencyNames + 1) {
1275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    return *begin;  // find range and exact match.
1276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return -1;  // find range, but no exact match.
1278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
1279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       }
1280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   }
1281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   *begin = -1;
1282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   *end = -1;
1283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   return -1;    // failed to find range.
1284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Linear search "text" in "currencyNames".
1288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  begin, end: the begin and end index in currencyNames, within which
1289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//         range should the search be performed.
1290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  textLen: the length of the text to be compared
1291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchLen(IN/OUT): passing in the computed max matching length
1292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                              pass out the new max  matching length
1293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchIndex: the index in currencyName which has the longest
1294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                        match with input text.
1295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerulinearSearch(const CurrencyNameStruct* currencyNames,
1297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t begin, int32_t end,
1298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             const UChar* text, int32_t textLen,
1299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru             int32_t *maxMatchLen, int32_t* maxMatchIndex) {
1300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = begin; index <= end; ++index) {
1301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int32_t len = currencyNames[index].currencyNameLen;
1302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (len > *maxMatchLen && len <= textLen &&
1303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_memcmp(currencyNames[index].currencyName, text, len * sizeof(UChar)) == 0) {
1304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchIndex = index;
1305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchLen = len;
1306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            printf("maxMatchIndex = %d, maxMatchLen = %d\n",
1308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   *maxMatchIndex, *maxMatchLen);
1309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define LINEAR_SEARCH_THRESHOLD 10
1315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Find longest match between "text" and currency names in "currencyNames".
1317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  total_currency_count: total number of currency names in CurrencyNames.
1318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  textLen: the length of the text to be compared
1319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchLen: passing in the computed max matching length
1320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                              pass out the new max  matching length
1321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// @param  maxMatchIndex: the index in currencyName which has the longest
1322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//                        match with input text.
1323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerusearchCurrencyName(const CurrencyNameStruct* currencyNames,
1325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   int32_t total_currency_count,
1326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   const UChar* text, int32_t textLen,
1327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   int32_t* maxMatchLen, int32_t* maxMatchIndex) {
1328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *maxMatchIndex = -1;
1329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    *maxMatchLen = 0;
1330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t matchIndex = -1;
1331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t binarySearchBegin = 0;
1332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t binarySearchEnd = total_currency_count - 1;
1333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // It is a variant of binary search.
1334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // For example, given the currency names in currencyNames array are:
1335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // A AB ABC AD AZ B BB BBEX BBEXYZ BS C D E....
1336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // and the input text is BBEXST
1337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The first round binary search search "B" in the text against
1338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // the first char in currency names, and find the first char matching range
1339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // to be "B BB BBEX BBEXYZ BS" (and the maximum matching "B").
1340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 2nd round binary search search the second "B" in the text against
1341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // the 2nd char in currency names, and narrow the matching range to
1342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // "BB BBEX BBEXYZ" (and the maximum matching "BB").
1343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 3rd round returnes the range as "BBEX BBEXYZ" (without changing
1344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // maximum matching).
1345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 4th round returns the same range (the maximum matching is "BBEX").
1346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The 5th round returns no matching range.
1347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < textLen; ++index) {
1348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // matchIndex saves the one with exact match till the current point.
1349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // [binarySearchBegin, binarySearchEnd] saves the matching range.
1350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        matchIndex = binarySearch(currencyNames, index,
1351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                  text[index],
1352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                  &binarySearchBegin, &binarySearchEnd);
1353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (binarySearchBegin == -1) { // did not find the range
1354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
1355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (matchIndex != -1) {
1357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // find an exact match for text from text[0] to text[index]
1358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // in currencyNames array.
1359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchLen = index + 1;
1360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *maxMatchIndex = matchIndex;
1361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (binarySearchEnd - binarySearchBegin < LINEAR_SEARCH_THRESHOLD) {
1363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // linear search if within threshold.
1364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            linearSearch(currencyNames, binarySearchBegin, binarySearchEnd,
1365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                         text, textLen,
1366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                         maxMatchLen, maxMatchIndex);
1367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
1368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return;
1371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//========================= currency name cache =====================
1374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef struct {
1375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char locale[ULOC_FULLNAME_CAPACITY];  //key
1376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // currency names, case insensitive
1377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencyNames;  // value
1378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t totalCurrencyNameCount;  // currency name count
1379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // currency symbols and ISO code, case sensitive
1380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencySymbols; // value
1381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t totalCurrencySymbolCount;  // count
1382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // reference count.
1383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // reference count is set to 1 when an entry is put to cache.
1384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // it increases by 1 before accessing, and decreased by 1 after accessing.
1385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // The entry is deleted when ref count is zero, which means
1386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // the entry is replaced out of cache and no process is accessing it.
1387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t refCount;
1388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} CurrencyNameCacheEntry;
1389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define CURRENCY_NAME_CACHE_NUM 10
1392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Reserve 10 cache entries.
1394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic CurrencyNameCacheEntry* currCache[CURRENCY_NAME_CACHE_NUM] = {NULL};
1395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Using an index to indicate which entry to be replaced when cache is full.
1396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// It is a simple round-robin replacement strategy.
1397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic int8_t currentCacheEntryIndex = 0;
1398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
139959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic UMutex gCurrencyCacheMutex = U_MUTEX_INITIALIZER;
140059d709d503bab6e2b61931737e662dd293b40578ccornelius
1401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Cache deletion
1402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteCurrencyNames(CurrencyNameStruct* currencyNames, int32_t count) {
1404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t index = 0; index < count; ++index) {
1405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( (currencyNames[index].flag & NEED_TO_BE_DELETED) ) {
1406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_free(currencyNames[index].currencyName);
1407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_free(currencyNames);
1410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void
1414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteCacheEntry(CurrencyNameCacheEntry* entry) {
1415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    deleteCurrencyNames(entry->currencyNames, entry->totalCurrencyNameCount);
1416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    deleteCurrencyNames(entry->currencySymbols, entry->totalCurrencySymbolCount);
1417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uprv_free(entry);
1418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Cache clean up
142250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool U_CALLCONV
1423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querucurrency_cache_cleanup(void) {
1424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
1425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currCache[i]) {
1426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            deleteCacheEntry(currCache[i]);
1427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currCache[i] = 0;
1428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return TRUE;
1431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CFUNC void
1435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruuprv_parseCurrency(const char* locale,
1436103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                   const icu::UnicodeString& text,
1437103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                   icu::ParsePosition& pos,
1438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   int8_t type,
1439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   UChar* result,
1440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                   UErrorCode& ec)
1441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
1442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    U_NAMESPACE_USE
1443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(ec)) {
1445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return;
1446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t total_currency_name_count = 0;
1449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencyNames = NULL;
1450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t total_currency_symbol_count = 0;
1451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameStruct* currencySymbols = NULL;
1452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    CurrencyNameCacheEntry* cacheEntry = NULL;
1453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
145459d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gCurrencyCacheMutex);
1455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // in order to handle racing correctly,
145659d709d503bab6e2b61931737e662dd293b40578ccornelius    // not putting 'search' in a separate function.
1457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int8_t  found = -1;
1458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
1459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (currCache[i]!= NULL &&
1460b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_strcmp(locale, currCache[i]->locale) == 0) {
1461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            found = i;
1462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
1463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
1464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1465b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (found != -1) {
1466b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        cacheEntry = currCache[found];
1467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        currencyNames = cacheEntry->currencyNames;
1468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        total_currency_name_count = cacheEntry->totalCurrencyNameCount;
1469b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        currencySymbols = cacheEntry->currencySymbols;
1470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
1471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ++(cacheEntry->refCount);
1472b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
147359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gCurrencyCacheMutex);
1474b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (found == -1) {
1475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        collectCurrencyNames(locale, &currencyNames, &total_currency_name_count, &currencySymbols, &total_currency_symbol_count, ec);
1476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(ec)) {
1477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return;
1478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
147959d709d503bab6e2b61931737e662dd293b40578ccornelius        umtx_lock(&gCurrencyCacheMutex);
1480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // check again.
1481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        int8_t  found = -1;
1482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
1483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (currCache[i]!= NULL &&
1484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uprv_strcmp(locale, currCache[i]->locale) == 0) {
1485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                found = i;
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (found == -1) {
1490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // insert new entry to
1491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // currentCacheEntryIndex % CURRENCY_NAME_CACHE_NUM
1492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // and remove the existing entry
1493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // currentCacheEntryIndex % CURRENCY_NAME_CACHE_NUM
1494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // from cache.
1495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry = currCache[currentCacheEntryIndex];
1496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (cacheEntry) {
1497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                --(cacheEntry->refCount);
1498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // delete if the ref count is zero
1499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (cacheEntry->refCount == 0) {
1500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    deleteCacheEntry(cacheEntry);
1501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
1502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
1503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry = (CurrencyNameCacheEntry*)uprv_malloc(sizeof(CurrencyNameCacheEntry));
1504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currCache[currentCacheEntryIndex] = cacheEntry;
1505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_strcpy(cacheEntry->locale, locale);
1506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->currencyNames = currencyNames;
1507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->totalCurrencyNameCount = total_currency_name_count;
1508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->currencySymbols = currencySymbols;
1509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->totalCurrencySymbolCount = total_currency_symbol_count;
1510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry->refCount = 2; // one for cache, one for reference
1511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currentCacheEntryIndex = (currentCacheEntryIndex + 1) % CURRENCY_NAME_CACHE_NUM;
1512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cache_cleanup);
1513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1514b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
1515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            deleteCurrencyNames(currencyNames, total_currency_name_count);
1516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            deleteCurrencyNames(currencySymbols, total_currency_symbol_count);
1517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            cacheEntry = currCache[found];
1518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currencyNames = cacheEntry->currencyNames;
1519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            total_currency_name_count = cacheEntry->totalCurrencyNameCount;
1520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            currencySymbols = cacheEntry->currencySymbols;
1521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
1522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ++(cacheEntry->refCount);
1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
152459d709d503bab6e2b61931737e662dd293b40578ccornelius        umtx_unlock(&gCurrencyCacheMutex);
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t start = pos.getIndex();
1528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar inputText[MAX_CURRENCY_NAME_LEN];
1530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UChar upperText[MAX_CURRENCY_NAME_LEN];
1531b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t textLen = MIN(MAX_CURRENCY_NAME_LEN, text.length() - start);
1532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    text.extract(start, textLen, inputText);
1533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode ec1 = U_ZERO_ERROR;
1534103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    textLen = u_strToUpper(upperText, MAX_CURRENCY_NAME_LEN, inputText, textLen, locale, &ec1);
1535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t max = 0;
1537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t matchIndex = -1;
1538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // case in-sensitive comparision against currency names
1539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    searchCurrencyName(currencyNames, total_currency_name_count,
1540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                       upperText, textLen, &max, &matchIndex);
1541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("search in names, max = %d, matchIndex = %d\n", max, matchIndex);
1544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t maxInSymbol = 0;
1547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t matchIndexInSymbol = -1;
1548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (type != UCURR_LONG_NAME) {  // not name only
1549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // case sensitive comparison against currency symbols and ISO code.
1550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        searchCurrencyName(currencySymbols, total_currency_symbol_count,
1551b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           inputText, textLen,
1552b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                           &maxInSymbol, &matchIndexInSymbol);
1553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1554b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1555b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef UCURR_DEBUG
1556b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    printf("search in symbols, maxInSymbol = %d, matchIndexInSymbol = %d\n", maxInSymbol, matchIndexInSymbol);
155759d709d503bab6e2b61931737e662dd293b40578ccornelius    if(matchIndexInSymbol != -1) {
155859d709d503bab6e2b61931737e662dd293b40578ccornelius      printf("== ISO=%s\n", currencySymbols[matchIndexInSymbol].IsoCode);
155959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
1560b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif
1561b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1562b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (max >= maxInSymbol && matchIndex != -1) {
1563b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_charsToUChars(currencyNames[matchIndex].IsoCode, result, 4);
1564b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        pos.setIndex(start + max);
1565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else if (maxInSymbol >= max && matchIndexInSymbol != -1) {
1566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        u_charsToUChars(currencySymbols[matchIndexInSymbol].IsoCode, result, 4);
1567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        pos.setIndex(start + maxInSymbol);
1568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // decrease reference count
157159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_lock(&gCurrencyCacheMutex);
1572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    --(cacheEntry->refCount);
1573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (cacheEntry->refCount == 0) {  // remove
1574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        deleteCacheEntry(cacheEntry);
1575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
157659d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_unlock(&gCurrencyCacheMutex);
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1579b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Internal method.  Given a currency ISO code and a locale, return
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the "static" currency name.  This is usually the same as the
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * format is applied to the number 2.0 (to yield the more common
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * plural) to return a static name.
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is used for backward compatibility with old currency logic in
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * DecimalFormat and DecimalFormatSymbols.
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
1590c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CFUNC void
1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_getStaticCurrencyName(const UChar* iso, const char* loc,
1592103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                           icu::UnicodeString& result, UErrorCode& ec)
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_NAMESPACE_USE
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool isChoiceFormat;
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME,
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                          &isChoiceFormat, &len, &ec);
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // If this is a ChoiceFormat currency, then format an
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // arbitrary value; pick something != 1; more common.
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result.truncate(0);
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (isChoiceFormat) {
1605103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            ChoiceFormat f(UnicodeString(TRUE, currname, len), ec);
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(ec)) {
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                f.format(2.0, result);
1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1609103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                result.setTo(iso, -1);
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1612103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.setTo(currname, -1);
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_getDefaultFractionDigits(const UChar* currency, UErrorCode* ec) {
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (_findMetaData(currency, *ec))[0];
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI double U_EXPORT2
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_getRoundingIncrement(const UChar* currency, UErrorCode* ec) {
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t *data = _findMetaData(currency, *ec);
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If the meta data is invalid, return 0.0.
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (data[0] < 0 || data[0] > MAX_POW10) {
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(*ec)) {
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *ec = U_INVALID_FORMAT_ERROR;
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0.0;
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If there is no rounding, return 0.0 to indicate no rounding.  A
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // rounding value (data[1]) of 0 or 1 indicates no rounding.
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (data[1] < 2) {
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0.0;
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Return data[1] / 10^(data[0]).  The only actual rounding data,
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // as of this writing, is CHF { 2, 5 }.
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return double(data[1]) / POW10[data[0]];
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct UCurrencyContext {
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t currType; /* UCurrCurrencyType */
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t listIdx;
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} UCurrencyContext;
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPlease keep this list in alphabetical order.
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruYou can look at the CLDR supplemental data or ISO-4217 for the meaning of some
1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruof these items.
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruISO-4217: http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const struct CurrencyList {
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *currency;
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t currType;
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} gCurrencyList[] = {
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ADP", UCURR_COMMON|UCURR_DEPRECATED},
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AED", UCURR_COMMON|UCURR_NON_DEPRECATED},
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AFA", UCURR_COMMON|UCURR_DEPRECATED},
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AFN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1666c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"ALK", UCURR_COMMON|UCURR_DEPRECATED},
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ALL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ANG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AOA", UCURR_COMMON|UCURR_NON_DEPRECATED},
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AOK", UCURR_COMMON|UCURR_DEPRECATED},
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AON", UCURR_COMMON|UCURR_DEPRECATED},
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AOR", UCURR_COMMON|UCURR_DEPRECATED},
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ARA", UCURR_COMMON|UCURR_DEPRECATED},
1675b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ARL", UCURR_COMMON|UCURR_DEPRECATED},
1676b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ARM", UCURR_COMMON|UCURR_DEPRECATED},
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ARP", UCURR_COMMON|UCURR_DEPRECATED},
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ARS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ATS", UCURR_COMMON|UCURR_DEPRECATED},
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AUD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AWG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AZM", UCURR_COMMON|UCURR_DEPRECATED},
1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"AZN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BAD", UCURR_COMMON|UCURR_DEPRECATED},
1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BAM", UCURR_COMMON|UCURR_NON_DEPRECATED},
1686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BAN", UCURR_COMMON|UCURR_DEPRECATED},
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BBD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BDT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BEC", UCURR_UNCOMMON|UCURR_DEPRECATED},
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BEF", UCURR_COMMON|UCURR_DEPRECATED},
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BEL", UCURR_UNCOMMON|UCURR_DEPRECATED},
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BGL", UCURR_COMMON|UCURR_DEPRECATED},
1693c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    {"BGM", UCURR_COMMON|UCURR_DEPRECATED},
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BGN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1695b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BGO", UCURR_COMMON|UCURR_DEPRECATED},
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BHD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BIF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BND", UCURR_COMMON|UCURR_NON_DEPRECATED},
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BOB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BOL", UCURR_COMMON|UCURR_DEPRECATED},
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BOP", UCURR_COMMON|UCURR_DEPRECATED},
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BOV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRB", UCURR_COMMON|UCURR_DEPRECATED},
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRC", UCURR_COMMON|UCURR_DEPRECATED},
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRE", UCURR_COMMON|UCURR_DEPRECATED},
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRN", UCURR_COMMON|UCURR_DEPRECATED},
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BRR", UCURR_COMMON|UCURR_DEPRECATED},
1710b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"BRZ", UCURR_COMMON|UCURR_DEPRECATED},
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BSD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BTN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BUK", UCURR_COMMON|UCURR_DEPRECATED},
1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BWP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BYB", UCURR_COMMON|UCURR_DEPRECATED},
1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BYR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"BZD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CAD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CDF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CHE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CHF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CHW", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"CLE", UCURR_COMMON|UCURR_DEPRECATED},
1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CLF", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CLP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CNX", UCURR_UNCOMMON|UCURR_DEPRECATED},
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CNY", UCURR_COMMON|UCURR_NON_DEPRECATED},
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"COP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"COU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CRC", UCURR_COMMON|UCURR_NON_DEPRECATED},
1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CSD", UCURR_COMMON|UCURR_DEPRECATED},
1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CSK", UCURR_COMMON|UCURR_DEPRECATED},
1733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"CUC", UCURR_COMMON|UCURR_NON_DEPRECATED},
1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CUP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CVE", UCURR_COMMON|UCURR_NON_DEPRECATED},
1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CYP", UCURR_COMMON|UCURR_DEPRECATED},
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"CZK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DDM", UCURR_COMMON|UCURR_DEPRECATED},
1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DEM", UCURR_COMMON|UCURR_DEPRECATED},
1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DJF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DKK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DOP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"DZD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ECS", UCURR_COMMON|UCURR_DEPRECATED},
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ECV", UCURR_UNCOMMON|UCURR_DEPRECATED},
1746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {"EEK", UCURR_COMMON|UCURR_DEPRECATED},
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EGP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EQE", UCURR_COMMON|UCURR_DEPRECATED},
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ERN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ESA", UCURR_UNCOMMON|UCURR_DEPRECATED},
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ESB", UCURR_UNCOMMON|UCURR_DEPRECATED},
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ESP", UCURR_COMMON|UCURR_DEPRECATED},
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ETB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"EUR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FIM", UCURR_COMMON|UCURR_DEPRECATED},
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FJD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FKP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"FRF", UCURR_COMMON|UCURR_DEPRECATED},
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GBP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GEK", UCURR_COMMON|UCURR_DEPRECATED},
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GEL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GHC", UCURR_COMMON|UCURR_DEPRECATED},
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GHS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GIP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GNF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GNS", UCURR_COMMON|UCURR_DEPRECATED},
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GQE", UCURR_COMMON|UCURR_DEPRECATED},
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GRD", UCURR_COMMON|UCURR_DEPRECATED},
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GTQ", UCURR_COMMON|UCURR_NON_DEPRECATED},
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GWE", UCURR_COMMON|UCURR_DEPRECATED},
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GWP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"GYD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HKD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HNL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HRD", UCURR_COMMON|UCURR_DEPRECATED},
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HRK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HTG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"HUF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IDR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IEP", UCURR_COMMON|UCURR_DEPRECATED},
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ILP", UCURR_COMMON|UCURR_DEPRECATED},
1783b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ILR", UCURR_COMMON|UCURR_DEPRECATED},
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ILS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"INR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IQD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"IRR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1788b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ISJ", UCURR_COMMON|UCURR_DEPRECATED},
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ISK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ITL", UCURR_COMMON|UCURR_DEPRECATED},
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"JMD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"JOD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"JPY", UCURR_COMMON|UCURR_NON_DEPRECATED},
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KES", UCURR_COMMON|UCURR_NON_DEPRECATED},
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KGS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KHR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KMF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KPW", UCURR_COMMON|UCURR_NON_DEPRECATED},
1799b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"KRH", UCURR_COMMON|UCURR_DEPRECATED},
1800b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"KRO", UCURR_COMMON|UCURR_DEPRECATED},
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KRW", UCURR_COMMON|UCURR_NON_DEPRECATED},
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KWD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KYD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"KZT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LAK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LBP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LKR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LRD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LSL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LSM", UCURR_COMMON|UCURR_DEPRECATED},
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LTL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LTT", UCURR_COMMON|UCURR_DEPRECATED},
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LUC", UCURR_UNCOMMON|UCURR_DEPRECATED},
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LUF", UCURR_COMMON|UCURR_DEPRECATED},
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LUL", UCURR_UNCOMMON|UCURR_DEPRECATED},
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LVL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LVR", UCURR_COMMON|UCURR_DEPRECATED},
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"LYD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MAD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MAF", UCURR_COMMON|UCURR_DEPRECATED},
1821b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MCF", UCURR_COMMON|UCURR_DEPRECATED},
1822b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MDC", UCURR_COMMON|UCURR_DEPRECATED},
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MDL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MGA", UCURR_COMMON|UCURR_NON_DEPRECATED},
1825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MGF", UCURR_COMMON|UCURR_DEPRECATED},
1826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MKD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1827b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MKN", UCURR_COMMON|UCURR_DEPRECATED},
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MLF", UCURR_COMMON|UCURR_DEPRECATED},
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MMK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MNT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MOP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MRO", UCURR_COMMON|UCURR_NON_DEPRECATED},
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MTL", UCURR_COMMON|UCURR_DEPRECATED},
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MTP", UCURR_COMMON|UCURR_DEPRECATED},
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MUR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1836b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"MVP", UCURR_COMMON|UCURR_DEPRECATED},
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MVR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MWK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MXN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MXP", UCURR_COMMON|UCURR_DEPRECATED},
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MXV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MYR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MZE", UCURR_COMMON|UCURR_NON_DEPRECATED},
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MZM", UCURR_COMMON|UCURR_DEPRECATED},
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"MZN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NAD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NGN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NIC", UCURR_COMMON|UCURR_DEPRECATED},
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NIO", UCURR_COMMON|UCURR_NON_DEPRECATED},
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NLG", UCURR_COMMON|UCURR_DEPRECATED},
1851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NOK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NPR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"NZD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"OMR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PAB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PEI", UCURR_COMMON|UCURR_DEPRECATED},
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PEN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PES", UCURR_COMMON|UCURR_DEPRECATED},
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PGK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PHP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PKR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PLN", UCURR_COMMON|UCURR_NON_DEPRECATED},
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PLZ", UCURR_COMMON|UCURR_DEPRECATED},
1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PTE", UCURR_COMMON|UCURR_DEPRECATED},
1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"PYG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"QAR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RHD", UCURR_COMMON|UCURR_DEPRECATED},
1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ROL", UCURR_COMMON|UCURR_DEPRECATED},
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RON", UCURR_COMMON|UCURR_NON_DEPRECATED},
1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RSD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RUB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RUR", UCURR_COMMON|UCURR_DEPRECATED},
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"RWF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SAR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SBD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SCR", UCURR_COMMON|UCURR_NON_DEPRECATED},
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SDD", UCURR_COMMON|UCURR_DEPRECATED},
1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SDG", UCURR_COMMON|UCURR_NON_DEPRECATED},
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SDP", UCURR_COMMON|UCURR_DEPRECATED},
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SEK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SGD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SHP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SIT", UCURR_COMMON|UCURR_DEPRECATED},
1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SKK", UCURR_COMMON|UCURR_NON_DEPRECATED},
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SLL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SOS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SRD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SRG", UCURR_COMMON|UCURR_DEPRECATED},
18898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    {"SSP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"STD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SUR", UCURR_COMMON|UCURR_DEPRECATED},
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SVC", UCURR_COMMON|UCURR_NON_DEPRECATED},
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SYP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"SZL", UCURR_COMMON|UCURR_NON_DEPRECATED},
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"THB", UCURR_COMMON|UCURR_NON_DEPRECATED},
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TJR", UCURR_COMMON|UCURR_DEPRECATED},
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TJS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1898b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"TMM", UCURR_COMMON|UCURR_DEPRECATED},
1899b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"TMT", UCURR_COMMON|UCURR_NON_DEPRECATED},
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TND", UCURR_COMMON|UCURR_NON_DEPRECATED},
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TOP", UCURR_COMMON|UCURR_NON_DEPRECATED},
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TPE", UCURR_COMMON|UCURR_DEPRECATED},
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TRL", UCURR_COMMON|UCURR_DEPRECATED},
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TRY", UCURR_COMMON|UCURR_NON_DEPRECATED},
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TTD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TWD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"TZS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UAH", UCURR_COMMON|UCURR_NON_DEPRECATED},
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UAK", UCURR_COMMON|UCURR_DEPRECATED},
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UGS", UCURR_COMMON|UCURR_DEPRECATED},
1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UGX", UCURR_COMMON|UCURR_NON_DEPRECATED},
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"USD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"USN", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"USS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UYI", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1916b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"UYP", UCURR_COMMON|UCURR_DEPRECATED},
1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UYU", UCURR_COMMON|UCURR_NON_DEPRECATED},
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"UZS", UCURR_COMMON|UCURR_NON_DEPRECATED},
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VEB", UCURR_COMMON|UCURR_DEPRECATED},
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VEF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VND", UCURR_COMMON|UCURR_NON_DEPRECATED},
1922b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"VNN", UCURR_COMMON|UCURR_DEPRECATED},
1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"VUV", UCURR_COMMON|UCURR_NON_DEPRECATED},
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"WST", UCURR_COMMON|UCURR_NON_DEPRECATED},
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XAF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XAG", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XAU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBA", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBB", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBC", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XBD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XCD", UCURR_COMMON|UCURR_NON_DEPRECATED},
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XDR", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XEU", UCURR_UNCOMMON|UCURR_DEPRECATED},
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XFO", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XFU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XOF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XPD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XPF", UCURR_COMMON|UCURR_NON_DEPRECATED},
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XPT", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XRE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
19428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    {"XSU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XTS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
19448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    {"XUA", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"XXX", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YDD", UCURR_COMMON|UCURR_DEPRECATED},
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YER", UCURR_COMMON|UCURR_NON_DEPRECATED},
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YUD", UCURR_COMMON|UCURR_DEPRECATED},
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YUM", UCURR_COMMON|UCURR_DEPRECATED},
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"YUN", UCURR_COMMON|UCURR_DEPRECATED},
1951b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"YUR", UCURR_COMMON|UCURR_DEPRECATED},
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZAL", UCURR_UNCOMMON|UCURR_NON_DEPRECATED},
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZAR", UCURR_COMMON|UCURR_NON_DEPRECATED},
19548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    {"ZMK", UCURR_COMMON|UCURR_DEPRECATED},
19558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    {"ZMW", UCURR_COMMON|UCURR_NON_DEPRECATED},
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZRN", UCURR_COMMON|UCURR_DEPRECATED},
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {"ZRZ", UCURR_COMMON|UCURR_DEPRECATED},
19588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    {"ZWL", UCURR_COMMON|UCURR_DEPRECATED},
1959b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ZWR", UCURR_COMMON|UCURR_DEPRECATED},
1960b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {"ZWD", UCURR_COMMON|UCURR_DEPRECATED},
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    { NULL, 0 } // Leave here to denote the end of the list.
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define UCURR_MATCHES_BITMASK(variable, typeToMatch) \
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((typeToMatch) == UCURR_ALL || ((variable) & (typeToMatch)) == (typeToMatch))
1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t U_CALLCONV
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_countCurrencyList(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context);
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uint32_t currType = myContext->currType;
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t count = 0;
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Count the number of items matching the type we are looking for. */
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t idx = 0; gCurrencyList[idx].currency != NULL; idx++) {
1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (UCURR_MATCHES_BITMASK(gCurrencyList[idx].currType, currType)) {
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            count++;
1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return count;
1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char* U_CALLCONV
1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_nextCurrencyList(UEnumeration *enumerator,
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        int32_t* resultLength,
1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UErrorCode * /*pErrorCode*/)
1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCurrencyContext *myContext = (UCurrencyContext *)(enumerator->context);
1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Find the next in the list that matches the type we are looking for. */
1990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (myContext->listIdx < (sizeof(gCurrencyList)/sizeof(gCurrencyList[0]))-1) {
1991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const struct CurrencyList *currItem = &gCurrencyList[myContext->listIdx++];
1992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (UCURR_MATCHES_BITMASK(currItem->currType, myContext->currType))
1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (resultLength) {
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *resultLength = 3; /* Currency codes are only 3 chars long */
1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return currItem->currency;
1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* We enumerated too far. */
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (resultLength) {
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *resultLength = 0;
2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV
2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_resetCurrencyList(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) {
2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ((UCurrencyContext *)(enumerator->context))->listIdx = 0;
2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_closeCurrencyList(UEnumeration *enumerator) {
2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(enumerator->context);
2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_free(enumerator);
2016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
201959d709d503bab6e2b61931737e662dd293b40578ccorneliusucurr_createCurrencyList(UHashtable *isoCodes, UErrorCode* status){
2020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode localStatus = U_ZERO_ERROR;
2021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Look up the CurrencyMap element in the root bundle.
2023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
2024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *currencyMapArray = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
2025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(localStatus)) {
2027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // process each entry in currency map
2028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i=0; i<ures_getSize(currencyMapArray); i++) {
2029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // get the currency resource
2030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UResourceBundle *currencyArray = ures_getByIndex(currencyMapArray, i, NULL, &localStatus);
2031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // process each currency
2032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(localStatus)) {
2033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                for (int32_t j=0; j<ures_getSize(currencyArray); j++) {
2034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // get the currency resource
2035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    UResourceBundle *currencyRes = ures_getByIndex(currencyArray, j, NULL, &localStatus);
2036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    IsoCodeEntry *entry = (IsoCodeEntry*)uprv_malloc(sizeof(IsoCodeEntry));
2037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (entry == NULL) {
2038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        *status = U_MEMORY_ALLOCATION_ERROR;
2039b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        return;
2040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
2041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // get the ISO code
2043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t isoLength = 0;
2044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    UResourceBundle *idRes = ures_getByKey(currencyRes, "id", NULL, &localStatus);
2045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (idRes == NULL) {
2046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
2047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
2048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    const UChar *isoCode = ures_getString(idRes, &isoLength, &localStatus);
2049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
205054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // get from date
205154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    UDate fromDate = U_DATE_MIN;
2052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
205354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
205454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    if (U_SUCCESS(localStatus)) {
205554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                        int32_t fromLength = 0;
205654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                        const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
205754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                        int64_t currDate64 = (int64_t)fromArray[0] << 32;
205854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                        currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
205954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                        fromDate = (UDate)currDate64;
206054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    }
206154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    ures_close(fromRes);
206254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
206354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    // get to date
2064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    UDate toDate = U_DATE_MAX;
206554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    localStatus = U_ZERO_ERROR;
206654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
2067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
206854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    if (U_SUCCESS(localStatus)) {
2069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        int32_t toLength = 0;
2070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
207154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                        int64_t currDate64 = (int64_t)toArray[0] << 32;
2072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        toDate = (UDate)currDate64;
207454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    }
207554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    ures_close(toRes);
2076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2077b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ures_close(idRes);
2078b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ures_close(currencyRes);
2079b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2080b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    entry->isoCode = isoCode;
2081b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    entry->from = fromDate;
2082b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    entry->to = toDate;
2083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
208454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    localStatus = U_ZERO_ERROR;
208559d709d503bab6e2b61931737e662dd293b40578ccornelius                    uhash_put(isoCodes, (UChar *)isoCode, entry, &localStatus);
2086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
2087b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
2088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                *status = localStatus;
2089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
2090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ures_close(currencyArray);
2091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
2092b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
2093b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        *status = localStatus;
2094b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(currencyMapArray);
2097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
2098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UEnumeration gEnumCurrencyList = {
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NULL,
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NULL,
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_closeCurrencyList,
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_countCurrencyList,
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uenum_unextDefault,
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_nextCurrencyList,
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ucurr_resetCurrencyList
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
211159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initIsoCodes(UErrorCode &status) {
211259d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(gIsoCodes == NULL);
211359d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
2114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
211559d709d503bab6e2b61931737e662dd293b40578ccornelius    UHashtable *isoCodes = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
211659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
211759d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
211859d709d503bab6e2b61931737e662dd293b40578ccornelius    }
211959d709d503bab6e2b61931737e662dd293b40578ccornelius    uhash_setValueDeleter(isoCodes, deleteIsoCodeEntry);
212059d709d503bab6e2b61931737e662dd293b40578ccornelius
212159d709d503bab6e2b61931737e662dd293b40578ccornelius    ucurr_createCurrencyList(isoCodes, &status);
212259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
212359d709d503bab6e2b61931737e662dd293b40578ccornelius        uhash_close(isoCodes);
212459d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
212559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
212659d709d503bab6e2b61931737e662dd293b40578ccornelius    gIsoCodes = isoCodes;  // Note: gIsoCodes is const. Once set up here it is never altered,
212759d709d503bab6e2b61931737e662dd293b40578ccornelius                           //       and read only access is safe without synchronization.
212859d709d503bab6e2b61931737e662dd293b40578ccornelius}
212959d709d503bab6e2b61931737e662dd293b40578ccornelius
213059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void populateCurrSymbolsEquiv(icu::Hashtable *hash, UErrorCode &status) {
213159d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
213259d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
213359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
213459d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t length = sizeof(EQUIV_CURRENCY_SYMBOLS) / sizeof(EQUIV_CURRENCY_SYMBOLS[0]);
213559d709d503bab6e2b61931737e662dd293b40578ccornelius    for (int32_t i = 0; i < length; ++i) {
213659d709d503bab6e2b61931737e662dd293b40578ccornelius        icu::UnicodeString lhs(EQUIV_CURRENCY_SYMBOLS[i][0], -1, US_INV);
213759d709d503bab6e2b61931737e662dd293b40578ccornelius        icu::UnicodeString rhs(EQUIV_CURRENCY_SYMBOLS[i][1], -1, US_INV);
213859d709d503bab6e2b61931737e662dd293b40578ccornelius        makeEquivalent(lhs.unescape(), rhs.unescape(), hash, status);
2139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
214059d709d503bab6e2b61931737e662dd293b40578ccornelius            return;
2141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
214259d709d503bab6e2b61931737e662dd293b40578ccornelius    }
214359d709d503bab6e2b61931737e662dd293b40578ccornelius}
2144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
214559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initCurrSymbolsEquiv() {
214659d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(gCurrSymbolsEquiv == NULL);
214759d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode status = U_ZERO_ERROR;
214859d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
214959d709d503bab6e2b61931737e662dd293b40578ccornelius    icu::Hashtable *temp = new icu::Hashtable(status);
215059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (temp == NULL) {
215159d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
2152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
215359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
215459d709d503bab6e2b61931737e662dd293b40578ccornelius        delete temp;
215559d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
215659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
215759d709d503bab6e2b61931737e662dd293b40578ccornelius    temp->setValueDeleter(deleteUnicode);
215859d709d503bab6e2b61931737e662dd293b40578ccornelius    populateCurrSymbolsEquiv(temp, status);
215959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
216059d709d503bab6e2b61931737e662dd293b40578ccornelius        delete temp;
216159d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
216259d709d503bab6e2b61931737e662dd293b40578ccornelius    }
216359d709d503bab6e2b61931737e662dd293b40578ccornelius    gCurrSymbolsEquiv = temp;
216459d709d503bab6e2b61931737e662dd293b40578ccornelius}
2165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
216659d709d503bab6e2b61931737e662dd293b40578ccorneliusU_CAPI UBool U_EXPORT2
216759d709d503bab6e2b61931737e662dd293b40578ccorneliusucurr_isAvailable(const UChar* isoCode, UDate from, UDate to, UErrorCode* eErrorCode) {
216859d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gIsoCodesInitOnce, &initIsoCodes, *eErrorCode);
216959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(*eErrorCode)) {
217059d709d503bab6e2b61931737e662dd293b40578ccornelius        return FALSE;
217159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
2172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
217359d709d503bab6e2b61931737e662dd293b40578ccornelius    IsoCodeEntry* result = (IsoCodeEntry *) uhash_get(gIsoCodes, isoCode);
2174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (result == NULL) {
2175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
2176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (from > to) {
2177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        *eErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
2178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
2179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if  ((from > result->to) || (to < result->from)) {
2180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
2181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
2182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
2183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
2184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
218559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic const icu::Hashtable* getCurrSymbolsEquiv() {
218659d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gCurrSymbolsEquivInitOnce, &initCurrSymbolsEquiv);
218759d709d503bab6e2b61931737e662dd293b40578ccornelius    return gCurrSymbolsEquiv;
218859d709d503bab6e2b61931737e662dd293b40578ccornelius}
218959d709d503bab6e2b61931737e662dd293b40578ccornelius
2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UEnumeration * U_EXPORT2
2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruucurr_openISOCurrencies(uint32_t currType, UErrorCode *pErrorCode) {
2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UEnumeration *myEnum = NULL;
2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCurrencyContext *myContext;
2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myEnum = (UEnumeration*)uprv_malloc(sizeof(UEnumeration));
2196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (myEnum == NULL) {
2197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
2198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memcpy(myEnum, &gEnumCurrencyList, sizeof(UEnumeration));
2201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myContext = (UCurrencyContext*)uprv_malloc(sizeof(UCurrencyContext));
2202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (myContext == NULL) {
2203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
2204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_free(myEnum);
2205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myContext->currType = currType;
2208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myContext->listIdx = 0;
2209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    myEnum->context = myContext;
2210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return myEnum;
2211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
2214c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruucurr_countCurrencies(const char* locale,
2215c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UDate date,
2216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                 UErrorCode* ec)
2217c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
2218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t currCount = 0;
2219c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2220c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (ec != NULL && U_SUCCESS(*ec))
2221b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {
2222b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // local variables
2223c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UErrorCode localStatus = U_ZERO_ERROR;
2224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        char id[ULOC_FULLNAME_CAPACITY];
2225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
2226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // get country or country_variant in `id'
2227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        /*uint32_t variantType =*/ idForLocale(locale, id, sizeof(id), ec);
2228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(*ec))
2230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return 0;
2232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2234b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Remove variants, which is only needed for registration.
2235b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        char *idDelim = strchr(id, VAR_DELIM);
2236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (idDelim)
2237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            idDelim[0] = 0;
2239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Look up the CurrencyMap element in the root bundle.
224250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
2243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
2244b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2245b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Using the id derived from the local, get the currency data
2246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
2247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // process each currency to see which one is valid for the given date
2249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_SUCCESS(localStatus))
2250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            for (int32_t i=0; i<ures_getSize(countryArray); i++)
2252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // get the currency resource
2254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, NULL, &localStatus);
2255b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // get the from date
2257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int32_t fromLength = 0;
2258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
2259b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
2260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                int64_t currDate64 = (int64_t)fromArray[0] << 32;
2262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UDate fromDate = (UDate)currDate64;
2264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (ures_getSize(currencyRes)> 2)
2266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t toLength = 0;
2268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
2269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
2270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    currDate64 = (int64_t)toArray[0] << 32;
2272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UDate toDate = (UDate)currDate64;
2274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if ((fromDate <= date) && (date < toDate))
2276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currCount++;
2278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(toRes);
2281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                else
2283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (fromDate <= date)
2285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currCount++;
2287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // close open resources
2291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ures_close(currencyRes);
2292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ures_close(fromRes);
2293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } // end For loop
2295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } // end if (U_SUCCESS(localStatus))
2296c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_close(countryArray);
2298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // Check for errors
2300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR)
2301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // There is nothing to fallback to.
2303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Report the failure/warning if possible.
2304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *ec = localStatus;
2305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_SUCCESS(*ec))
2308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // no errors
2310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return currCount;
2311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we got here, either error code is invalid or
2316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // some argument passed is no good.
2317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return 0;
2318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
2321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruucurr_forLocaleAndDate(const char* locale,
2322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                UDate date,
2323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t index,
2324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                UChar* buff,
2325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                int32_t buffCapacity,
2326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                UErrorCode* ec)
2327c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
2328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t resLen = 0;
2329c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru	int32_t currIndex = 0;
2330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar* s = NULL;
2331c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (ec != NULL && U_SUCCESS(*ec))
2333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {
2334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // check the arguments passed
2335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ((buff && buffCapacity) || !buffCapacity )
2336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // local variables
2338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UErrorCode localStatus = U_ZERO_ERROR;
2339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            char id[ULOC_FULLNAME_CAPACITY];
2340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus);
2341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // get country or country_variant in `id'
2343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            /*uint32_t variantType =*/ idForLocale(locale, id, sizeof(id), ec);
2344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_FAILURE(*ec))
2345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                return 0;
2347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Remove variants, which is only needed for registration.
2350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            char *idDelim = strchr(id, VAR_DELIM);
2351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (idDelim)
2352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                idDelim[0] = 0;
2354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Look up the CurrencyMap element in the root bundle.
235750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            UResourceBundle *rb = ures_openDirect(U_ICUDATA_CURR, CURRENCY_DATA, &localStatus);
2358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus);
2359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Using the id derived from the local, get the currency data
2361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus);
2362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // process each currency to see which one is valid for the given date
2364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            bool matchFound = false;
2365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_SUCCESS(localStatus))
2366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if ((index <= 0) || (index> ures_getSize(countryArray)))
2368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    // requested index is out of bounds
2370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    ures_close(countryArray);
2371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    return 0;
2372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                for (int32_t i=0; i<ures_getSize(countryArray); i++)
2375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // get the currency resource
2377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UResourceBundle *currencyRes = ures_getByIndex(countryArray, i, NULL, &localStatus);
2378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    s = ures_getStringByKey(currencyRes, "id", &resLen, &localStatus);
2379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // get the from date
2381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t fromLength = 0;
2382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UResourceBundle *fromRes = ures_getByKey(currencyRes, "from", NULL, &localStatus);
2383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    const int32_t *fromArray = ures_getIntVector(fromRes, &fromLength, &localStatus);
2384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int64_t currDate64 = (int64_t)fromArray[0] << 32;
2386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    currDate64 |= ((int64_t)fromArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    UDate fromDate = (UDate)currDate64;
2388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (ures_getSize(currencyRes)> 2)
2390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        int32_t toLength = 0;
2392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        UResourceBundle *toRes = ures_getByKey(currencyRes, "to", NULL, &localStatus);
2393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        const int32_t *toArray = ures_getIntVector(toRes, &toLength, &localStatus);
2394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currDate64 = (int64_t)toArray[0] << 32;
2396b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        currDate64 |= ((int64_t)toArray[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
2397b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        UDate toDate = (UDate)currDate64;
2398b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2399b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if ((fromDate <= date) && (date < toDate))
2400b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        {
2401b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            currIndex++;
2402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            if (currIndex == index)
2403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            {
2404b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                matchFound = true;
2405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            }
2406b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
2407b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2408b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        ures_close(toRes);
2409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2410b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    else
2411b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2412b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (fromDate <= date)
2413b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        {
2414b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            currIndex++;
2415b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            if (currIndex == index)
2416b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            {
2417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                matchFound = true;
2418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            }
2419b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
2420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2421b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2422b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // close open resources
2423b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(currencyRes);
2424b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ures_close(fromRes);
2425b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2426b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // check for loop exit
2427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (matchFound)
2428b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    {
2429b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        break;
2430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2431b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2432b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                } // end For loop
2433b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2435b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_close(countryArray);
2436b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2437b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Check for errors
2438b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR)
2439b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2440b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // There is nothing to fallback to.
2441b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Report the failure/warning if possible.
2442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *ec = localStatus;
2443b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2444b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2445b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_SUCCESS(*ec))
2446b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            {
2447b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // no errors
2448b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if((buffCapacity> resLen) && matchFound)
2449b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2450b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // write out the currency value
2451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    u_strcpy(buff, s);
2452b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2453b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                else
2454b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                {
2455b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    return 0;
2456b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2457b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2458b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2459b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // return null terminated currency string
2460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return u_terminateUChars(buff, buffCapacity, resLen, ec);
2461b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2462b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        else
2463b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        {
2464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // illegal argument encountered
2465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            *ec = U_ILLEGAL_ARGUMENT_ERROR;
2466c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
2467c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2468c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
2469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2470b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If we got here, either error code is invalid or
2471b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // some argument passed is no good.
2472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return resLen;
2473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
2474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
2475b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UEnumeration defaultKeywordValues = {
2476b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    NULL,
2477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    NULL,
2478b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_close_keyword_values_iterator,
2479b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_count_keyword_values,
2480b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    uenum_unextDefault,
2481b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_next_keyword_value,
2482b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_reset_keyword_values_iterator
2483b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru};
2484b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) {
2486b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Resolve region
2487b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    char prefRegion[ULOC_FULLNAME_CAPACITY] = "";
2488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t prefRegionLength = 0;
2489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    prefRegionLength = uloc_getCountry(locale, prefRegion, sizeof(prefRegion), status);
2490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (prefRegionLength == 0) {
2491b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        char loc[ULOC_FULLNAME_CAPACITY] = "";
2492103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uloc_addLikelySubtags(locale, loc, sizeof(loc), status);
2493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2494b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        prefRegionLength = uloc_getCountry(loc, prefRegion, sizeof(prefRegion), status);
2495b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2497b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Read value from supplementalData
2498b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UList *values = ulist_createEmptyList(status);
2499b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UList *otherValues = ulist_createEmptyList(status);
2500b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
2501b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_FAILURE(*status) || en == NULL) {
2502b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (en == NULL) {
2503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            *status = U_MEMORY_ALLOCATION_ERROR;
2504b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
2505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            uprv_free(en);
2506b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2507b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_deleteList(values);
2508b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_deleteList(otherValues);
2509b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return NULL;
2510b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2511b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    memcpy(en, &defaultKeywordValues, sizeof(UEnumeration));
2512b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    en->context = values;
2513b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
251450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *bundle = ures_openDirect(U_ICUDATA_CURR, "supplementalData", status);
2515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_getByKey(bundle, "CurrencyMap", bundle, status);
2516b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UResourceBundle bundlekey, regbndl, curbndl, to;
2517b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&bundlekey);
2518b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&regbndl);
2519b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&curbndl);
2520b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_initStackObject(&to);
2521b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2522b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    while (U_SUCCESS(*status) && ures_hasNext(bundle)) {
2523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_getNextResource(bundle, &bundlekey, status);
2524b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(*status)) {
2525b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
2526b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2527b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        const char *region = ures_getKey(&bundlekey);
2528b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        UBool isPrefRegion = uprv_strcmp(region, prefRegion) == 0 ? TRUE : FALSE;
2529b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (!isPrefRegion && commonlyUsed) {
2530b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // With commonlyUsed=true, we do not put
253150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // currencies for other regions in the
2532b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // result list.
2533b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            continue;
2534b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2535b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ures_getByKey(bundle, region, &regbndl, status);
2536b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_FAILURE(*status)) {
2537b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            break;
2538b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2539b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        while (U_SUCCESS(*status) && ures_hasNext(&regbndl)) {
2540b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_getNextResource(&regbndl, &curbndl, status);
2541b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (ures_getType(&curbndl) != URES_TABLE) {
2542b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Currently, an empty ARRAY is mixed in.
2543b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                continue;
2544b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2545b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            char *curID = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY);
2546b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            int32_t curIDLength = ULOC_KEYWORDS_CAPACITY;
2547b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (curID == NULL) {
2548b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *status = U_MEMORY_ALLOCATION_ERROR;
2549b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                break;
2550b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
255150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
255250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if U_CHARSET_FAMILY==U_ASCII_FAMILY
2553b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_getUTF8StringByKey(&curbndl, "id", curID, &curIDLength, TRUE, status);
255450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* optimize - use the utf-8 string */
255550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
255650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            {
255750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       const UChar* defString = ures_getStringByKey(&curbndl, "id", &curIDLength, status);
255850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       if(U_SUCCESS(*status)) {
255950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			   if(curIDLength+1 > ULOC_KEYWORDS_CAPACITY) {
256050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho				*status = U_BUFFER_OVERFLOW_ERROR;
256150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			   } else {
256250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                           	u_UCharsToChars(defString, curID, curIDLength+1);
256350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho			   }
256450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                       }
256550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
256650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
256750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
2568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_FAILURE(*status)) {
2569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                break;
2570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            UBool hasTo = FALSE;
2572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ures_getByKey(&curbndl, "to", &to, status);
2573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (U_FAILURE(*status)) {
2574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Do nothing here...
2575b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                *status = U_ZERO_ERROR;
2576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
2577b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                hasTo = TRUE;
2578b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
257950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (isPrefRegion && !hasTo && !ulist_containsString(values, curID, (int32_t)uprv_strlen(curID))) {
2580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // Currently active currency for the target country
2581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ulist_addItemEndList(values, curID, TRUE, status);
258250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } else if (!ulist_containsString(otherValues, curID, (int32_t)uprv_strlen(curID)) && !commonlyUsed) {
2583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                ulist_addItemEndList(otherValues, curID, TRUE, status);
2584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            } else {
2585b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uprv_free(curID);
2586b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2588b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2589b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2590b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (U_SUCCESS(*status)) {
2591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (commonlyUsed) {
2592b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            if (ulist_getListSize(values) == 0) {
2593b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // This could happen if no valid region is supplied in the input
2594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                // locale. In this case, we use the CLDR's default.
2595b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                uenum_close(en);
2596b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                en = ucurr_getKeywordValuesForLocale(key, "und", TRUE, status);
2597b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2598b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        } else {
2599b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            // Consolidate the list
2600b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            char *value = NULL;
2601b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            ulist_resetList(otherValues);
2602b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            while ((value = (char *)ulist_getNext(otherValues)) != NULL) {
260350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (!ulist_containsString(values, value, (int32_t)uprv_strlen(value))) {
2604b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    char *tmpValue = (char *)uprv_malloc(sizeof(char) * ULOC_KEYWORDS_CAPACITY);
2605b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    uprv_memcpy(tmpValue, value, uprv_strlen(value) + 1);
2606b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    ulist_addItemEndList(values, tmpValue, TRUE, status);
2607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    if (U_FAILURE(*status)) {
2608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        break;
2609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
2610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                }
2611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            }
2612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_resetList((UList *)(en->context));
2615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else {
2616b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        ulist_deleteList(values);
2617b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        uprv_free(en);
2618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        values = NULL;
2619b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        en = NULL;
2620b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2621b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&to);
2622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&curbndl);
2623b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&regbndl);
2624b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(&bundlekey);
2625b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ures_close(bundle);
2626b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2627b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    ulist_deleteList(otherValues);
2628b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2629b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return en;
2630b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
2631b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2632103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
2633103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI int32_t U_EXPORT2
2634103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusucurr_getNumericCode(const UChar* currency) {
2635103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t code = 0;
2636103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (currency && u_strlen(currency) == ISO_CURRENCY_CODE_LENGTH) {
2637103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UErrorCode status = U_ZERO_ERROR;
2638103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
2639103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UResourceBundle *bundle = ures_openDirect(0, "currencyNumericCodes", &status);
2640103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        ures_getByKey(bundle, "codeMap", bundle, &status);
2641103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_SUCCESS(status)) {
2642103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            char alphaCode[ISO_CURRENCY_CODE_LENGTH+1];
2643103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            myUCharsToChars(alphaCode, currency);
2644103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            T_CString_toUpperCase(alphaCode);
2645103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            ures_getByKey(bundle, alphaCode, bundle, &status);
2646103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            int tmpCode = ures_getInt(bundle, &status);
2647103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            if (U_SUCCESS(status)) {
2648103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                code = tmpCode;
2649103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
2650103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
2651103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        ures_close(bundle);
2652103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
2653103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return code;
2654103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
2655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
2656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
2658