2 **********************************************************************
3 * Copyright (c) 2002-2006, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
12 #include "unicode/ucurr.h"
13 #include "unicode/locid.h"
14 #include "unicode/ures.h"
15 #include "unicode/ustring.h"
16 #include "unicode/choicfmt.h"
17 #include "unicode/parsepos.h"
26 //------------------------------------------------------------
29 // Default currency meta data of last resort. We try to use the
30 // defaults encoded in the meta data resource bundle. If there is a
31 // configuration/build error and these are not available, we use these
32 // hard-coded defaults (which should be identical).
33 static const int32_t LAST_RESORT_DATA
[] = { 2, 0 };
35 // POW10[i] = 10^i, i=0..MAX_POW10
36 static const int32_t POW10
[] = { 1, 10, 100, 1000, 10000, 100000,
37 1000000, 10000000, 100000000, 1000000000 };
39 static const int32_t MAX_POW10
= (sizeof(POW10
)/sizeof(POW10
[0])) - 1;
41 #define ISO_COUNTRY_CODE_LENGTH 3
43 //------------------------------------------------------------
47 static const char CURRENCY_DATA
[] = "CurrencyData";
48 // Tag for meta-data, in root.
49 static const char CURRENCY_META
[] = "CurrencyMeta";
51 // Tag for map from countries to currencies, in root.
52 static const char CURRENCY_MAP
[] = "CurrencyMap";
54 // Tag for default meta-data, in CURRENCY_META
55 static const char DEFAULT_META
[] = "DEFAULT";
57 // Variant for legacy pre-euro mapping in CurrencyMap
58 static const char VAR_PRE_EURO
[] = "PREEURO";
60 // Variant for legacy euro mapping in CurrencyMap
61 static const char VAR_EURO
[] = "EURO";
64 static const char VAR_DELIM
[] = "_";
66 // Variant for legacy euro mapping in CurrencyMap
67 static const char VAR_DELIM_EURO
[] = "_EURO";
69 #define VARIANT_IS_EMPTY 0
70 #define VARIANT_IS_EURO 0x1
71 #define VARIANT_IS_PREEURO 0x2
73 // Tag for localized display names (symbols) of currencies
74 static const char CURRENCIES
[] = "Currencies";
76 // Marker character indicating that a display name is a ChoiceFormat
77 // pattern. Strings that start with one mark are ChoiceFormat
78 // patterns. Strings that start with 2 marks are static strings, and
79 // the first mark is deleted.
80 static const UChar CHOICE_FORMAT_MARK
= 0x003D; // Equals sign
82 //------------------------------------------------------------
86 * Unfortunately, we have to convert the UChar* currency code to char*
87 * to use it as a resource key.
90 myUCharsToChars(char* resultOfLen4
, const UChar
* currency
) {
91 u_UCharsToChars(currency
, resultOfLen4
, ISO_COUNTRY_CODE_LENGTH
);
92 resultOfLen4
[ISO_COUNTRY_CODE_LENGTH
] = 0;
97 * Internal function to look up currency data. Result is an array of
98 * two integers. The first is the fraction digits. The second is the
99 * rounding increment, or 0 if none. The rounding increment is in
100 * units of 10^(-fraction_digits).
102 static const int32_t*
103 _findMetaData(const UChar
* currency
, UErrorCode
& ec
) {
105 if (currency
== 0 || *currency
== 0) {
107 ec
= U_ILLEGAL_ARGUMENT_ERROR
;
109 return LAST_RESORT_DATA
;
112 // Get CurrencyMeta resource out of root locale file. [This may
113 // move out of the root locale file later; if it does, update this
115 UResourceBundle
* currencyData
= ures_openDirect(NULL
, CURRENCY_DATA
, &ec
);
116 UResourceBundle
* currencyMeta
= ures_getByKey(currencyData
, CURRENCY_META
, currencyData
, &ec
);
119 ures_close(currencyMeta
);
120 // Config/build error; return hard-coded defaults
121 return LAST_RESORT_DATA
;
124 // Look up our currency, or if that's not available, then DEFAULT
125 char buf
[ISO_COUNTRY_CODE_LENGTH
+1];
126 UErrorCode ec2
= U_ZERO_ERROR
; // local error code: soft failure
127 UResourceBundle
* rb
= ures_getByKey(currencyMeta
, myUCharsToChars(buf
, currency
), NULL
, &ec2
);
128 if (U_FAILURE(ec2
)) {
130 rb
= ures_getByKey(currencyMeta
,DEFAULT_META
, NULL
, &ec
);
132 ures_close(currencyMeta
);
134 // Config/build error; return hard-coded defaults
135 return LAST_RESORT_DATA
;
140 const int32_t *data
= ures_getIntVector(rb
, &len
, &ec
);
141 if (U_FAILURE(ec
) || len
!= 2) {
142 // Config/build error; return hard-coded defaults
144 ec
= U_INVALID_FORMAT_ERROR
;
146 ures_close(currencyMeta
);
148 return LAST_RESORT_DATA
;
151 ures_close(currencyMeta
);
156 // -------------------------------------
159 * @see VARIANT_IS_EURO
160 * @see VARIANT_IS_PREEURO
163 idForLocale(const char* locale
, char* countryAndVariant
, int capacity
, UErrorCode
* ec
)
165 uint32_t variantType
= 0;
166 // !!! this is internal only, assumes buffer is not null and capacity is sufficient
167 // Extract the country name and variant name. We only
168 // recognize two variant names, EURO and PREEURO.
169 char variant
[ULOC_FULLNAME_CAPACITY
];
170 uloc_getCountry(locale
, countryAndVariant
, capacity
, ec
);
171 uloc_getVariant(locale
, variant
, sizeof(variant
), ec
);
172 if (variant
[0] != 0) {
173 variantType
= (0 == uprv_strcmp(variant
, VAR_EURO
))
174 | ((0 == uprv_strcmp(variant
, VAR_PRE_EURO
)) << 1);
177 uprv_strcat(countryAndVariant
, VAR_DELIM
);
178 uprv_strcat(countryAndVariant
, variant
);
184 // ------------------------------------------
188 //-------------------------------------------
190 // don't use ICUService since we don't need fallback
192 #if !UCONFIG_NO_SERVICE
194 static UBool U_CALLCONV
currency_cleanup(void);
198 /* Remember to call umtx_init(&gCRegLock) before using it! */
199 static UMTX gCRegLock
= 0;
200 static CReg
* gCRegHead
= 0;
202 struct CReg
: public UMemory
{
204 UChar iso
[ISO_COUNTRY_CODE_LENGTH
+1];
205 char id
[ULOC_FULLNAME_CAPACITY
];
207 CReg(const UChar
* _iso
, const char* _id
)
210 int32_t len
= (int32_t)uprv_strlen(_id
);
211 if (len
> (int32_t)(sizeof(id
)-1)) {
212 len
= (sizeof(id
)-1);
214 uprv_strncpy(id
, _id
, len
);
216 uprv_memcpy(iso
, _iso
, ISO_COUNTRY_CODE_LENGTH
* sizeof(const UChar
));
217 iso
[ISO_COUNTRY_CODE_LENGTH
] = 0;
220 static UCurrRegistryKey
reg(const UChar
* _iso
, const char* _id
, UErrorCode
* status
)
222 if (status
&& U_SUCCESS(*status
) && _iso
&& _id
) {
223 CReg
* n
= new CReg(_iso
, _id
);
225 umtx_init(&gCRegLock
);
226 Mutex
mutex(&gCRegLock
);
228 /* register for the first time */
229 ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY
, currency_cleanup
);
235 *status
= U_MEMORY_ALLOCATION_ERROR
;
240 static UBool
unreg(UCurrRegistryKey key
) {
241 umtx_init(&gCRegLock
);
242 Mutex
mutex(&gCRegLock
);
243 if (gCRegHead
== key
) {
244 gCRegHead
= gCRegHead
->next
;
251 if (p
->next
== key
) {
252 p
->next
= ((CReg
*)key
)->next
;
262 static const UChar
* get(const char* id
) {
263 umtx_init(&gCRegLock
);
264 Mutex
mutex(&gCRegLock
);
267 /* register cleanup of the mutex */
268 ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY
, currency_cleanup
);
270 if (uprv_strcmp(id
, p
->id
) == 0) {
278 /* This doesn't need to be thread safe. It's for u_cleanup only. */
279 static void cleanup(void) {
282 gCRegHead
= gCRegHead
->next
;
285 umtx_destroy(&gCRegLock
);
290 * Release all static memory held by currency.
293 static UBool U_CALLCONV
currency_cleanup(void) {
294 #if !UCONFIG_NO_SERVICE
301 // -------------------------------------
303 U_CAPI UCurrRegistryKey U_EXPORT2
304 ucurr_register(const UChar
* isoCode
, const char* locale
, UErrorCode
*status
)
306 if (status
&& U_SUCCESS(*status
)) {
307 char id
[ULOC_FULLNAME_CAPACITY
];
308 idForLocale(locale
, id
, sizeof(id
), status
);
309 return CReg::reg(isoCode
, id
, status
);
314 // -------------------------------------
316 U_CAPI UBool U_EXPORT2
317 ucurr_unregister(UCurrRegistryKey key
, UErrorCode
* status
)
319 if (status
&& U_SUCCESS(*status
)) {
320 return CReg::unreg(key
);
324 #endif /* UCONFIG_NO_SERVICE */
326 // -------------------------------------
328 U_CAPI
int32_t U_EXPORT2
329 ucurr_forLocale(const char* locale
,
331 int32_t buffCapacity
,
335 const UChar
* s
= NULL
;
336 if (ec
!= NULL
&& U_SUCCESS(*ec
)) {
337 if ((buff
&& buffCapacity
) || !buffCapacity
) {
338 UErrorCode localStatus
= U_ZERO_ERROR
;
339 char id
[ULOC_FULLNAME_CAPACITY
];
340 if ((resLen
= uloc_getKeywordValue(locale
, "currency", id
, ULOC_FULLNAME_CAPACITY
, &localStatus
))) {
341 // there is a currency keyword. Try to see if it's valid
342 if(buffCapacity
> resLen
) {
343 u_charsToUChars(id
, buff
, resLen
);
346 // get country or country_variant in `id'
347 uint32_t variantType
= idForLocale(locale
, id
, sizeof(id
), ec
);
349 if (U_FAILURE(*ec
)) {
353 #if !UCONFIG_NO_SERVICE
354 const UChar
* result
= CReg::get(id
);
356 if(buffCapacity
> u_strlen(result
)) {
357 u_strcpy(buff
, result
);
359 return u_strlen(result
);
363 // Look up the CurrencyMap element in the root bundle.
364 UResourceBundle
*rb
= ures_openDirect(NULL
, CURRENCY_DATA
, &localStatus
);
365 UResourceBundle
*cm
= ures_getByKey(rb
, CURRENCY_MAP
, rb
, &localStatus
);
366 s
= ures_getStringByKey(cm
, id
, &resLen
, &localStatus
);
368 if ((s
== NULL
|| U_FAILURE(localStatus
)) && variantType
!= VARIANT_IS_EMPTY
371 // We don't know about it. Check to see if we support the variant.
372 if (variantType
& VARIANT_IS_EURO
) {
373 s
= ures_getStringByKey(cm
, VAR_DELIM_EURO
, &resLen
, ec
);
376 uloc_getParent(locale
, id
, sizeof(id
), ec
);
377 *ec
= U_USING_FALLBACK_WARNING
;
379 return ucurr_forLocale(id
, buff
, buffCapacity
, ec
);
382 else if (*ec
== U_ZERO_ERROR
|| localStatus
!= U_ZERO_ERROR
) {
383 // There is nothing to fallback to. Report the failure/warning if possible.
386 if (U_SUCCESS(*ec
)) {
387 if(buffCapacity
> resLen
) {
393 return u_terminateUChars(buff
, buffCapacity
, resLen
, ec
);
395 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
404 * Modify the given locale name by removing the rightmost _-delimited
405 * element. If there is none, empty the string ("" == root).
406 * NOTE: The string "root" is not recognized; do not use it.
407 * @return TRUE if the fallback happened; FALSE if locale is already
410 static UBool
fallback(char *loc
) {
414 UErrorCode status
= U_ZERO_ERROR
;
415 uloc_getParent(loc
, loc
, (int32_t)uprv_strlen(loc
), &status
);
417 char *i = uprv_strrchr(loc, '_');
427 U_CAPI
const UChar
* U_EXPORT2
428 ucurr_getName(const UChar
* currency
,
430 UCurrNameStyle nameStyle
,
431 UBool
* isChoiceFormat
, // fillin
432 int32_t* len
, // fillin
435 // Look up the Currencies resource for the given locale. The
436 // Currencies locale data looks like this:
439 //| USD { "US$", "US Dollar" }
440 //| CHF { "Sw F", "Swiss Franc" }
441 //| INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
446 if (U_FAILURE(*ec
)) {
450 int32_t choice
= (int32_t) nameStyle
;
451 if (choice
< 0 || choice
> 1) {
452 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
456 // In the future, resource bundles may implement multi-level
457 // fallback. That is, if a currency is not found in the en_US
458 // Currencies data, then the en Currencies data will be searched.
459 // Currently, if a Currencies datum exists in en_US and en, the
460 // en_US entry hides that in en.
462 // We want multi-level fallback for this resource, so we implement
465 // Use a separate UErrorCode here that does not propagate out of
467 UErrorCode ec2
= U_ZERO_ERROR
;
469 char loc
[ULOC_FULLNAME_CAPACITY
];
470 uloc_getName(locale
, loc
, sizeof(loc
), &ec2
);
471 if (U_FAILURE(ec2
) || ec2
== U_STRING_NOT_TERMINATED_WARNING
) {
472 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
476 char buf
[ISO_COUNTRY_CODE_LENGTH
+1];
477 myUCharsToChars(buf
, currency
);
479 const UChar
* s
= NULL
;
481 // Multi-level resource inheritance fallback loop
484 UResourceBundle
* rb
= ures_open(NULL
, loc
, &ec2
);
485 rb
= ures_getByKey(rb
, CURRENCIES
, rb
, &ec2
);
486 rb
= ures_getByKey(rb
, buf
, rb
, &ec2
);
487 s
= ures_getStringByIndex(rb
, choice
, len
, &ec2
);
490 // If we've succeeded we're done. Otherwise, try to fallback.
491 // If that fails (because we are already at root) then exit.
492 if (U_SUCCESS(ec2
) || !fallback(loc
)) {
493 if (ec2
== U_USING_DEFAULT_WARNING
494 || (ec2
== U_USING_FALLBACK_WARNING
&& *ec
!= U_USING_DEFAULT_WARNING
)) {
498 } else if (strlen(loc
) == 0) {
499 *ec
= U_USING_DEFAULT_WARNING
;
500 } else if (*ec
!= U_USING_DEFAULT_WARNING
) {
501 *ec
= U_USING_FALLBACK_WARNING
;
505 // Determine if this is a ChoiceFormat pattern. One leading mark
506 // indicates a ChoiceFormat. Two indicates a static string that
507 // starts with a mark. In either case, the first mark is ignored,
508 // if present. Marks in the rest of the string have no special
510 *isChoiceFormat
= FALSE
;
511 if (U_SUCCESS(ec2
)) {
514 while (i
< *len
&& s
[i
] == CHOICE_FORMAT_MARK
&& i
< 2) {
517 *isChoiceFormat
= (i
== 1);
518 if (i
!= 0) ++s
; // Skip over first mark
522 // If we fail to find a match, use the ISO 4217 code
523 *len
= u_strlen(currency
); // Should == ISO_COUNTRY_CODE_LENGTH, but maybe not...?
524 *ec
= U_USING_DEFAULT_WARNING
;
531 uprv_parseCurrency(const char* locale
,
532 const UnicodeString
& text
,
537 // TODO: There is a slight problem with the pseudo-multi-level
538 // fallback implemented here. More-specific locales don't
539 // properly shield duplicate entries in less-specific locales.
540 // This problem will go away when real multi-level fallback is
541 // implemented. We could also fix this by recording (in a
542 // hash) which codes are used at each level of fallback, but
543 // this doesn't seem warranted.
549 // Look up the Currencies resource for the given locale. The
550 // Currencies locale data looks like this:
553 //| USD { "US$", "US Dollar" }
554 //| CHF { "Sw F", "Swiss Franc" }
555 //| INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
560 // In the future, resource bundles may implement multi-level
561 // fallback. That is, if a currency is not found in the en_US
562 // Currencies data, then the en Currencies data will be searched.
563 // Currently, if a Currencies datum exists in en_US and en, the
564 // en_US entry hides that in en.
566 // We want multi-level fallback for this resource, so we implement
569 // Use a separate UErrorCode here that does not propagate out of
571 UErrorCode ec2
= U_ZERO_ERROR
;
573 char loc
[ULOC_FULLNAME_CAPACITY
];
574 uloc_getName(locale
, loc
, sizeof(loc
), &ec2
);
575 if (U_FAILURE(ec2
) || ec2
== U_STRING_NOT_TERMINATED_WARNING
) {
576 ec
= U_ILLEGAL_ARGUMENT_ERROR
;
580 int32_t start
= pos
.getIndex();
581 const UChar
* s
= NULL
;
583 const char* iso
= NULL
;
586 // Multi-level resource inheritance fallback loop
589 UResourceBundle
* rb
= ures_open(NULL
, loc
, &ec2
);
590 UResourceBundle
* curr
= ures_getByKey(rb
, CURRENCIES
, NULL
, &ec2
);
591 int32_t n
= ures_getSize(curr
);
592 for (int32_t i
=0; i
<n
; ++i
) {
593 UResourceBundle
* names
= ures_getByIndex(curr
, i
, NULL
, &ec2
);
595 s
= ures_getStringByIndex(names
, UCURR_SYMBOL_NAME
, &len
, &ec2
);
596 UBool isChoice
= FALSE
;
597 if (len
> 0 && s
[0] == CHOICE_FORMAT_MARK
) {
600 if (len
> 0 && s
[0] != CHOICE_FORMAT_MARK
) {
606 ChoiceFormat
fmt(s
, ec2
);
607 fmt
.parse(text
, temp
, pos
);
608 len
= pos
.getIndex() - start
;
610 } else if (len
> max
&&
611 text
.compare(pos
.getIndex(), len
, s
) != 0) {
615 iso
= ures_getKey(names
);
623 // Try to fallback. If that fails (because we are already at
625 if (!fallback(loc
)) {
631 u_charsToUChars(iso
, result
, 4);
634 // If display name parse fails or if it matches fewer than 3
635 // characters, try to parse 3-letter ISO. Do this after the
636 // display name processing so 3-letter display names are
637 // preferred. Consider /[A-Z]{3}/ to be valid ISO, and parse
638 // it manually--UnicodeSet/regex are too slow and heavy.
639 if (max
< 3 && (text
.length() - start
) >= 3) {
641 for (int32_t k
=0; k
<3; ++k
) {
642 UChar ch
= text
.charAt(start
+ k
); // 16-bit ok
643 if (ch
< 0x41/*'A'*/ || ch
> 0x5A/*'Z'*/) {
649 text
.extract(start
, 3, result
);
655 pos
.setIndex(start
+ max
);
661 * Internal method. Given a currency ISO code and a locale, return
662 * the "static" currency name. This is usually the same as the
663 * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the
664 * format is applied to the number 2.0 (to yield the more common
665 * plural) to return a static name.
667 * This is used for backward compatibility with old currency logic in
668 * DecimalFormat and DecimalFormatSymbols.
671 uprv_getStaticCurrencyName(const UChar
* iso
, const char* loc
,
672 UnicodeString
& result
, UErrorCode
& ec
)
674 UBool isChoiceFormat
;
676 const UChar
* currname
= ucurr_getName(iso
, loc
, UCURR_SYMBOL_NAME
,
677 &isChoiceFormat
, &len
, &ec
);
679 // If this is a ChoiceFormat currency, then format an
680 // arbitrary value; pick something != 1; more common.
682 if (isChoiceFormat
) {
683 ChoiceFormat
f(currname
, ec
);
685 f
.format(2.0, result
);
695 U_CAPI
int32_t U_EXPORT2
696 ucurr_getDefaultFractionDigits(const UChar
* currency
, UErrorCode
* ec
) {
697 return (_findMetaData(currency
, *ec
))[0];
700 U_CAPI
double U_EXPORT2
701 ucurr_getRoundingIncrement(const UChar
* currency
, UErrorCode
* ec
) {
702 const int32_t *data
= _findMetaData(currency
, *ec
);
704 // If the meta data is invalid, return 0.0.
705 if (data
[0] < 0 || data
[0] > MAX_POW10
) {
706 if (U_SUCCESS(*ec
)) {
707 *ec
= U_INVALID_FORMAT_ERROR
;
712 // If there is no rounding, return 0.0 to indicate no rounding. A
713 // rounding value (data[1]) of 0 or 1 indicates no rounding.
718 // Return data[1] / 10^(data[0]). The only actual rounding data,
719 // as of this writing, is CHF { 2, 5 }.
720 return double(data
[1]) / POW10
[data
[0]];
725 typedef struct UCurrencyContext
{
726 uint32_t currType
; /* UCurrCurrencyType */
731 Please keep this list in alphabetical order.
732 You can look at the CLDR supplemental data or ISO-4217 for the meaning of some
734 ISO-4217: http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html
736 static const struct CurrencyList
{
737 const char *currency
;
739 } gCurrencyList
[] = {
740 {"ADP", UCURR_COMMON
|UCURR_DEPRECATED
},
741 {"AED", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
742 {"AFA", UCURR_COMMON
|UCURR_DEPRECATED
},
743 {"AFN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
744 {"ALL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
745 {"AMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
746 {"ANG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
747 {"AOA", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
748 {"AOK", UCURR_COMMON
|UCURR_DEPRECATED
},
749 {"AON", UCURR_COMMON
|UCURR_DEPRECATED
},
750 {"AOR", UCURR_COMMON
|UCURR_DEPRECATED
},
751 {"ARA", UCURR_COMMON
|UCURR_DEPRECATED
},
752 {"ARP", UCURR_COMMON
|UCURR_DEPRECATED
},
753 {"ARS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
754 {"ATS", UCURR_COMMON
|UCURR_DEPRECATED
},
755 {"AUD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
756 {"AWG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
757 {"AZM", UCURR_COMMON
|UCURR_DEPRECATED
},
758 {"AZN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
759 {"BAD", UCURR_COMMON
|UCURR_DEPRECATED
},
760 {"BAM", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
761 {"BBD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
762 {"BDT", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
763 {"BEC", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
764 {"BEF", UCURR_COMMON
|UCURR_DEPRECATED
},
765 {"BEL", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
766 {"BGL", UCURR_COMMON
|UCURR_DEPRECATED
},
767 {"BGN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
768 {"BHD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
769 {"BIF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
770 {"BMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
771 {"BND", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
772 {"BOB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
773 {"BOP", UCURR_COMMON
|UCURR_DEPRECATED
},
774 {"BOV", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
775 {"BRB", UCURR_COMMON
|UCURR_DEPRECATED
},
776 {"BRC", UCURR_COMMON
|UCURR_DEPRECATED
},
777 {"BRE", UCURR_COMMON
|UCURR_DEPRECATED
},
778 {"BRL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
779 {"BRN", UCURR_COMMON
|UCURR_DEPRECATED
},
780 {"BRR", UCURR_COMMON
|UCURR_DEPRECATED
},
781 {"BSD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
782 {"BTN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
783 {"BUK", UCURR_COMMON
|UCURR_DEPRECATED
},
784 {"BWP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
785 {"BYB", UCURR_COMMON
|UCURR_DEPRECATED
},
786 {"BYR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
787 {"BZD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
788 {"CAD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
789 {"CDF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
790 {"CHE", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
791 {"CHF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
792 {"CHW", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
793 {"CLF", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
794 {"CLP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
795 {"CNX", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
796 {"CNY", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
797 {"COP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
798 {"COU", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
799 {"CRC", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
800 {"CSD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
801 {"CSK", UCURR_COMMON
|UCURR_DEPRECATED
},
802 {"CUP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
803 {"CVE", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
804 {"CYP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
805 {"CZK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
806 {"DDM", UCURR_COMMON
|UCURR_DEPRECATED
},
807 {"DEM", UCURR_COMMON
|UCURR_DEPRECATED
},
808 {"DJF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
809 {"DKK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
810 {"DOP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
811 {"DZD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
812 {"ECS", UCURR_COMMON
|UCURR_DEPRECATED
},
813 {"ECV", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
814 {"EEK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
815 {"EGP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
816 {"EQE", UCURR_COMMON
|UCURR_DEPRECATED
},
817 {"ERN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
818 {"ESA", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
819 {"ESB", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
820 {"ESP", UCURR_COMMON
|UCURR_DEPRECATED
},
821 {"ETB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
822 {"EUR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
823 {"FIM", UCURR_COMMON
|UCURR_DEPRECATED
},
824 {"FJD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
825 {"FKP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
826 {"FRF", UCURR_COMMON
|UCURR_DEPRECATED
},
827 {"GBP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
828 {"GEK", UCURR_COMMON
|UCURR_DEPRECATED
},
829 {"GEL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
830 {"GHC", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
831 {"GIP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
832 {"GMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
833 {"GNF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
834 {"GNS", UCURR_COMMON
|UCURR_DEPRECATED
},
835 {"GQE", UCURR_COMMON
|UCURR_DEPRECATED
},
836 {"GRD", UCURR_COMMON
|UCURR_DEPRECATED
},
837 {"GTQ", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
838 {"GWE", UCURR_COMMON
|UCURR_DEPRECATED
},
839 {"GWP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
840 {"GYD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
841 {"HKD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
842 {"HNL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
843 {"HRD", UCURR_COMMON
|UCURR_DEPRECATED
},
844 {"HRK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
845 {"HTG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
846 {"HUF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
847 {"IDR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
848 {"IEP", UCURR_COMMON
|UCURR_DEPRECATED
},
849 {"ILP", UCURR_COMMON
|UCURR_DEPRECATED
},
850 {"ILS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
851 {"INR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
852 {"IQD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
853 {"IRR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
854 {"ISK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
855 {"ITL", UCURR_COMMON
|UCURR_DEPRECATED
},
856 {"JMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
857 {"JOD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
858 {"JPY", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
859 {"KES", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
860 {"KGS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
861 {"KHR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
862 {"KMF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
863 {"KPW", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
864 {"KRW", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
865 {"KWD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
866 {"KYD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
867 {"KZT", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
868 {"LAK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
869 {"LBP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
870 {"LKR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
871 {"LRD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
872 {"LSL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
873 {"LSM", UCURR_COMMON
|UCURR_DEPRECATED
},
874 {"LTL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
875 {"LTT", UCURR_COMMON
|UCURR_DEPRECATED
},
876 {"LUC", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
877 {"LUF", UCURR_COMMON
|UCURR_DEPRECATED
},
878 {"LUL", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
879 {"LVL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
880 {"LVR", UCURR_COMMON
|UCURR_DEPRECATED
},
881 {"LYD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
882 {"MAD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
883 {"MAF", UCURR_COMMON
|UCURR_DEPRECATED
},
884 {"MDL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
885 {"MGA", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
886 {"MGF", UCURR_COMMON
|UCURR_DEPRECATED
},
887 {"MKD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
888 {"MLF", UCURR_COMMON
|UCURR_DEPRECATED
},
889 {"MMK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
890 {"MNT", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
891 {"MOP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
892 {"MRO", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
893 {"MTL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
894 {"MTP", UCURR_COMMON
|UCURR_DEPRECATED
},
895 {"MUR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
896 {"MVR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
897 {"MWK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
898 {"MXN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
899 {"MXP", UCURR_COMMON
|UCURR_DEPRECATED
},
900 {"MXV", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
901 {"MYR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
902 {"MZE", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
903 {"MZM", UCURR_COMMON
|UCURR_DEPRECATED
},
904 {"MZN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
905 {"NAD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
906 {"NGN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
907 {"NIC", UCURR_COMMON
|UCURR_DEPRECATED
},
908 {"NIO", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
909 {"NLG", UCURR_COMMON
|UCURR_DEPRECATED
},
910 {"NOK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
911 {"NPR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
912 {"NZD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
913 {"OMR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
914 {"PAB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
915 {"PEI", UCURR_COMMON
|UCURR_DEPRECATED
},
916 {"PEN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
917 {"PES", UCURR_COMMON
|UCURR_DEPRECATED
},
918 {"PGK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
919 {"PHP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
920 {"PKR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
921 {"PLN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
922 {"PLZ", UCURR_COMMON
|UCURR_DEPRECATED
},
923 {"PTE", UCURR_COMMON
|UCURR_DEPRECATED
},
924 {"PYG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
925 {"QAR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
926 {"RHD", UCURR_COMMON
|UCURR_DEPRECATED
},
927 {"ROL", UCURR_COMMON
|UCURR_DEPRECATED
},
928 {"RON", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
929 {"RUB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
930 {"RUR", UCURR_COMMON
|UCURR_DEPRECATED
},
931 {"RWF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
932 {"SAR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
933 {"SBD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
934 {"SCR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
935 {"SDD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
936 {"SDP", UCURR_COMMON
|UCURR_DEPRECATED
},
937 {"SEK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
938 {"SGD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
939 {"SHP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
940 {"SIT", UCURR_COMMON
|UCURR_DEPRECATED
},
941 {"SKK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
942 {"SLL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
943 {"SOS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
944 {"SRD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
945 {"SRG", UCURR_COMMON
|UCURR_DEPRECATED
},
946 {"STD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
947 {"SUR", UCURR_COMMON
|UCURR_DEPRECATED
},
948 {"SVC", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
949 {"SYP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
950 {"SZL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
951 {"THB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
952 {"TJR", UCURR_COMMON
|UCURR_DEPRECATED
},
953 {"TJS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
954 {"TMM", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
955 {"TND", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
956 {"TOP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
957 {"TPE", UCURR_COMMON
|UCURR_DEPRECATED
},
958 {"TRL", UCURR_COMMON
|UCURR_DEPRECATED
},
959 {"TRY", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
960 {"TTD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
961 {"TWD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
962 {"TZS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
963 {"UAH", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
964 {"UAK", UCURR_COMMON
|UCURR_DEPRECATED
},
965 {"UGS", UCURR_COMMON
|UCURR_DEPRECATED
},
966 {"UGX", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
967 {"USD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
968 {"USN", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
969 {"USS", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
970 {"UYP", UCURR_COMMON
|UCURR_DEPRECATED
},
971 {"UYU", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
972 {"UZS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
973 {"VEB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
974 {"VND", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
975 {"VUV", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
976 {"WST", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
977 {"XAF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
978 {"XAG", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
979 {"XAU", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
980 {"XBA", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
981 {"XBB", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
982 {"XBC", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
983 {"XBD", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
984 {"XCD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
985 {"XDR", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
986 {"XEU", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
987 {"XFO", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
988 {"XFU", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
989 {"XOF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
990 {"XPD", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
991 {"XPF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
992 {"XPT", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
993 {"XRE", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
994 {"XTS", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
995 {"XXX", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
996 {"YDD", UCURR_COMMON
|UCURR_DEPRECATED
},
997 {"YER", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
998 {"YUD", UCURR_COMMON
|UCURR_DEPRECATED
},
999 {"YUM", UCURR_COMMON
|UCURR_DEPRECATED
},
1000 {"YUN", UCURR_COMMON
|UCURR_DEPRECATED
},
1001 {"ZAL", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1002 {"ZAR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1003 {"ZMK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1004 {"ZRN", UCURR_COMMON
|UCURR_DEPRECATED
},
1005 {"ZRZ", UCURR_COMMON
|UCURR_DEPRECATED
},
1006 {"ZWD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1007 { NULL
, 0 } // Leave here to denote the end of the list.
1010 #define UCURR_MATCHES_BITMASK(variable, typeToMatch) \
1011 ((typeToMatch) == UCURR_ALL || ((variable) & (typeToMatch)) == (typeToMatch))
1013 static int32_t U_CALLCONV
1014 ucurr_countCurrencyList(UEnumeration
*enumerator
, UErrorCode
* /*pErrorCode*/) {
1015 UCurrencyContext
*myContext
= (UCurrencyContext
*)(enumerator
->context
);
1016 uint32_t currType
= myContext
->currType
;
1019 /* Count the number of items matching the type we are looking for. */
1020 for (int32_t idx
= 0; gCurrencyList
[idx
].currency
!= NULL
; idx
++) {
1021 if (UCURR_MATCHES_BITMASK(gCurrencyList
[idx
].currType
, currType
)) {
1028 static const char* U_CALLCONV
1029 ucurr_nextCurrencyList(UEnumeration
*enumerator
,
1030 int32_t* resultLength
,
1031 UErrorCode
* /*pErrorCode*/)
1033 UCurrencyContext
*myContext
= (UCurrencyContext
*)(enumerator
->context
);
1035 /* Find the next in the list that matches the type we are looking for. */
1036 while (myContext
->listIdx
< (sizeof(gCurrencyList
)/sizeof(gCurrencyList
[0]))-1) {
1037 const struct CurrencyList
*currItem
= &gCurrencyList
[myContext
->listIdx
++];
1038 if (UCURR_MATCHES_BITMASK(currItem
->currType
, myContext
->currType
))
1041 *resultLength
= 3; /* Currency codes are only 3 chars long */
1043 return currItem
->currency
;
1046 /* We enumerated too far. */
1053 static void U_CALLCONV
1054 ucurr_resetCurrencyList(UEnumeration
*enumerator
, UErrorCode
* /*pErrorCode*/) {
1055 ((UCurrencyContext
*)(enumerator
->context
))->listIdx
= 0;
1058 static void U_CALLCONV
1059 ucurr_closeCurrencyList(UEnumeration
*enumerator
) {
1060 uprv_free(enumerator
->context
);
1061 uprv_free(enumerator
);
1064 static const UEnumeration gEnumCurrencyList
= {
1067 ucurr_closeCurrencyList
,
1068 ucurr_countCurrencyList
,
1070 ucurr_nextCurrencyList
,
1071 ucurr_resetCurrencyList
1075 U_CAPI UEnumeration
* U_EXPORT2
1076 ucurr_openISOCurrencies(uint32_t currType
, UErrorCode
*pErrorCode
) {
1077 UEnumeration
*myEnum
= NULL
;
1078 UCurrencyContext
*myContext
;
1080 myEnum
= (UEnumeration
*)uprv_malloc(sizeof(UEnumeration
));
1081 if (myEnum
== NULL
) {
1082 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
1085 uprv_memcpy(myEnum
, &gEnumCurrencyList
, sizeof(UEnumeration
));
1086 myContext
= (UCurrencyContext
*)uprv_malloc(sizeof(UCurrencyContext
));
1087 if (myContext
== NULL
) {
1088 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
1092 myContext
->currType
= currType
;
1093 myContext
->listIdx
= 0;
1094 myEnum
->context
= myContext
;
1098 #endif /* #if !UCONFIG_NO_FORMATTING */