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