2 **********************************************************************
3 * Copyright (c) 2002-2008, 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"
27 //------------------------------------------------------------
30 // Default currency meta data of last resort. We try to use the
31 // defaults encoded in the meta data resource bundle. If there is a
32 // configuration/build error and these are not available, we use these
33 // hard-coded defaults (which should be identical).
34 static const int32_t LAST_RESORT_DATA
[] = { 2, 0 };
36 // POW10[i] = 10^i, i=0..MAX_POW10
37 static const int32_t POW10
[] = { 1, 10, 100, 1000, 10000, 100000,
38 1000000, 10000000, 100000000, 1000000000 };
40 static const int32_t MAX_POW10
= (sizeof(POW10
)/sizeof(POW10
[0])) - 1;
42 #define ISO_COUNTRY_CODE_LENGTH 3
44 //------------------------------------------------------------
48 static const char CURRENCY_DATA
[] = "supplementalData";
49 // Tag for meta-data, in root.
50 static const char CURRENCY_META
[] = "CurrencyMeta";
52 // Tag for map from countries to currencies, in root.
53 static const char CURRENCY_MAP
[] = "CurrencyMap";
55 // Tag for default meta-data, in CURRENCY_META
56 static const char DEFAULT_META
[] = "DEFAULT";
58 // Variant for legacy pre-euro mapping in CurrencyMap
59 static const char VAR_PRE_EURO
[] = "PREEURO";
61 // Variant for legacy euro mapping in CurrencyMap
62 static const char VAR_EURO
[] = "EURO";
65 static const char VAR_DELIM
= '_';
66 static const char VAR_DELIM_STR
[] = "_";
68 // Variant for legacy euro mapping in CurrencyMap
69 //static const char VAR_DELIM_EURO[] = "_EURO";
71 #define VARIANT_IS_EMPTY 0
72 #define VARIANT_IS_EURO 0x1
73 #define VARIANT_IS_PREEURO 0x2
75 // Tag for localized display names (symbols) of currencies
76 static const char CURRENCIES
[] = "Currencies";
78 // Marker character indicating that a display name is a ChoiceFormat
79 // pattern. Strings that start with one mark are ChoiceFormat
80 // patterns. Strings that start with 2 marks are static strings, and
81 // the first mark is deleted.
82 static const UChar CHOICE_FORMAT_MARK
= 0x003D; // Equals sign
84 static const UChar EUR_STR
[] = {0x0045,0x0055,0x0052,0};
86 //------------------------------------------------------------
90 * Unfortunately, we have to convert the UChar* currency code to char*
91 * to use it as a resource key.
94 myUCharsToChars(char* resultOfLen4
, const UChar
* currency
) {
95 u_UCharsToChars(currency
, resultOfLen4
, ISO_COUNTRY_CODE_LENGTH
);
96 resultOfLen4
[ISO_COUNTRY_CODE_LENGTH
] = 0;
101 * Internal function to look up currency data. Result is an array of
102 * two integers. The first is the fraction digits. The second is the
103 * rounding increment, or 0 if none. The rounding increment is in
104 * units of 10^(-fraction_digits).
106 static const int32_t*
107 _findMetaData(const UChar
* currency
, UErrorCode
& ec
) {
109 if (currency
== 0 || *currency
== 0) {
111 ec
= U_ILLEGAL_ARGUMENT_ERROR
;
113 return LAST_RESORT_DATA
;
116 // Get CurrencyMeta resource out of root locale file. [This may
117 // move out of the root locale file later; if it does, update this
119 UResourceBundle
* currencyData
= ures_openDirect(NULL
, CURRENCY_DATA
, &ec
);
120 UResourceBundle
* currencyMeta
= ures_getByKey(currencyData
, CURRENCY_META
, currencyData
, &ec
);
123 ures_close(currencyMeta
);
124 // Config/build error; return hard-coded defaults
125 return LAST_RESORT_DATA
;
128 // Look up our currency, or if that's not available, then DEFAULT
129 char buf
[ISO_COUNTRY_CODE_LENGTH
+1];
130 UErrorCode ec2
= U_ZERO_ERROR
; // local error code: soft failure
131 UResourceBundle
* rb
= ures_getByKey(currencyMeta
, myUCharsToChars(buf
, currency
), NULL
, &ec2
);
132 if (U_FAILURE(ec2
)) {
134 rb
= ures_getByKey(currencyMeta
,DEFAULT_META
, NULL
, &ec
);
136 ures_close(currencyMeta
);
138 // Config/build error; return hard-coded defaults
139 return LAST_RESORT_DATA
;
144 const int32_t *data
= ures_getIntVector(rb
, &len
, &ec
);
145 if (U_FAILURE(ec
) || len
!= 2) {
146 // Config/build error; return hard-coded defaults
148 ec
= U_INVALID_FORMAT_ERROR
;
150 ures_close(currencyMeta
);
152 return LAST_RESORT_DATA
;
155 ures_close(currencyMeta
);
160 // -------------------------------------
163 * @see VARIANT_IS_EURO
164 * @see VARIANT_IS_PREEURO
167 idForLocale(const char* locale
, char* countryAndVariant
, int capacity
, UErrorCode
* ec
)
169 uint32_t variantType
= 0;
170 // !!! this is internal only, assumes buffer is not null and capacity is sufficient
171 // Extract the country name and variant name. We only
172 // recognize two variant names, EURO and PREEURO.
173 char variant
[ULOC_FULLNAME_CAPACITY
];
174 uloc_getCountry(locale
, countryAndVariant
, capacity
, ec
);
175 uloc_getVariant(locale
, variant
, sizeof(variant
), ec
);
176 if (variant
[0] != 0) {
177 variantType
= (0 == uprv_strcmp(variant
, VAR_EURO
))
178 | ((0 == uprv_strcmp(variant
, VAR_PRE_EURO
)) << 1);
181 uprv_strcat(countryAndVariant
, VAR_DELIM_STR
);
182 uprv_strcat(countryAndVariant
, variant
);
188 // ------------------------------------------
192 //-------------------------------------------
194 // don't use ICUService since we don't need fallback
196 #if !UCONFIG_NO_SERVICE
198 static UBool U_CALLCONV
currency_cleanup(void);
202 /* Remember to call umtx_init(&gCRegLock) before using it! */
203 static UMTX gCRegLock
= 0;
204 static CReg
* gCRegHead
= 0;
206 struct CReg
: public U_NAMESPACE_QUALIFIER UMemory
{
208 UChar iso
[ISO_COUNTRY_CODE_LENGTH
+1];
209 char id
[ULOC_FULLNAME_CAPACITY
];
211 CReg(const UChar
* _iso
, const char* _id
)
214 int32_t len
= (int32_t)uprv_strlen(_id
);
215 if (len
> (int32_t)(sizeof(id
)-1)) {
216 len
= (sizeof(id
)-1);
218 uprv_strncpy(id
, _id
, len
);
220 uprv_memcpy(iso
, _iso
, ISO_COUNTRY_CODE_LENGTH
* sizeof(const UChar
));
221 iso
[ISO_COUNTRY_CODE_LENGTH
] = 0;
224 static UCurrRegistryKey
reg(const UChar
* _iso
, const char* _id
, UErrorCode
* status
)
226 if (status
&& U_SUCCESS(*status
) && _iso
&& _id
) {
227 CReg
* n
= new CReg(_iso
, _id
);
229 umtx_init(&gCRegLock
);
230 umtx_lock(&gCRegLock
);
232 /* register for the first time */
233 ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY
, currency_cleanup
);
237 umtx_unlock(&gCRegLock
);
240 *status
= U_MEMORY_ALLOCATION_ERROR
;
245 static UBool
unreg(UCurrRegistryKey key
) {
247 umtx_init(&gCRegLock
);
248 umtx_lock(&gCRegLock
);
250 CReg
** p
= &gCRegHead
;
253 *p
= ((CReg
*)key
)->next
;
261 umtx_unlock(&gCRegLock
);
265 static const UChar
* get(const char* id
) {
266 const UChar
* result
= NULL
;
267 umtx_init(&gCRegLock
);
268 umtx_lock(&gCRegLock
);
271 /* register cleanup of the mutex */
272 ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY
, currency_cleanup
);
274 if (uprv_strcmp(id
, p
->id
) == 0) {
280 umtx_unlock(&gCRegLock
);
284 /* This doesn't need to be thread safe. It's for u_cleanup only. */
285 static void cleanup(void) {
288 gCRegHead
= gCRegHead
->next
;
291 umtx_destroy(&gCRegLock
);
296 * Release all static memory held by currency.
299 static UBool U_CALLCONV
currency_cleanup(void) {
300 #if !UCONFIG_NO_SERVICE
307 // -------------------------------------
309 U_CAPI UCurrRegistryKey U_EXPORT2
310 ucurr_register(const UChar
* isoCode
, const char* locale
, UErrorCode
*status
)
312 if (status
&& U_SUCCESS(*status
)) {
313 char id
[ULOC_FULLNAME_CAPACITY
];
314 idForLocale(locale
, id
, sizeof(id
), status
);
315 return CReg::reg(isoCode
, id
, status
);
320 // -------------------------------------
322 U_CAPI UBool U_EXPORT2
323 ucurr_unregister(UCurrRegistryKey key
, UErrorCode
* status
)
325 if (status
&& U_SUCCESS(*status
)) {
326 return CReg::unreg(key
);
330 #endif /* UCONFIG_NO_SERVICE */
332 // -------------------------------------
334 U_CAPI
int32_t U_EXPORT2
335 ucurr_forLocale(const char* locale
,
337 int32_t buffCapacity
,
341 const UChar
* s
= NULL
;
342 if (ec
!= NULL
&& U_SUCCESS(*ec
)) {
343 if ((buff
&& buffCapacity
) || !buffCapacity
) {
344 UErrorCode localStatus
= U_ZERO_ERROR
;
345 char id
[ULOC_FULLNAME_CAPACITY
];
346 if ((resLen
= uloc_getKeywordValue(locale
, "currency", id
, ULOC_FULLNAME_CAPACITY
, &localStatus
))) {
347 // there is a currency keyword. Try to see if it's valid
348 if(buffCapacity
> resLen
) {
349 u_charsToUChars(id
, buff
, resLen
);
352 // get country or country_variant in `id'
353 uint32_t variantType
= idForLocale(locale
, id
, sizeof(id
), ec
);
355 if (U_FAILURE(*ec
)) {
359 #if !UCONFIG_NO_SERVICE
360 const UChar
* result
= CReg::get(id
);
362 if(buffCapacity
> u_strlen(result
)) {
363 u_strcpy(buff
, result
);
365 return u_strlen(result
);
368 // Remove variants, which is only needed for registration.
369 char *idDelim
= strchr(id
, VAR_DELIM
);
374 // Look up the CurrencyMap element in the root bundle.
375 UResourceBundle
*rb
= ures_openDirect(NULL
, CURRENCY_DATA
, &localStatus
);
376 UResourceBundle
*cm
= ures_getByKey(rb
, CURRENCY_MAP
, rb
, &localStatus
);
377 UResourceBundle
*countryArray
= ures_getByKey(rb
, id
, cm
, &localStatus
);
378 UResourceBundle
*currencyReq
= ures_getByIndex(countryArray
, 0, NULL
, &localStatus
);
379 s
= ures_getStringByKey(currencyReq
, "id", &resLen
, &localStatus
);
382 Get the second item when PREEURO is requested, and this is a known Euro country.
383 If the requested variant is PREEURO, and this isn't a Euro country, assume
384 that the country changed over to the Euro in the future. This is probably
385 an old version of ICU that hasn't been updated yet. The latest currency is
388 if (U_SUCCESS(localStatus
)) {
389 if ((variantType
& VARIANT_IS_PREEURO
) && u_strcmp(s
, EUR_STR
) == 0) {
390 currencyReq
= ures_getByIndex(countryArray
, 1, currencyReq
, &localStatus
);
391 s
= ures_getStringByKey(currencyReq
, "id", &resLen
, &localStatus
);
393 else if ((variantType
& VARIANT_IS_EURO
)) {
397 ures_close(countryArray
);
398 ures_close(currencyReq
);
400 if ((U_FAILURE(localStatus
)) && strchr(id
, '_') != 0)
402 // We don't know about it. Check to see if we support the variant.
403 uloc_getParent(locale
, id
, sizeof(id
), ec
);
404 *ec
= U_USING_FALLBACK_WARNING
;
405 return ucurr_forLocale(id
, buff
, buffCapacity
, ec
);
407 else if (*ec
== U_ZERO_ERROR
|| localStatus
!= U_ZERO_ERROR
) {
408 // There is nothing to fallback to. Report the failure/warning if possible.
411 if (U_SUCCESS(*ec
)) {
412 if(buffCapacity
> resLen
) {
417 return u_terminateUChars(buff
, buffCapacity
, resLen
, ec
);
419 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
428 * Modify the given locale name by removing the rightmost _-delimited
429 * element. If there is none, empty the string ("" == root).
430 * NOTE: The string "root" is not recognized; do not use it.
431 * @return TRUE if the fallback happened; FALSE if locale is already
434 static UBool
fallback(char *loc
) {
438 UErrorCode status
= U_ZERO_ERROR
;
439 uloc_getParent(loc
, loc
, (int32_t)uprv_strlen(loc
), &status
);
441 char *i = uprv_strrchr(loc, '_');
451 U_CAPI
const UChar
* U_EXPORT2
452 ucurr_getName(const UChar
* currency
,
454 UCurrNameStyle nameStyle
,
455 UBool
* isChoiceFormat
, // fillin
456 int32_t* len
, // fillin
459 // Look up the Currencies resource for the given locale. The
460 // Currencies locale data looks like this:
463 //| USD { "US$", "US Dollar" }
464 //| CHF { "Sw F", "Swiss Franc" }
465 //| INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
470 if (U_FAILURE(*ec
)) {
474 int32_t choice
= (int32_t) nameStyle
;
475 if (choice
< 0 || choice
> 1) {
476 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
480 // In the future, resource bundles may implement multi-level
481 // fallback. That is, if a currency is not found in the en_US
482 // Currencies data, then the en Currencies data will be searched.
483 // Currently, if a Currencies datum exists in en_US and en, the
484 // en_US entry hides that in en.
486 // We want multi-level fallback for this resource, so we implement
489 // Use a separate UErrorCode here that does not propagate out of
491 UErrorCode ec2
= U_ZERO_ERROR
;
493 char loc
[ULOC_FULLNAME_CAPACITY
];
494 uloc_getName(locale
, loc
, sizeof(loc
), &ec2
);
495 if (U_FAILURE(ec2
) || ec2
== U_STRING_NOT_TERMINATED_WARNING
) {
496 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
500 char buf
[ISO_COUNTRY_CODE_LENGTH
+1];
501 myUCharsToChars(buf
, currency
);
503 const UChar
* s
= NULL
;
505 UResourceBundle
* rb
= ures_open(NULL
, loc
, &ec2
);
507 rb
= ures_getByKey(rb
, CURRENCIES
, rb
, &ec2
);
509 // Fetch resource with multi-level resource inheritance fallback
510 rb
= ures_getByKeyWithFallback(rb
, buf
, rb
, &ec2
);
512 s
= ures_getStringByIndex(rb
, choice
, len
, &ec2
);
515 // If we've succeeded we're done. Otherwise, try to fallback.
516 // If that fails (because we are already at root) then exit.
517 if (U_SUCCESS(ec2
)) {
518 if (ec2
== U_USING_DEFAULT_WARNING
519 || (ec2
== U_USING_FALLBACK_WARNING
&& *ec
!= U_USING_DEFAULT_WARNING
)) {
524 // Determine if this is a ChoiceFormat pattern. One leading mark
525 // indicates a ChoiceFormat. Two indicates a static string that
526 // starts with a mark. In either case, the first mark is ignored,
527 // if present. Marks in the rest of the string have no special
529 *isChoiceFormat
= FALSE
;
530 if (U_SUCCESS(ec2
)) {
533 while (i
< *len
&& s
[i
] == CHOICE_FORMAT_MARK
&& i
< 2) {
536 *isChoiceFormat
= (i
== 1);
537 if (i
!= 0) ++s
; // Skip over first mark
541 // If we fail to find a match, use the ISO 4217 code
542 *len
= u_strlen(currency
); // Should == ISO_COUNTRY_CODE_LENGTH, but maybe not...?
543 *ec
= U_USING_DEFAULT_WARNING
;
548 uprv_parseCurrency(const char* locale
,
549 const U_NAMESPACE_QUALIFIER UnicodeString
& text
,
550 U_NAMESPACE_QUALIFIER ParsePosition
& pos
,
556 // TODO: There is a slight problem with the pseudo-multi-level
557 // fallback implemented here. More-specific locales don't
558 // properly shield duplicate entries in less-specific locales.
559 // This problem will go away when real multi-level fallback is
560 // implemented. We could also fix this by recording (in a
561 // hash) which codes are used at each level of fallback, but
562 // this doesn't seem warranted.
568 // Look up the Currencies resource for the given locale. The
569 // Currencies locale data looks like this:
572 //| USD { "US$", "US Dollar" }
573 //| CHF { "Sw F", "Swiss Franc" }
574 //| INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" }
579 // In the future, resource bundles may implement multi-level
580 // fallback. That is, if a currency is not found in the en_US
581 // Currencies data, then the en Currencies data will be searched.
582 // Currently, if a Currencies datum exists in en_US and en, the
583 // en_US entry hides that in en.
585 // We want multi-level fallback for this resource, so we implement
588 // Use a separate UErrorCode here that does not propagate out of
590 UErrorCode ec2
= U_ZERO_ERROR
;
592 char loc
[ULOC_FULLNAME_CAPACITY
];
593 uloc_getName(locale
, loc
, sizeof(loc
), &ec2
);
594 if (U_FAILURE(ec2
) || ec2
== U_STRING_NOT_TERMINATED_WARNING
) {
595 ec
= U_ILLEGAL_ARGUMENT_ERROR
;
599 int32_t start
= pos
.getIndex();
600 const UChar
* s
= NULL
;
602 const char* iso
= NULL
;
605 // Multi-level resource inheritance fallback loop
608 UResourceBundle
* rb
= ures_open(NULL
, loc
, &ec2
);
609 UResourceBundle
* curr
= ures_getByKey(rb
, CURRENCIES
, NULL
, &ec2
);
610 int32_t n
= ures_getSize(curr
);
611 for (int32_t i
=0; i
<n
; ++i
) {
612 UResourceBundle
* names
= ures_getByIndex(curr
, i
, NULL
, &ec2
);
614 s
= ures_getStringByIndex(names
, UCURR_SYMBOL_NAME
, &len
, &ec2
);
615 UBool isChoice
= FALSE
;
616 if (len
> 0 && s
[0] == CHOICE_FORMAT_MARK
) {
619 if (len
> 0 && s
[0] != CHOICE_FORMAT_MARK
) {
625 ChoiceFormat
fmt(s
, ec2
);
626 fmt
.parse(text
, temp
, pos
);
627 len
= pos
.getIndex() - start
;
629 } else if (len
> max
&&
630 text
.compare(pos
.getIndex(), len
, s
) != 0) {
634 iso
= ures_getKey(names
);
642 // Try to fallback. If that fails (because we are already at
644 if (!fallback(loc
)) {
650 u_charsToUChars(iso
, result
, 4);
653 // If display name parse fails or if it matches fewer than 3
654 // characters, try to parse 3-letter ISO. Do this after the
655 // display name processing so 3-letter display names are
656 // preferred. Consider /[A-Z]{3}/ to be valid ISO, and parse
657 // it manually--UnicodeSet/regex are too slow and heavy.
658 if (max
< 3 && (text
.length() - start
) >= 3) {
660 for (int32_t k
=0; k
<3; ++k
) {
661 UChar ch
= text
.charAt(start
+ k
); // 16-bit ok
662 if (ch
< 0x41/*'A'*/ || ch
> 0x5A/*'Z'*/) {
668 text
.extract(start
, 3, result
);
674 pos
.setIndex(start
+ max
);
678 * Internal method. Given a currency ISO code and a locale, return
679 * the "static" currency name. This is usually the same as the
680 * UCURR_SYMBOL_NAME, but if the latter is a choice format, then the
681 * format is applied to the number 2.0 (to yield the more common
682 * plural) to return a static name.
684 * This is used for backward compatibility with old currency logic in
685 * DecimalFormat and DecimalFormatSymbols.
688 uprv_getStaticCurrencyName(const UChar
* iso
, const char* loc
,
689 U_NAMESPACE_QUALIFIER UnicodeString
& result
, UErrorCode
& ec
)
693 UBool isChoiceFormat
;
695 const UChar
* currname
= ucurr_getName(iso
, loc
, UCURR_SYMBOL_NAME
,
696 &isChoiceFormat
, &len
, &ec
);
698 // If this is a ChoiceFormat currency, then format an
699 // arbitrary value; pick something != 1; more common.
701 if (isChoiceFormat
) {
702 ChoiceFormat
f(currname
, ec
);
704 f
.format(2.0, result
);
714 U_CAPI
int32_t U_EXPORT2
715 ucurr_getDefaultFractionDigits(const UChar
* currency
, UErrorCode
* ec
) {
716 return (_findMetaData(currency
, *ec
))[0];
719 U_CAPI
double U_EXPORT2
720 ucurr_getRoundingIncrement(const UChar
* currency
, UErrorCode
* ec
) {
721 const int32_t *data
= _findMetaData(currency
, *ec
);
723 // If the meta data is invalid, return 0.0.
724 if (data
[0] < 0 || data
[0] > MAX_POW10
) {
725 if (U_SUCCESS(*ec
)) {
726 *ec
= U_INVALID_FORMAT_ERROR
;
731 // If there is no rounding, return 0.0 to indicate no rounding. A
732 // rounding value (data[1]) of 0 or 1 indicates no rounding.
737 // Return data[1] / 10^(data[0]). The only actual rounding data,
738 // as of this writing, is CHF { 2, 5 }.
739 return double(data
[1]) / POW10
[data
[0]];
744 typedef struct UCurrencyContext
{
745 uint32_t currType
; /* UCurrCurrencyType */
750 Please keep this list in alphabetical order.
751 You can look at the CLDR supplemental data or ISO-4217 for the meaning of some
753 ISO-4217: http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html
755 static const struct CurrencyList
{
756 const char *currency
;
758 } gCurrencyList
[] = {
759 {"ADP", UCURR_COMMON
|UCURR_DEPRECATED
},
760 {"AED", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
761 {"AFA", UCURR_COMMON
|UCURR_DEPRECATED
},
762 {"AFN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
763 {"ALK", UCURR_COMMON
|UCURR_DEPRECATED
},
764 {"ALL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
765 {"AMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
766 {"ANG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
767 {"AOA", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
768 {"AOK", UCURR_COMMON
|UCURR_DEPRECATED
},
769 {"AON", UCURR_COMMON
|UCURR_DEPRECATED
},
770 {"AOR", UCURR_COMMON
|UCURR_DEPRECATED
},
771 {"ARA", UCURR_COMMON
|UCURR_DEPRECATED
},
772 {"ARP", UCURR_COMMON
|UCURR_DEPRECATED
},
773 {"ARS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
774 {"ATS", UCURR_COMMON
|UCURR_DEPRECATED
},
775 {"AUD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
776 {"AWG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
777 {"AZM", UCURR_COMMON
|UCURR_DEPRECATED
},
778 {"AZN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
779 {"BAD", UCURR_COMMON
|UCURR_DEPRECATED
},
780 {"BAM", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
781 {"BBD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
782 {"BDT", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
783 {"BEC", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
784 {"BEF", UCURR_COMMON
|UCURR_DEPRECATED
},
785 {"BEL", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
786 {"BGL", UCURR_COMMON
|UCURR_DEPRECATED
},
787 {"BGM", UCURR_COMMON
|UCURR_DEPRECATED
},
788 {"BGN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
789 {"BHD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
790 {"BIF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
791 {"BMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
792 {"BND", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
793 {"BOB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
794 {"BOP", UCURR_COMMON
|UCURR_DEPRECATED
},
795 {"BOV", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
796 {"BRB", UCURR_COMMON
|UCURR_DEPRECATED
},
797 {"BRC", UCURR_COMMON
|UCURR_DEPRECATED
},
798 {"BRE", UCURR_COMMON
|UCURR_DEPRECATED
},
799 {"BRL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
800 {"BRN", UCURR_COMMON
|UCURR_DEPRECATED
},
801 {"BRR", UCURR_COMMON
|UCURR_DEPRECATED
},
802 {"BSD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
803 {"BTN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
804 {"BUK", UCURR_COMMON
|UCURR_DEPRECATED
},
805 {"BWP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
806 {"BYB", UCURR_COMMON
|UCURR_DEPRECATED
},
807 {"BYR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
808 {"BZD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
809 {"CAD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
810 {"CDF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
811 {"CHE", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
812 {"CHF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
813 {"CHW", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
814 {"CLF", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
815 {"CLP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
816 {"CNX", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
817 {"CNY", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
818 {"COP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
819 {"COU", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
820 {"CRC", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
821 {"CSD", UCURR_COMMON
|UCURR_DEPRECATED
},
822 {"CSK", UCURR_COMMON
|UCURR_DEPRECATED
},
823 {"CUP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
824 {"CVE", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
825 {"CYP", UCURR_COMMON
|UCURR_DEPRECATED
},
826 {"CZK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
827 {"DDM", UCURR_COMMON
|UCURR_DEPRECATED
},
828 {"DEM", UCURR_COMMON
|UCURR_DEPRECATED
},
829 {"DJF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
830 {"DKK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
831 {"DOP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
832 {"DZD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
833 {"ECS", UCURR_COMMON
|UCURR_DEPRECATED
},
834 {"ECV", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
835 {"EEK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
836 {"EGP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
837 {"EQE", UCURR_COMMON
|UCURR_DEPRECATED
},
838 {"ERN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
839 {"ESA", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
840 {"ESB", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
841 {"ESP", UCURR_COMMON
|UCURR_DEPRECATED
},
842 {"ETB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
843 {"EUR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
844 {"FIM", UCURR_COMMON
|UCURR_DEPRECATED
},
845 {"FJD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
846 {"FKP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
847 {"FRF", UCURR_COMMON
|UCURR_DEPRECATED
},
848 {"GBP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
849 {"GEK", UCURR_COMMON
|UCURR_DEPRECATED
},
850 {"GEL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
851 {"GHC", UCURR_COMMON
|UCURR_DEPRECATED
},
852 {"GHS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
853 {"GIP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
854 {"GMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
855 {"GNF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
856 {"GNS", UCURR_COMMON
|UCURR_DEPRECATED
},
857 {"GQE", UCURR_COMMON
|UCURR_DEPRECATED
},
858 {"GRD", UCURR_COMMON
|UCURR_DEPRECATED
},
859 {"GTQ", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
860 {"GWE", UCURR_COMMON
|UCURR_DEPRECATED
},
861 {"GWP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
862 {"GYD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
863 {"HKD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
864 {"HNL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
865 {"HRD", UCURR_COMMON
|UCURR_DEPRECATED
},
866 {"HRK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
867 {"HTG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
868 {"HUF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
869 {"IDR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
870 {"IEP", UCURR_COMMON
|UCURR_DEPRECATED
},
871 {"ILP", UCURR_COMMON
|UCURR_DEPRECATED
},
872 {"ILS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
873 {"INR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
874 {"IQD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
875 {"IRR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
876 {"ISK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
877 {"ITL", UCURR_COMMON
|UCURR_DEPRECATED
},
878 {"JMD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
879 {"JOD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
880 {"JPY", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
881 {"KES", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
882 {"KGS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
883 {"KHR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
884 {"KMF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
885 {"KPW", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
886 {"KRW", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
887 {"KWD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
888 {"KYD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
889 {"KZT", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
890 {"LAK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
891 {"LBP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
892 {"LKR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
893 {"LRD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
894 {"LSL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
895 {"LSM", UCURR_COMMON
|UCURR_DEPRECATED
},
896 {"LTL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
897 {"LTT", UCURR_COMMON
|UCURR_DEPRECATED
},
898 {"LUC", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
899 {"LUF", UCURR_COMMON
|UCURR_DEPRECATED
},
900 {"LUL", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
901 {"LVL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
902 {"LVR", UCURR_COMMON
|UCURR_DEPRECATED
},
903 {"LYD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
904 {"MAD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
905 {"MAF", UCURR_COMMON
|UCURR_DEPRECATED
},
906 {"MDL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
907 {"MGA", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
908 {"MGF", UCURR_COMMON
|UCURR_DEPRECATED
},
909 {"MKD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
910 {"MLF", UCURR_COMMON
|UCURR_DEPRECATED
},
911 {"MMK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
912 {"MNT", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
913 {"MOP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
914 {"MRO", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
915 {"MTL", UCURR_COMMON
|UCURR_DEPRECATED
},
916 {"MTP", UCURR_COMMON
|UCURR_DEPRECATED
},
917 {"MUR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
918 {"MVR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
919 {"MWK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
920 {"MXN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
921 {"MXP", UCURR_COMMON
|UCURR_DEPRECATED
},
922 {"MXV", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
923 {"MYR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
924 {"MZE", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
925 {"MZM", UCURR_COMMON
|UCURR_DEPRECATED
},
926 {"MZN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
927 {"NAD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
928 {"NGN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
929 {"NIC", UCURR_COMMON
|UCURR_DEPRECATED
},
930 {"NIO", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
931 {"NLG", UCURR_COMMON
|UCURR_DEPRECATED
},
932 {"NOK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
933 {"NPR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
934 {"NZD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
935 {"OMR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
936 {"PAB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
937 {"PEI", UCURR_COMMON
|UCURR_DEPRECATED
},
938 {"PEN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
939 {"PES", UCURR_COMMON
|UCURR_DEPRECATED
},
940 {"PGK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
941 {"PHP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
942 {"PKR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
943 {"PLN", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
944 {"PLZ", UCURR_COMMON
|UCURR_DEPRECATED
},
945 {"PTE", UCURR_COMMON
|UCURR_DEPRECATED
},
946 {"PYG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
947 {"QAR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
948 {"RHD", UCURR_COMMON
|UCURR_DEPRECATED
},
949 {"ROL", UCURR_COMMON
|UCURR_DEPRECATED
},
950 {"RON", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
951 {"RSD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
952 {"RUB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
953 {"RUR", UCURR_COMMON
|UCURR_DEPRECATED
},
954 {"RWF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
955 {"SAR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
956 {"SBD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
957 {"SCR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
958 {"SDD", UCURR_COMMON
|UCURR_DEPRECATED
},
959 {"SDG", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
960 {"SDP", UCURR_COMMON
|UCURR_DEPRECATED
},
961 {"SEK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
962 {"SGD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
963 {"SHP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
964 {"SIT", UCURR_COMMON
|UCURR_DEPRECATED
},
965 {"SKK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
966 {"SLL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
967 {"SOS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
968 {"SRD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
969 {"SRG", UCURR_COMMON
|UCURR_DEPRECATED
},
970 {"STD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
971 {"SUR", UCURR_COMMON
|UCURR_DEPRECATED
},
972 {"SVC", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
973 {"SYP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
974 {"SZL", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
975 {"THB", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
976 {"TJR", UCURR_COMMON
|UCURR_DEPRECATED
},
977 {"TJS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
978 {"TMM", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
979 {"TND", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
980 {"TOP", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
981 {"TPE", UCURR_COMMON
|UCURR_DEPRECATED
},
982 {"TRL", UCURR_COMMON
|UCURR_DEPRECATED
},
983 {"TRY", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
984 {"TTD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
985 {"TWD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
986 {"TZS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
987 {"UAH", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
988 {"UAK", UCURR_COMMON
|UCURR_DEPRECATED
},
989 {"UGS", UCURR_COMMON
|UCURR_DEPRECATED
},
990 {"UGX", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
991 {"USD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
992 {"USN", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
993 {"USS", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
994 {"UYP", UCURR_COMMON
|UCURR_DEPRECATED
},
995 {"UYI", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
996 {"UYU", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
997 {"UZS", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
998 {"VEB", UCURR_COMMON
|UCURR_DEPRECATED
},
999 {"VEF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1000 {"VND", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1001 {"VUV", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1002 {"WST", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1003 {"XAF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1004 {"XAG", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1005 {"XAU", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1006 {"XBA", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1007 {"XBB", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1008 {"XBC", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1009 {"XBD", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1010 {"XCD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1011 {"XDR", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1012 {"XEU", UCURR_UNCOMMON
|UCURR_DEPRECATED
},
1013 {"XFO", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1014 {"XFU", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1015 {"XOF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1016 {"XPD", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1017 {"XPF", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1018 {"XPT", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1019 {"XRE", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1020 {"XTS", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1021 {"XXX", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1022 {"YDD", UCURR_COMMON
|UCURR_DEPRECATED
},
1023 {"YER", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1024 {"YUD", UCURR_COMMON
|UCURR_DEPRECATED
},
1025 {"YUM", UCURR_COMMON
|UCURR_DEPRECATED
},
1026 {"YUN", UCURR_COMMON
|UCURR_DEPRECATED
},
1027 {"ZAL", UCURR_UNCOMMON
|UCURR_NON_DEPRECATED
},
1028 {"ZAR", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1029 {"ZMK", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1030 {"ZRN", UCURR_COMMON
|UCURR_DEPRECATED
},
1031 {"ZRZ", UCURR_COMMON
|UCURR_DEPRECATED
},
1032 {"ZWD", UCURR_COMMON
|UCURR_NON_DEPRECATED
},
1033 { NULL
, 0 } // Leave here to denote the end of the list.
1036 #define UCURR_MATCHES_BITMASK(variable, typeToMatch) \
1037 ((typeToMatch) == UCURR_ALL || ((variable) & (typeToMatch)) == (typeToMatch))
1039 static int32_t U_CALLCONV
1040 ucurr_countCurrencyList(UEnumeration
*enumerator
, UErrorCode
* /*pErrorCode*/) {
1041 UCurrencyContext
*myContext
= (UCurrencyContext
*)(enumerator
->context
);
1042 uint32_t currType
= myContext
->currType
;
1045 /* Count the number of items matching the type we are looking for. */
1046 for (int32_t idx
= 0; gCurrencyList
[idx
].currency
!= NULL
; idx
++) {
1047 if (UCURR_MATCHES_BITMASK(gCurrencyList
[idx
].currType
, currType
)) {
1054 static const char* U_CALLCONV
1055 ucurr_nextCurrencyList(UEnumeration
*enumerator
,
1056 int32_t* resultLength
,
1057 UErrorCode
* /*pErrorCode*/)
1059 UCurrencyContext
*myContext
= (UCurrencyContext
*)(enumerator
->context
);
1061 /* Find the next in the list that matches the type we are looking for. */
1062 while (myContext
->listIdx
< (sizeof(gCurrencyList
)/sizeof(gCurrencyList
[0]))-1) {
1063 const struct CurrencyList
*currItem
= &gCurrencyList
[myContext
->listIdx
++];
1064 if (UCURR_MATCHES_BITMASK(currItem
->currType
, myContext
->currType
))
1067 *resultLength
= 3; /* Currency codes are only 3 chars long */
1069 return currItem
->currency
;
1072 /* We enumerated too far. */
1079 static void U_CALLCONV
1080 ucurr_resetCurrencyList(UEnumeration
*enumerator
, UErrorCode
* /*pErrorCode*/) {
1081 ((UCurrencyContext
*)(enumerator
->context
))->listIdx
= 0;
1084 static void U_CALLCONV
1085 ucurr_closeCurrencyList(UEnumeration
*enumerator
) {
1086 uprv_free(enumerator
->context
);
1087 uprv_free(enumerator
);
1090 static const UEnumeration gEnumCurrencyList
= {
1093 ucurr_closeCurrencyList
,
1094 ucurr_countCurrencyList
,
1096 ucurr_nextCurrencyList
,
1097 ucurr_resetCurrencyList
1101 U_CAPI UEnumeration
* U_EXPORT2
1102 ucurr_openISOCurrencies(uint32_t currType
, UErrorCode
*pErrorCode
) {
1103 UEnumeration
*myEnum
= NULL
;
1104 UCurrencyContext
*myContext
;
1106 myEnum
= (UEnumeration
*)uprv_malloc(sizeof(UEnumeration
));
1107 if (myEnum
== NULL
) {
1108 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
1111 uprv_memcpy(myEnum
, &gEnumCurrencyList
, sizeof(UEnumeration
));
1112 myContext
= (UCurrencyContext
*)uprv_malloc(sizeof(UCurrencyContext
));
1113 if (myContext
== NULL
) {
1114 *pErrorCode
= U_MEMORY_ALLOCATION_ERROR
;
1118 myContext
->currType
= currType
;
1119 myContext
->listIdx
= 0;
1120 myEnum
->context
= myContext
;
1124 U_CAPI
int32_t U_EXPORT2
1125 ucurr_countCurrencies(const char* locale
,
1129 int32_t currCount
= 0;
1131 const UChar
* s
= NULL
;
1133 if (ec
!= NULL
&& U_SUCCESS(*ec
))
1136 UErrorCode localStatus
= U_ZERO_ERROR
;
1137 char id
[ULOC_FULLNAME_CAPACITY
];
1138 resLen
= uloc_getKeywordValue(locale
, "currency", id
, ULOC_FULLNAME_CAPACITY
, &localStatus
);
1140 // get country or country_variant in `id'
1141 uint32_t variantType
= idForLocale(locale
, id
, sizeof(id
), ec
);
1147 // Remove variants, which is only needed for registration.
1148 char *idDelim
= strchr(id
, VAR_DELIM
);
1154 // Look up the CurrencyMap element in the root bundle.
1155 UResourceBundle
*rb
= ures_openDirect(NULL
, CURRENCY_DATA
, &localStatus
);
1156 UResourceBundle
*cm
= ures_getByKey(rb
, CURRENCY_MAP
, rb
, &localStatus
);
1158 // Using the id derived from the local, get the currency data
1159 UResourceBundle
*countryArray
= ures_getByKey(rb
, id
, cm
, &localStatus
);
1161 // process each currency to see which one is valid for the given date
1162 if (U_SUCCESS(localStatus
))
1164 for (int32_t i
=0; i
<ures_getSize(countryArray
); i
++)
1166 // get the currency resource
1167 UResourceBundle
*currencyRes
= ures_getByIndex(countryArray
, i
, NULL
, &localStatus
);
1168 s
= ures_getStringByKey(currencyRes
, "id", &resLen
, &localStatus
);
1170 // get the from date
1171 int32_t fromLength
= 0;
1172 UResourceBundle
*fromRes
= ures_getByKey(currencyRes
, "from", NULL
, &localStatus
);
1173 const int32_t *fromArray
= ures_getIntVector(fromRes
, &fromLength
, &localStatus
);
1175 int64_t currDate64
= (int64_t)fromArray
[0] << 32;
1176 currDate64
|= ((int64_t)fromArray
[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
1177 UDate fromDate
= (UDate
)currDate64
;
1179 if (ures_getSize(currencyRes
) > 2)
1181 int32_t toLength
= 0;
1182 UResourceBundle
*toRes
= ures_getByKey(currencyRes
, "to", NULL
, &localStatus
);
1183 const int32_t *toArray
= ures_getIntVector(toRes
, &toLength
, &localStatus
);
1185 currDate64
= (int64_t)toArray
[0] << 32;
1186 currDate64
|= ((int64_t)toArray
[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
1187 UDate toDate
= (UDate
)currDate64
;
1189 if ((fromDate
<= date
) && (date
< toDate
))
1198 if (fromDate
<= date
)
1204 // close open resources
1205 ures_close(currencyRes
);
1206 ures_close(fromRes
);
1209 } // end if (U_SUCCESS(localStatus))
1211 ures_close(countryArray
);
1214 if (*ec
== U_ZERO_ERROR
|| localStatus
!= U_ZERO_ERROR
)
1216 // There is nothing to fallback to.
1217 // Report the failure/warning if possible.
1229 // If we got here, either error code is invalid or
1230 // some argument passed is no good.
1234 U_CAPI
int32_t U_EXPORT2
1235 ucurr_forLocaleAndDate(const char* locale
,
1239 int32_t buffCapacity
,
1243 int32_t currIndex
= 0;
1244 const UChar
* s
= NULL
;
1246 if (ec
!= NULL
&& U_SUCCESS(*ec
))
1248 // check the arguments passed
1249 if ((buff
&& buffCapacity
) || !buffCapacity
)
1252 UErrorCode localStatus
= U_ZERO_ERROR
;
1253 char id
[ULOC_FULLNAME_CAPACITY
];
1254 resLen
= uloc_getKeywordValue(locale
, "currency", id
, ULOC_FULLNAME_CAPACITY
, &localStatus
);
1256 // get country or country_variant in `id'
1257 uint32_t variantType
= idForLocale(locale
, id
, sizeof(id
), ec
);
1263 // Remove variants, which is only needed for registration.
1264 char *idDelim
= strchr(id
, VAR_DELIM
);
1270 // Look up the CurrencyMap element in the root bundle.
1271 UResourceBundle
*rb
= ures_openDirect(NULL
, CURRENCY_DATA
, &localStatus
);
1272 UResourceBundle
*cm
= ures_getByKey(rb
, CURRENCY_MAP
, rb
, &localStatus
);
1274 // Using the id derived from the local, get the currency data
1275 UResourceBundle
*countryArray
= ures_getByKey(rb
, id
, cm
, &localStatus
);
1277 // process each currency to see which one is valid for the given date
1278 bool matchFound
= false;
1279 if (U_SUCCESS(localStatus
))
1281 if ((index
<= 0) || (index
> ures_getSize(countryArray
)))
1283 // requested index is out of bounds
1284 ures_close(countryArray
);
1288 for (int32_t i
=0; i
<ures_getSize(countryArray
); i
++)
1290 // get the currency resource
1291 UResourceBundle
*currencyRes
= ures_getByIndex(countryArray
, i
, NULL
, &localStatus
);
1292 s
= ures_getStringByKey(currencyRes
, "id", &resLen
, &localStatus
);
1294 // get the from date
1295 int32_t fromLength
= 0;
1296 UResourceBundle
*fromRes
= ures_getByKey(currencyRes
, "from", NULL
, &localStatus
);
1297 const int32_t *fromArray
= ures_getIntVector(fromRes
, &fromLength
, &localStatus
);
1299 int64_t currDate64
= (int64_t)fromArray
[0] << 32;
1300 currDate64
|= ((int64_t)fromArray
[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
1301 UDate fromDate
= (UDate
)currDate64
;
1303 if (ures_getSize(currencyRes
) > 2)
1305 int32_t toLength
= 0;
1306 UResourceBundle
*toRes
= ures_getByKey(currencyRes
, "to", NULL
, &localStatus
);
1307 const int32_t *toArray
= ures_getIntVector(toRes
, &toLength
, &localStatus
);
1309 currDate64
= (int64_t)toArray
[0] << 32;
1310 currDate64
|= ((int64_t)toArray
[1] & (int64_t)INT64_C(0x00000000FFFFFFFF));
1311 UDate toDate
= (UDate
)currDate64
;
1313 if ((fromDate
<= date
) && (date
< toDate
))
1316 if (currIndex
== index
)
1326 if (fromDate
<= date
)
1329 if (currIndex
== index
)
1336 // close open resources
1337 ures_close(currencyRes
);
1338 ures_close(fromRes
);
1340 // check for loop exit
1349 ures_close(countryArray
);
1352 if (*ec
== U_ZERO_ERROR
|| localStatus
!= U_ZERO_ERROR
)
1354 // There is nothing to fallback to.
1355 // Report the failure/warning if possible.
1362 if((buffCapacity
> resLen
) && matchFound
)
1364 // write out the currency value
1373 // return null terminated currency string
1374 return u_terminateUChars(buff
, buffCapacity
, resLen
, ec
);
1378 // illegal argument encountered
1379 *ec
= U_ILLEGAL_ARGUMENT_ERROR
;
1384 // If we got here, either error code is invalid or
1385 // some argument passed is no good.
1389 #endif /* #if !UCONFIG_NO_FORMATTING */