/* Function: GetLocaleCurrencyName Gets the locale currency English or native name and convert the result to UChars */ static UErrorCode GetLocaleCurrencyName(const char* locale, UBool nativeName, UChar* value, int32_t valueLength) { UErrorCode status = U_ZERO_ERROR; UChar currencyThreeLettersName[4]; // 3 letters currency iso name + NULL ucurr_forLocale(locale, currencyThreeLettersName, 4, &status); if (!U_SUCCESS(status)) { return status; } int32_t len; UBool formatChoice; const UChar *pCurrencyLongName = ucurr_getName( currencyThreeLettersName, nativeName ? locale : ULOC_US, UCURR_LONG_NAME, &formatChoice, &len, &status); if (!U_SUCCESS(status)) { return status; } if (len >= valueLength) // we need to have room for NULL too { return U_BUFFER_OVERFLOW_ERROR; } u_strncpy(value, pCurrencyLongName, len); value[len] = 0; return status; }
void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { const UChar* c = getCurrency(); if (*c != 0) { u_strncpy(result, c, 3); result[3] = 0; } else { const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec); if (loc == NULL) { loc = uloc_getDefault(); } ucurr_forLocale(loc, result, 4, &ec); } }
void DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData) { static const char *gNumberElementKeys[kFormatSymbolCount] = { "decimal", "group", "list", "percentSign", NULL, /* Native zero digit is deprecated from CLDR - get it from the numbering system */ NULL, /* Pattern digit character is deprecated from CLDR - use # by default always */ "minusSign", "plusSign", NULL, /* currency symbol - We don't really try to load this directly from CLDR until we know the currency */ NULL, /* intl currency symbol - We don't really try to load this directly from CLDR until we know the currency */ "currencyDecimal", "exponential", "perMille", NULL, /* Escape padding character - not in CLDR */ "infinity", "nan", NULL, /* Significant digit symbol - not in CLDR */ "currencyGroup", NULL, /* one digit - get it from the numbering system */ NULL, /* two digit - get it from the numbering system */ NULL, /* three digit - get it from the numbering system */ NULL, /* four digit - get it from the numbering system */ NULL, /* five digit - get it from the numbering system */ NULL, /* six digit - get it from the numbering system */ NULL, /* seven digit - get it from the numbering system */ NULL, /* eight digit - get it from the numbering system */ NULL, /* nine digit - get it from the numbering system */ "superscriptingExponent", /* Multiplication (x) symbol for exponents */ }; static const char *gLatn = "latn"; static const char *gSymbols = "symbols"; const char *nsName; const UChar *sym = NULL; int32_t len = 0; *validLocale = *actualLocale = 0; currPattern = NULL; if (U_FAILURE(status)) return; const char* locStr = loc.getName(); LocalUResourceBundlePointer resource(ures_open(NULL, locStr, &status)); LocalUResourceBundlePointer numberElementsRes( ures_getByKeyWithFallback(resource.getAlias(), gNumberElements, NULL, &status)); if (U_FAILURE(status)) { if ( useLastResortData ) { status = U_USING_DEFAULT_WARNING; initialize(); } return; } // First initialize all the symbols to the fallbacks for anything we can't find initialize(); // // Next get the numbering system for this locale and set zero digit // and the digit string based on the numbering system for the locale // LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(loc, status)); if (U_SUCCESS(status) && ns->getRadix() == 10 && !ns->isAlgorithmic()) { nsName = ns->getName(); UnicodeString digitString(ns->getDescription()); int32_t digitIndex = 0; UChar32 digit = digitString.char32At(0); fSymbols[kZeroDigitSymbol].setTo(digit); for (int32_t i = kOneDigitSymbol; i <= kNineDigitSymbol; ++i) { digitIndex += U16_LENGTH(digit); digit = digitString.char32At(digitIndex); fSymbols[i].setTo(digit); } } else { nsName = gLatn; } UBool isLatn = !uprv_strcmp(nsName,gLatn); UErrorCode nlStatus = U_ZERO_ERROR; LocalUResourceBundlePointer nonLatnSymbols; if ( !isLatn ) { nonLatnSymbols.adoptInstead( ures_getByKeyWithFallback(numberElementsRes.getAlias(), nsName, NULL, &nlStatus)); ures_getByKeyWithFallback(nonLatnSymbols.getAlias(), gSymbols, nonLatnSymbols.getAlias(), &nlStatus); } LocalUResourceBundlePointer latnSymbols( ures_getByKeyWithFallback(numberElementsRes.getAlias(), gLatn, NULL, &status)); ures_getByKeyWithFallback(latnSymbols.getAlias(), gSymbols, latnSymbols.getAlias(), &status); UBool kMonetaryDecimalSet = FALSE; UBool kMonetaryGroupingSet = FALSE; for(int32_t i = 0; i<kFormatSymbolCount; i++) { if ( gNumberElementKeys[i] != NULL ) { UErrorCode localStatus = U_ZERO_ERROR; if ( !isLatn ) { sym = ures_getStringByKeyWithFallback(nonLatnSymbols.getAlias(), gNumberElementKeys[i], &len, &localStatus); // If we can't find the symbol in the numbering system specific resources, // use the "latn" numbering system as the fallback. if ( U_FAILURE(localStatus) ) { localStatus = U_ZERO_ERROR; sym = ures_getStringByKeyWithFallback(latnSymbols.getAlias(), gNumberElementKeys[i], &len, &localStatus); } } else { sym = ures_getStringByKeyWithFallback(latnSymbols.getAlias(), gNumberElementKeys[i], &len, &localStatus); } if ( U_SUCCESS(localStatus) ) { setSymbol((ENumberFormatSymbol)i, UnicodeString(TRUE, sym, len)); if ( i == kMonetarySeparatorSymbol ) { kMonetaryDecimalSet = TRUE; } else if ( i == kMonetaryGroupingSeparatorSymbol ) { kMonetaryGroupingSet = TRUE; } } } } // If monetary decimal or grouping were not explicitly set, then set them to be the // same as their non-monetary counterparts. if ( !kMonetaryDecimalSet ) { setSymbol(kMonetarySeparatorSymbol,fSymbols[kDecimalSeparatorSymbol]); } if ( !kMonetaryGroupingSet ) { setSymbol(kMonetaryGroupingSeparatorSymbol,fSymbols[kGroupingSeparatorSymbol]); } // Obtain currency data from the currency API. This is strictly // for backward compatibility; we don't use DecimalFormatSymbols // for currency data anymore. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; ucurr_forLocale(locStr, curriso, 4, &internalStatus); uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); if (U_SUCCESS(internalStatus)) { fSymbols[kIntlCurrencySymbol].setTo(curriso, -1); fSymbols[kCurrencySymbol] = tempStr; } /* else use the default values. */ U_LOCALE_BASED(locBased, *this); locBased.setLocaleIDs(ures_getLocaleByType(numberElementsRes.getAlias(), ULOC_VALID_LOCALE, &status), ures_getLocaleByType(numberElementsRes.getAlias(), ULOC_ACTUAL_LOCALE, &status)); //load the currency data UChar ucc[4]={0}; //Currency Codes are always 3 chars long int32_t uccLen = 4; const char* locName = loc.getName(); UErrorCode localStatus = U_ZERO_ERROR; uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus); if(U_SUCCESS(localStatus) && uccLen > 0) { char cc[4]={0}; u_UCharsToChars(ucc, cc, uccLen); /* An explicit currency was requested */ LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); LocalUResourceBundlePointer currency( ures_getByKeyWithFallback(currencyResource.getAlias(), "Currencies", NULL, &localStatus)); ures_getByKeyWithFallback(currency.getAlias(), cc, currency.getAlias(), &localStatus); if(U_SUCCESS(localStatus) && ures_getSize(currency.getAlias())>2) { // the length is 3 if more data is present ures_getByIndex(currency.getAlias(), 2, currency.getAlias(), &localStatus); int32_t currPatternLen = 0; currPattern = ures_getStringByIndex(currency.getAlias(), (int32_t)0, &currPatternLen, &localStatus); UnicodeString decimalSep = ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)1, &localStatus); UnicodeString groupingSep = ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)2, &localStatus); if(U_SUCCESS(localStatus)){ fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; fSymbols[kMonetarySeparatorSymbol] = decimalSep; //pattern.setTo(TRUE, currPattern, currPatternLen); status = localStatus; } } /* else An explicit currency was requested and is unknown or locale data is malformed. */ /* ucurr_* API will get the correct value later on. */ } // else ignore the error if no currency // Currency Spacing. localStatus = U_ZERO_ERROR; LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); LocalUResourceBundlePointer currencySpcRes( ures_getByKeyWithFallback(currencyResource.getAlias(), gCurrencySpacingTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { const char* keywords[UNUM_CURRENCY_SPACING_COUNT] = { gCurrencyMatchTag, gCurrencySudMatchTag, gCurrencyInsertBtnTag }; localStatus = U_ZERO_ERROR; LocalUResourceBundlePointer dataRes( ures_getByKeyWithFallback(currencySpcRes.getAlias(), gBeforeCurrencyTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { localStatus = U_ZERO_ERROR; for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) { currencySpcBeforeSym[i] = ures_getUnicodeStringByKey(dataRes.getAlias(), keywords[i], &localStatus); } } dataRes.adoptInstead( ures_getByKeyWithFallback(currencySpcRes.getAlias(), gAfterCurrencyTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { localStatus = U_ZERO_ERROR; for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) { currencySpcAfterSym[i] = ures_getUnicodeStringByKey(dataRes.getAlias(), keywords[i], &localStatus); } } } }
static void TestGetKeywordValuesForLocale(void) { #define PREFERRED_SIZE 15 #define MAX_NUMBER_OF_KEYWORDS 4 const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS] = { { "root", "USD", "USN", NULL }, { "und", "USD", "USN", NULL }, /* { "und_ZZ", "USD", NULL, NULL }, -- temporarily remove as this locale now has 15 entries */ { "en_US", "USD", "USN", NULL }, { "en_029", "USD", "USN", NULL }, { "en_TH", "THB", NULL, NULL }, { "de", "EUR", NULL, NULL }, { "de_DE", "EUR", NULL, NULL }, { "ar", "EGP", NULL, NULL }, { "ar_PS", "ILS", "JOD", NULL }, { "en@currency=CAD", "USD", "USN", NULL }, { "fr@currency=zzz", "EUR", NULL, NULL }, { "de_DE@currency=DEM", "EUR", NULL, NULL }, { "en_US@rg=THZZZZ", "THB", NULL, NULL }, { "de@rg=USZZZZ", "USD", "USN", NULL }, { "en_US@currency=CAD;rg=THZZZZ", "THB", NULL, NULL }, }; const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1 }; /* ucurr_forLocale results for same locales; "" if no result expected */ const char *FORLOCALE[PREFERRED_SIZE] = { "", "", "USD", "", "THB", "", "EUR", "", "ILS", "CAD", "ZZZ", "DEM", "THB", "USD", "CAD" }; UErrorCode status = U_ZERO_ERROR; int32_t i, j, size; UEnumeration *pref, *all; const char *loc = NULL; UBool matchPref, matchAll; const char *value = NULL; int32_t valueLength = 0; UList *ALLList = NULL; UEnumeration *ALL = ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE, &status); if (ALL == NULL) { log_err_status(status, "ERROR getting keyword value for default locale. -> %s\n", u_errorName(status)); return; } for (i = 0; i < PREFERRED_SIZE; i++) { UChar getCurrU[4]; int32_t getCurrLen; status = U_ZERO_ERROR; pref = NULL; all = NULL; loc = PREFERRED[i][0]; pref = ucurr_getKeywordValuesForLocale("currency", loc, TRUE, &status); matchPref = FALSE; matchAll = FALSE; size = uenum_count(pref, &status); if (size == EXPECTED_SIZE[i]) { matchPref = TRUE; for (j = 0; j < size; j++) { if ((value = uenum_next(pref, &valueLength, &status)) != NULL && U_SUCCESS(status)) { if (uprv_strcmp(value, PREFERRED[i][j+1]) != 0) { log_err("ERROR: locale %s got keywords #%d %s expected %s\n", loc, j, value, PREFERRED[i][j+1]); matchPref = FALSE; break; } } else { matchPref = FALSE; log_err("ERROR getting keyword value for locale \"%s\"\n", loc); break; } } } else { log_err("FAIL: size of locale \"%s\" %d does not match expected size %d\n", loc, size, EXPECTED_SIZE[i]); } if (!matchPref) { log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc); break; } uenum_close(pref); all = ucurr_getKeywordValuesForLocale("currency", loc, FALSE, &status); size = uenum_count(all, &status); if (U_SUCCESS(status) && size == uenum_count(ALL, &status)) { matchAll = TRUE; ALLList = ulist_getListFromEnum(ALL); for (j = 0; j < size; j++) { if ((value = uenum_next(all, &valueLength, &status)) != NULL && U_SUCCESS(status)) { if (!ulist_containsString(ALLList, value, uprv_strlen(value))) { log_err("Locale %s have %s not in ALL\n", loc, value); matchAll = FALSE; break; } } else { matchAll = FALSE; log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc); break; } } if (!matchAll) { log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc); } } else { if(U_FAILURE(status)) { log_err("ERROR: %s\n", u_errorName(status)); } else if(size!=uenum_count(ALL, &status)) { log_err("ERROR: got size of %d, wanted %d\n", size, uenum_count(ALL, &status)); } } uenum_close(all); status = U_ZERO_ERROR; getCurrLen = ucurr_forLocale(loc, getCurrU, 4, &status); if(U_FAILURE(status)) { if (FORLOCALE[i][0] != 0) { log_err("ERROR: ucurr_forLocale %s, status %s\n", loc, u_errorName(status)); } } else if (getCurrLen != 3) { if (FORLOCALE[i][0] != 0 || getCurrLen != -1) { log_err("ERROR: ucurr_forLocale %s, returned len %d\n", loc, getCurrLen); } } else { char getCurrB[4]; u_UCharsToChars(getCurrU, getCurrB, 4); if ( uprv_strncmp(getCurrB, FORLOCALE[i], 4) != 0 ) { log_err("ERROR: ucurr_forLocale %s, expected %s, got %s\n", loc, FORLOCALE[i], getCurrB); } } } uenum_close(ALL); }
static void TestCurrencyKeywords(void) { static const char * const currencies[] = { "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD", "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS", "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF", "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND", "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ", "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD", "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF", "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK", "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK", "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB", "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF", "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP", "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF", "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP", "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD", "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO", "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR", "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF", "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL", "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP", "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP", "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG", "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN", "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP", "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR", "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK", "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC", "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS", "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS", "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD", "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST", "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR", "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS", "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR", "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD" }; UErrorCode status = U_ZERO_ERROR; int32_t i = 0, j = 0; int32_t noLocales = uloc_countAvailable(); char locale[256]; char currLoc[256]; UChar result[4]; UChar currBuffer[256]; for(i = 0; i < noLocales; i++) { strcpy(currLoc, uloc_getAvailable(i)); for(j = 0; j < UPRV_LENGTHOF(currencies); j++) { strcpy(locale, currLoc); strcat(locale, "@currency="); strcat(locale, currencies[j]); ucurr_forLocale(locale, result, 4, &status); u_charsToUChars(currencies[j], currBuffer, 3); currBuffer[3] = 0; if(u_strcmp(currBuffer, result) != 0) { log_err("Didn't get the right currency for %s\n", locale); } } } }
void DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData) { *validLocale = *actualLocale = 0; currPattern = NULL; if (U_FAILURE(status)) return; const char* locStr = loc.getName(); UResourceBundle *resource = ures_open((char *)0, locStr, &status); UResourceBundle *numberElementsRes = ures_getByKey(resource, gNumberElements, NULL, &status); if (U_FAILURE(status)) { // Initializes with last resort data if necessary. if (useLastResortData) { status = U_USING_FALLBACK_WARNING; initialize(); } } else { // Gets the number element array. int32_t numberElementsLength = ures_getSize(numberElementsRes); if (numberElementsLength > (int32_t)kFormatSymbolCount) { /* Warning: Invalid format. Array too large. */ numberElementsLength = (int32_t)kFormatSymbolCount; } // If the array size is too small, something is wrong with the resource // bundle, returns the failure error code. if (numberElementsLength != 12 || U_FAILURE(status)) { status = U_INVALID_FORMAT_ERROR; } else { const UChar *numberElements[kFormatSymbolCount]; int32_t numberElementsStrLen[kFormatSymbolCount]; int32_t i = 0; for(i = 0; i<numberElementsLength; i++) { numberElements[i] = ures_getStringByIndex(numberElementsRes, i, &numberElementsStrLen[i], &status); } if (U_SUCCESS(status)) { initialize(numberElements, numberElementsStrLen, numberElementsLength); // Obtain currency data from the currency API. This is strictly // for backward compatibility; we don't use DecimalFormatSymbols // for currency data anymore. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; ucurr_forLocale(locStr, curriso, 4, &internalStatus); // Reuse numberElements[0] as a temporary buffer uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); if (U_SUCCESS(internalStatus)) { fSymbols[kIntlCurrencySymbol] = curriso; fSymbols[kCurrencySymbol] = tempStr; } /* else use the default values. */ } U_LOCALE_BASED(locBased, *this); locBased.setLocaleIDs(ures_getLocaleByType(numberElementsRes, ULOC_VALID_LOCALE, &status), ures_getLocaleByType(numberElementsRes, ULOC_ACTUAL_LOCALE, &status)); } //load the currency data UChar ucc[4]= {0}; //Currency Codes are always 3 chars long int32_t uccLen = 4; const char* locName = loc.getName(); uccLen = ucurr_forLocale(locName, ucc, uccLen, &status); if(U_SUCCESS(status) && uccLen > 0) { char cc[4]= {0}; u_UCharsToChars(ucc, cc, uccLen); /* An explicit currency was requested */ UErrorCode localStatus = U_ZERO_ERROR; UResourceBundle *currency = ures_getByKeyWithFallback(resource, "Currencies", NULL, &localStatus); currency = ures_getByKeyWithFallback(currency, cc, currency, &localStatus); if(U_SUCCESS(localStatus) && ures_getSize(currency)>2) { // the length is 3 if more data is present currency = ures_getByIndex(currency, 2, currency, &localStatus); int32_t currPatternLen = 0; currPattern = ures_getStringByIndex(currency, (int32_t)0, &currPatternLen, &localStatus); UnicodeString decimalSep = ures_getStringByIndex(currency, (int32_t)1, NULL, &localStatus); UnicodeString groupingSep = ures_getStringByIndex(currency, (int32_t)2, NULL, &localStatus); if(U_SUCCESS(localStatus)) { fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; fSymbols[kMonetarySeparatorSymbol] = decimalSep; //pattern.setTo(TRUE, currPattern, currPatternLen); status = localStatus; } } ures_close(currency); /* else An explicit currency was requested and is unknown or locale data is malformed. */ /* ucurr_* API will get the correct value later on. */ } else { // ignore the error if no currency status = U_ZERO_ERROR; } } ures_close(resource); ures_close(numberElementsRes); }
void DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData) { if (U_FAILURE(status)) { return; } *validLocale = *actualLocale = 0; currPattern = NULL; // First initialize all the symbols to the fallbacks for anything we can't find initialize(); // // Next get the numbering system for this locale and set zero digit // and the digit string based on the numbering system for the locale // LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(loc, status)); const char *nsName; if (U_SUCCESS(status) && ns->getRadix() == 10 && !ns->isAlgorithmic()) { nsName = ns->getName(); UnicodeString digitString(ns->getDescription()); int32_t digitIndex = 0; UChar32 digit = digitString.char32At(0); fSymbols[kZeroDigitSymbol].setTo(digit); for (int32_t i = kOneDigitSymbol; i <= kNineDigitSymbol; ++i) { digitIndex += U16_LENGTH(digit); digit = digitString.char32At(digitIndex); fSymbols[i].setTo(digit); } } else { nsName = gLatn; } // Open resource bundles const char* locStr = loc.getName(); LocalUResourceBundlePointer resource(ures_open(NULL, locStr, &status)); LocalUResourceBundlePointer numberElementsRes( ures_getByKeyWithFallback(resource.getAlias(), gNumberElements, NULL, &status)); if (U_FAILURE(status)) { if ( useLastResortData ) { status = U_USING_DEFAULT_WARNING; initialize(); } return; } // Set locale IDs // TODO: Is there a way to do this without depending on the resource bundle instance? U_LOCALE_BASED(locBased, *this); locBased.setLocaleIDs( ures_getLocaleByType( numberElementsRes.getAlias(), ULOC_VALID_LOCALE, &status), ures_getLocaleByType( numberElementsRes.getAlias(), ULOC_ACTUAL_LOCALE, &status)); // Now load the rest of the data from the data sink. // Start with loading this nsName if it is not Latin. DecFmtSymDataSink sink(*this); if (uprv_strcmp(nsName, gLatn) != 0) { CharString path; path.append(gNumberElements, status) .append('/', status) .append(nsName, status) .append('/', status) .append(gSymbols, status); ures_getAllItemsWithFallback(resource.getAlias(), path.data(), sink, status); // If no symbols exist for the given nsName and resource bundle, silently ignore // and fall back to Latin. if (status == U_MISSING_RESOURCE_ERROR) { status = U_ZERO_ERROR; } else if (U_FAILURE(status)) { return; } } // Continue with Latin if necessary. if (!sink.seenAll()) { ures_getAllItemsWithFallback(resource.getAlias(), gNumberElementsLatnSymbols, sink, status); if (U_FAILURE(status)) { return; } } // Let the monetary number separators equal the default number separators if necessary. sink.resolveMissingMonetarySeparators(fSymbols); // Obtain currency data from the currency API. This is strictly // for backward compatibility; we don't use DecimalFormatSymbols // for currency data anymore. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; ucurr_forLocale(locStr, curriso, 4, &internalStatus); uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); if (U_SUCCESS(internalStatus)) { fSymbols[kIntlCurrencySymbol].setTo(curriso, -1); fSymbols[kCurrencySymbol] = tempStr; } /* else use the default values. */ //load the currency data UChar ucc[4]={0}; //Currency Codes are always 3 chars long int32_t uccLen = 4; const char* locName = loc.getName(); UErrorCode localStatus = U_ZERO_ERROR; uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus); if(U_SUCCESS(localStatus) && uccLen > 0) { char cc[4]={0}; u_UCharsToChars(ucc, cc, uccLen); /* An explicit currency was requested */ LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); LocalUResourceBundlePointer currency( ures_getByKeyWithFallback(currencyResource.getAlias(), "Currencies", NULL, &localStatus)); ures_getByKeyWithFallback(currency.getAlias(), cc, currency.getAlias(), &localStatus); if(U_SUCCESS(localStatus) && ures_getSize(currency.getAlias())>2) { // the length is 3 if more data is present ures_getByIndex(currency.getAlias(), 2, currency.getAlias(), &localStatus); int32_t currPatternLen = 0; currPattern = ures_getStringByIndex(currency.getAlias(), (int32_t)0, &currPatternLen, &localStatus); UnicodeString decimalSep = ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)1, &localStatus); UnicodeString groupingSep = ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)2, &localStatus); if(U_SUCCESS(localStatus)){ fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; fSymbols[kMonetarySeparatorSymbol] = decimalSep; //pattern.setTo(TRUE, currPattern, currPatternLen); status = localStatus; } } /* else An explicit currency was requested and is unknown or locale data is malformed. */ /* ucurr_* API will get the correct value later on. */ } // else ignore the error if no currency // Currency Spacing. localStatus = U_ZERO_ERROR; LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); LocalUResourceBundlePointer currencySpcRes( ures_getByKeyWithFallback(currencyResource.getAlias(), gCurrencySpacingTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { const char* keywords[UNUM_CURRENCY_SPACING_COUNT] = { gCurrencyMatchTag, gCurrencySudMatchTag, gCurrencyInsertBtnTag }; localStatus = U_ZERO_ERROR; LocalUResourceBundlePointer dataRes( ures_getByKeyWithFallback(currencySpcRes.getAlias(), gBeforeCurrencyTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { localStatus = U_ZERO_ERROR; for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) { currencySpcBeforeSym[i] = ures_getUnicodeStringByKey(dataRes.getAlias(), keywords[i], &localStatus); } } dataRes.adoptInstead( ures_getByKeyWithFallback(currencySpcRes.getAlias(), gAfterCurrencyTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { localStatus = U_ZERO_ERROR; for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) { currencySpcAfterSym[i] = ures_getUnicodeStringByKey(dataRes.getAlias(), keywords[i], &localStatus); } } } }
U_CAPI int32_t U_EXPORT2 ucurr_forLocale(const char* locale, UChar* buff, int32_t buffCapacity, UErrorCode* ec) { int32_t resLen = 0; const UChar* s = NULL; if (ec != NULL && U_SUCCESS(*ec)) { if ((buff && buffCapacity) || !buffCapacity) { UErrorCode localStatus = U_ZERO_ERROR; char id[ULOC_FULLNAME_CAPACITY]; if ((resLen = uloc_getKeywordValue(locale, "currency", id, ULOC_FULLNAME_CAPACITY, &localStatus))) { // there is a currency keyword. Try to see if it's valid if(buffCapacity > resLen) { u_charsToUChars(id, buff, resLen); } } else { // get country or country_variant in `id' uint32_t variantType = idForLocale(locale, id, sizeof(id), ec); if (U_FAILURE(*ec)) { return 0; } #if !UCONFIG_NO_SERVICE const UChar* result = CReg::get(id); if (result) { if(buffCapacity > u_strlen(result)) { u_strcpy(buff, result); } return u_strlen(result); } #endif // Remove variants, which is only needed for registration. char *idDelim = strchr(id, VAR_DELIM); if (idDelim) { idDelim[0] = 0; } // Look up the CurrencyMap element in the root bundle. UResourceBundle *rb = ures_openDirect(NULL, CURRENCY_DATA, &localStatus); UResourceBundle *cm = ures_getByKey(rb, CURRENCY_MAP, rb, &localStatus); UResourceBundle *countryArray = ures_getByKey(rb, id, cm, &localStatus); UResourceBundle *currencyReq = ures_getByIndex(countryArray, 0, NULL, &localStatus); s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus); /* Get the second item when PREEURO is requested, and this is a known Euro country. If the requested variant is PREEURO, and this isn't a Euro country, assume that the country changed over to the Euro in the future. This is probably an old version of ICU that hasn't been updated yet. The latest currency is probably correct. */ if (U_SUCCESS(localStatus)) { if ((variantType & VARIANT_IS_PREEURO) && u_strcmp(s, EUR_STR) == 0) { currencyReq = ures_getByIndex(countryArray, 1, currencyReq, &localStatus); s = ures_getStringByKey(currencyReq, "id", &resLen, &localStatus); } else if ((variantType & VARIANT_IS_EURO)) { s = EUR_STR; } } ures_close(countryArray); ures_close(currencyReq); if ((U_FAILURE(localStatus)) && strchr(id, '_') != 0) { // We don't know about it. Check to see if we support the variant. uloc_getParent(locale, id, sizeof(id), ec); *ec = U_USING_FALLBACK_WARNING; return ucurr_forLocale(id, buff, buffCapacity, ec); } else if (*ec == U_ZERO_ERROR || localStatus != U_ZERO_ERROR) { // There is nothing to fallback to. Report the failure/warning if possible. *ec = localStatus; } if (U_SUCCESS(*ec)) { if(buffCapacity > resLen) { u_strcpy(buff, s); } } } return u_terminateUChars(buff, buffCapacity, resLen, ec); } else { *ec = U_ILLEGAL_ARGUMENT_ERROR; } } return resLen; }