bool NumberValcon::parse(const QString& text) { if (text.isEmpty()) { _value = 0; return true; } UnicodeString utext = convertToICU(text); // Parse the number using ICU UErrorCode status = U_ZERO_ERROR; NumberFormat* fmt = NumberFormat::createInstance(status); if (U_SUCCESS(status)) { Formattable value; ParsePosition pos; fmt->parse(utext, value, pos); if (pos.getErrorIndex() == -1 && pos.getIndex() == utext.length()) { #if U_ICU_VERSION_MAJOR_NUM < 3 _value = value.getDouble(&status); #else _value = value.getDouble(status); #endif return true; } } return false; }
void RelativeDateTimeFormatterTest::TestCustomNumberFormat() { NumberFormat *nf; UErrorCode status = U_ZERO_ERROR; { RelativeDateTimeFormatter fmt("en", status); if (U_FAILURE(status)) { dataerrln( "Failure creating format object - %s", u_errorName(status)); return; } nf = (NumberFormat *) fmt.getNumberFormat().clone(); } nf->setMinimumFractionDigits(1); nf->setMaximumFractionDigits(1); RelativeDateTimeFormatter fmt("en", nf, status); // Test copy constructor. RelativeDateTimeFormatter fmt2(fmt); RunTest(fmt2, kEnglishDecimal, UPRV_LENGTHOF(kEnglishDecimal), "en decimal digits"); // Test assignment fmt = RelativeDateTimeFormatter("es", status); RunTest(fmt, kSpanishNoQuantity, UPRV_LENGTHOF(kSpanishNoQuantity), "assignment operator"); }
/** * Convenience method that ought to be in NumberFormat */ NumberFormat* MessageFormat::createIntegerFormat(const Locale& locale, UErrorCode& status) const { NumberFormat *temp = NumberFormat::createInstance(locale, status); if (temp != NULL && temp->getDynamicClassID() == DecimalFormat::getStaticClassID()) { DecimalFormat *temp2 = (DecimalFormat*) temp; temp2->setMaximumFractionDigits(0); temp2->setDecimalSeparatorAlwaysShown(FALSE); temp2->setParseIntegerOnly(TRUE); } return temp; }
QString NumberValcon::format() { // Format decimal using ICU default numeric format UnicodeString text; UErrorCode status = U_ZERO_ERROR; NumberFormat* fmt = NumberFormat::createInstance(status); fmt->format(_value.toDouble(), text, status); if (U_FAILURE(status)) return ""; return convertToQt(text); }
std::string L10n::FormatDecimalNumberIntoString(double number) const { UErrorCode success = U_ZERO_ERROR; UnicodeString utf16Number; NumberFormat* numberFormatter = NumberFormat::createInstance(currentLocale, UNUM_DECIMAL, success); numberFormatter->format(number, utf16Number); char utf8Number[512]; CheckedArrayByteSink sink(utf8Number, ARRAY_SIZE(utf8Number)); utf16Number.toUTF8(sink); ENSURE(!sink.Overflowed()); return std::string(utf8Number, sink.NumberOfBytesWritten()); }
QString PercentValcon::format() { // Format money using ICU default percent format UnicodeString text; UErrorCode status = U_ZERO_ERROR; NumberFormat* fmt = NumberFormat::createPercentInstance(status); fmt->setMaximumFractionDigits(4); fmt->format(_value.toDouble() / 100.0, text, status); if (U_FAILURE(status)) return ""; return convertToQt(text); }
template<> U_I18N_API const MeasureFormatCacheData *LocaleCacheKey<MeasureFormatCacheData>::createObject( const void * /*unused*/, UErrorCode &status) const { const char *localeId = fLoc.getName(); LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, localeId, &status)); static UNumberFormatStyle currencyStyles[] = { UNUM_CURRENCY_PLURAL, UNUM_CURRENCY_ISO, UNUM_CURRENCY}; LocalPointer<MeasureFormatCacheData> result(new MeasureFormatCacheData(), status); if (U_FAILURE(status)) { return NULL; } if (!loadMeasureUnitData( unitsBundle.getAlias(), *result, status)) { return NULL; } result->adoptNumericDateFormatters(loadNumericDateFormatters( unitsBundle.getAlias(), status)); if (U_FAILURE(status)) { return NULL; } for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) { // NumberFormat::createInstance can erase warning codes from status, so pass it // a separate status instance UErrorCode localStatus = U_ZERO_ERROR; result->adoptCurrencyFormat(i, NumberFormat::createInstance( localeId, currencyStyles[i], localStatus)); if (localStatus != U_ZERO_ERROR) { status = localStatus; } if (U_FAILURE(status)) { return NULL; } } NumberFormat *inf = NumberFormat::createInstance( localeId, UNUM_DECIMAL, status); if (U_FAILURE(status)) { return NULL; } inf->setMaximumFractionDigits(0); DecimalFormat *decfmt = dynamic_cast<DecimalFormat *>(inf); if (decfmt != NULL) { decfmt->setRoundingMode(DecimalFormat::kRoundDown); } result->adoptIntegerFormat(inf); result->addRef(); return result.orphan(); }
static void showCurrencyFormatting(UBool useICU26API) { NumberFormat *nf; int32_t i, j; UnicodeString output; UErrorCode errorCode; // TODO: Using printf() here assumes that the runtime encoding is ASCII-friendly // and can therefore be mixed with UTF-8 for(i=0; i<UPRV_LENGTHOF(sampleLocaleIDs); ++i) { printf("show currency formatting (method for %s) in the locale \"%s\"\n", useICU26API ? "ICU 2.6" : "before ICU 2.6", sampleLocaleIDs[i]); // get a currency formatter for this locale ID errorCode=U_ZERO_ERROR; nf=NumberFormat::createCurrencyInstance(sampleLocaleIDs[i], errorCode); if(U_FAILURE(errorCode)) { printf("NumberFormat::createCurrencyInstance(%s) failed - %s\n", sampleLocaleIDs[i], u_errorName(errorCode)); continue; } for(j=0; j<UPRV_LENGTHOF(sampleCurrencies); ++j) { printf(" - format currency \"%s\": ", sampleCurrencies[j]); // set the actual currency to be formatted if(useICU26API) { setNumberFormatCurrency_2_6(*nf, sampleCurrencies[j], errorCode); } else { setNumberFormatCurrency_2_4(*nf, sampleCurrencies[j], errorCode); } if(U_FAILURE(errorCode)) { printf("setNumberFormatCurrency(%s) failed - %s\n", sampleCurrencies[j], u_errorName(errorCode)); continue; } // output=formatted currency value output.remove(); nf->format(12345678.93, output); output+=(UChar)0x0a; // '\n' uprintf(output); } } }
// Test bug9042 void TimeUnitTest::testGreekWithSanitization() { UErrorCode status = U_ZERO_ERROR; Locale elLoc("el"); NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status); if (!assertSuccess("NumberFormat::createInstance for el locale", status, TRUE)) return; numberFmt->setMaximumFractionDigits(1); TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status); if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return; timeUnitFormat->setNumberFormat(*numberFmt, status); delete numberFmt; delete timeUnitFormat; }
virtual NumberFormat* createFormat(const Locale& /* loc */, UNumberFormatStyle formatType) { if (formatType == UNUM_CURRENCY) { return (NumberFormat*)currencyStyle->clone(); } return NULL; }
StandardPlural::Form QuantityFormatter::selectPlural( const Formattable &number, const NumberFormat &fmt, const PluralRules &rules, UnicodeString &formattedNumber, FieldPosition &pos, UErrorCode &status) { if (U_FAILURE(status)) { return StandardPlural::OTHER; } UnicodeString pluralKeyword; const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt); if (decFmt != NULL) { number::impl::DecimalQuantity dq; decFmt->formatToDecimalQuantity(number, dq, status); if (U_FAILURE(status)) { return StandardPlural::OTHER; } pluralKeyword = rules.select(dq); decFmt->format(number, formattedNumber, pos, status); } else { if (number.getType() == Formattable::kDouble) { pluralKeyword = rules.select(number.getDouble()); } else if (number.getType() == Formattable::kLong) { pluralKeyword = rules.select(number.getLong()); } else if (number.getType() == Formattable::kInt64) { pluralKeyword = rules.select((double) number.getInt64()); } else { status = U_ILLEGAL_ARGUMENT_ERROR; return StandardPlural::OTHER; } fmt.format(number, formattedNumber, pos, status); } return StandardPlural::orOtherFromString(pluralKeyword); }
void TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){ if (U_FAILURE(status)) { return; } adoptNumberFormat((NumberFormat *)format.clone(), status); }
// Write AxisBlock keywords bool UChromaSession::writeAxisBlock(LineParser& parser, Axes& axes, int axis) { parser.writeLineF(" %s %i\n", UChromaSession::viewPaneKeyword(UChromaSession::AxisBlockKeyword), axis); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::AutoScaleKeyword), Axes::autoScaleMethod(axes.autoScale(axis))); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::AutoTicksKeyword), stringBool(axes.autoTicks(axis))); parser.writeLineF(" %s %f\n", UChromaSession::axisKeyword(UChromaSession::FirstTickKeyword), axes.tickFirst(axis)); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::FractionalPositioningKeyword), stringBool(axes.positionIsFractional(axis))); parser.writeLineF(" %s %s %s %s\n", UChromaSession::axisKeyword(UChromaSession::GridLinesKeyword), stringBool(axes.gridLinesMajor(axis)), stringBool(axes.gridLinesMinor(axis)), stringBool(axes.gridLinesFull(axis))); LineStyle style = axes.gridLineMajorStyle(axis); parser.writeLineF(" %s %f '%s' %f %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::GridLineMajorStyleKeyword), style.width(), LineStipple::stipple[style.stipple()].name, style.colour().redF(), style.colour().greenF(), style.colour().blueF(), style.colour().alphaF()); style = axes.gridLineMinorStyle(axis); parser.writeLineF(" %s %f '%s' %f %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::GridLineMinorStyleKeyword), style.width(), LineStipple::stipple[style.stipple()].name, style.colour().redF(), style.colour().greenF(), style.colour().blueF(), style.colour().alphaF()); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::InvertKeyword), stringBool(axes.inverted(axis))); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::LabelAnchorKeyword), TextPrimitive::textAnchor(axes.labelAnchor(axis))); parser.writeLineF(" %s %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::LabelOrientationKeyword), axes.labelOrientation(axis).x, axes.labelOrientation(axis).y, axes.labelOrientation(axis).z); parser.writeLineF(" %s %f %f\n", UChromaSession::axisKeyword(UChromaSession::LimitsKeyword), axes.min(axis), axes.max(axis)); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::LogarithmicKeyword), stringBool(axes.logarithmic(axis))); parser.writeLineF(" %s %i\n", UChromaSession::axisKeyword(UChromaSession::MinorTicksKeyword), axes.minorTicks(axis)); NumberFormat fmt = axes.numberFormat(axis); parser.writeLineF(" %s '%s' %i %s %s\n", UChromaSession::axisKeyword(UChromaSession::NumberFormatKeyword), NumberFormat::formatType(fmt.type()), fmt.nDecimals(), stringBool(fmt.useUpperCaseExponent()), stringBool(fmt.forcePrecedingPlus())); parser.writeLineF(" %s %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::PositionFractionalKeyword), axes.positionFractional(axis).x, axes.positionFractional(axis).y, axes.positionFractional(axis).z); parser.writeLineF(" %s %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::PositionRealKeyword), axes.positionReal(axis).x, axes.positionReal(axis).y, axes.positionReal(axis).z); parser.writeLineF(" %s %f\n", UChromaSession::axisKeyword(UChromaSession::StretchKeyword), axes.stretch(axis)); parser.writeLineF(" %s %f\n", UChromaSession::axisKeyword(UChromaSession::TickDeltaKeyword), axes.tickDelta(axis)); parser.writeLineF(" %s %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::TickDirectionKeyword), axes.tickDirection(axis).x, axes.tickDirection(axis).y, axes.tickDirection(axis).z); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::TitleAnchorKeyword), TextPrimitive::textAnchor(axes.titleAnchor(axis))); parser.writeLine(QString(" ")+UChromaSession::axisKeyword(UChromaSession::TitleKeyword)+" '"+axes.title(axis)+"'\n"); parser.writeLineF(" %s %f %f %f %f\n", UChromaSession::axisKeyword(UChromaSession::TitleOrientationKeyword), axes.titleOrientation(axis).x, axes.titleOrientation(axis).y, axes.titleOrientation(axis).z, axes.titleOrientation(axis).w); parser.writeLineF(" %s %s\n", UChromaSession::axisKeyword(UChromaSession::VisibleAxisKeyword), stringBool(axes.visible(axis))); parser.writeLineF(" %s\n", UChromaSession::axisKeyword(UChromaSession::EndAxisKeyword)); return true; }
void BCountry::FormatNumber(BString* string, int32 value) { UErrorCode err; NumberFormat* numberFormatter = NumberFormat::createInstance(*fICULocale, err); assert(err == U_ZERO_ERROR); UnicodeString ICUString; ICUString = numberFormatter->format((int32_t)value, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); }
void DateFormat::setNumberFormat(const NumberFormat& newNumberFormat) { NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone(); if (newNumFmtClone != NULL) { adoptNumberFormat(newNumFmtClone); } }
U_CAPI void U_EXPORT2 unum_setAttribute( UNumberFormat* fmt, UNumberFormatAttribute attr, int32_t newValue) { NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); if ( attr == UNUM_LENIENT_PARSE ) { // Supported for all subclasses // keep this here as the class may not be a DecimalFormat return nf->setLenient(newValue != 0); } // The remaining attributea are only supported for DecimalFormat DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); if (df != NULL) { UErrorCode ignoredStatus = U_ZERO_ERROR; df->setAttribute(attr, newValue, ignoredStatus); } }
static jint getCurrencyFractionDigitsNative(JNIEnv* env, jclass clazz, jstring currencyCode) { UErrorCode status = U_ZERO_ERROR; NumberFormat* fmt = NumberFormat::createCurrencyInstance(status); if (U_FAILURE(status)) { return -1; } const jchar* cCode = env->GetStringChars(currencyCode, NULL); fmt->setCurrency(cCode, status); env->ReleaseStringChars(currencyCode, cCode); if (U_FAILURE(status)) { return -1; } // for CurrencyFormats the minimum and maximum fraction digits are the same. int result = fmt->getMinimumFractionDigits(); delete fmt; return result; }
status_t BCountry::FormatNumber(BString* string, double value) { UErrorCode err = U_ZERO_ERROR; NumberFormat* numberFormatter = NumberFormat::createInstance(*fICULocale, NumberFormat::kNumberStyle, err); // Warning: we're returning an ICU error here but the type is status_t. if (U_FAILURE(err)) return err; UnicodeString ICUString; ICUString = numberFormatter->format(value, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); return U_ZERO_ERROR; }
/* * Set a currency on a NumberFormat with ICU 2.6 APIs. * * @param nf The NumberFormat on which to set the currency; takes effect on * currency-formatting NumberFormat instances. * The display style of the output is controlled by nf (its pattern, * usually from the display locale ID used to create this instance) * while the currency symbol and number of decimals are set for * the currency. * @param currency The 3-letter ISO 4217 currency code, NUL-terminated. * @param errorCode ICU error code, must pass U_SUCCESS() on input. */ static void setNumberFormatCurrency_2_6(NumberFormat &nf, const char *currency, UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return; } if(currency==NULL || strlen(currency)!=3) { errorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } // invariant-character conversion to UChars (see utypes.h and putil.h) UChar uCurrency[4]; u_charsToUChars(currency, uCurrency, 4); // set the currency // in ICU 3.0 this API (which was @draft ICU 2.6) gained a UErrorCode& argument #if (U_ICU_VERSION_MAJOR_NUM < 3) nf.setCurrency(uCurrency); #else nf.setCurrency(uCurrency, errorCode); #endif }
ssize_t BCountry::FormatMonetary(BString* string, double value) { if (string == NULL) return B_BAD_VALUE; UErrorCode err; NumberFormat* numberFormatter = NumberFormat::createCurrencyInstance(*fICULocale, err); assert(err == U_ZERO_ERROR); UnicodeString ICUString; ICUString = numberFormatter->format(value, ICUString); string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); return string->Length(); }
/** * Sample code for the C++ API to NumberFormat. */ void cppapi() { Locale us("en", "US"); UErrorCode status = U_ZERO_ERROR; // Create a number formatter for the US locale NumberFormat *fmt = NumberFormat::createInstance(us, status); check(status, "NumberFormat::createInstance"); // Parse a string. The string uses the digits '0' through '9' // and the decimal separator '.', standard in the US locale UnicodeString str("9876543210.123"); Formattable result; fmt->parse(str, result, status); check(status, "NumberFormat::parse"); printf("NumberFormat::parse(\""); // Display the result uprintf(str); printf("\") => "); uprintf(formattableToString(result)); printf("\n"); // Take the number parsed above, and use the formatter to // format it. str.remove(); // format() will APPEND to this string fmt->format(result, str, status); check(status, "NumberFormat::format"); printf("NumberFormat::format("); // Display the result uprintf(formattableToString(result)); printf(") => \""); uprintf(str); printf("\"\n"); delete fmt; // Release the storage used by the formatter }
ArgExtractor::ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status) : ncnf((NumberFormat*) &nf), num(&obj), setCurr(FALSE) { const UObject* o = obj.getObject(); // most commonly o==NULL const CurrencyAmount* amt; if (o != NULL && (amt = dynamic_cast<const CurrencyAmount*>(o)) != NULL) { // getISOCurrency() returns a pointer to internal storage, so we // copy it to retain it across the call to setCurrency(). const UChar* curr = amt->getISOCurrency(); u_strcpy(save, nf.getCurrency()); setCurr = (u_strcmp(curr, save) != 0); if (setCurr) { ncnf->setCurrency(curr, status); } num = &amt->getNumber(); } }
void TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){ if (U_FAILURE(status) || (fNumberFormat && format == *fNumberFormat)) { return; } delete fNumberFormat; fNumberFormat = (NumberFormat*)format.clone(); // reset the number formatter in the fTimeUnitToCountToPatterns map for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; i = (TimeUnit::UTimeUnitFields)(i+1)) { int32_t pos = -1; const UHashElement* elem = NULL; while ((elem = fTimeUnitToCountToPatterns[i]->nextElement(pos)) != NULL){ const UHashTok keyTok = elem->value; MessageFormat** pattern = (MessageFormat**)keyTok.pointer; pattern[kFull]->setFormat(0, format); pattern[kAbbreviate]->setFormat(0, format); } } }
NumberFormat* NumberFormat::makeInstance(const Locale& desiredLocale, UNumberFormatStyle style, UBool mustBeDecimalFormat, UErrorCode& status) { if (U_FAILURE(status)) return NULL; if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) { status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } // Some styles are not supported. This is a result of merging // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle. // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations: // this one and unum_open(). // The UNUM_PATTERN_ styles are not supported here // because this method does not take a pattern string. if (!isStyleSupported(style)) { status = U_UNSUPPORTED_ERROR; return NULL; } #if U_PLATFORM_USES_ONLY_WIN32_API if (!mustBeDecimalFormat) { char buffer[8]; int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status); // if the locale has "@compat=host", create a host-specific NumberFormat if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) { Win32NumberFormat *f = NULL; UBool curr = TRUE; switch (style) { case UNUM_DECIMAL: curr = FALSE; // fall-through case UNUM_CURRENCY: case UNUM_CURRENCY_ISO: // do not support plural formatting here case UNUM_CURRENCY_PLURAL: f = new Win32NumberFormat(desiredLocale, curr, status); if (U_SUCCESS(status)) { return f; } delete f; break; default: break; } } } #endif // Use numbering system cache hashtable umtx_initOnce(gNSCacheInitOnce, &nscacheInit); // Get cached numbering system LocalPointer<NumberingSystem> ownedNs; NumberingSystem *ns = NULL; if (NumberingSystem_cache != NULL) { // TODO: Bad hash key usage, see ticket #8504. int32_t hashKey = desiredLocale.hashCode(); Mutex lock(&nscacheMutex); ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey); if (ns == NULL) { ns = NumberingSystem::createInstance(desiredLocale,status); uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status); } } else { ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status)); ns = ownedNs.getAlias(); } // check results of getting a numbering system if (U_FAILURE(status)) { return NULL; } if (mustBeDecimalFormat && ns->isAlgorithmic()) { status = U_UNSUPPORTED_ERROR; return NULL; } LocalPointer<DecimalFormatSymbols> symbolsToAdopt; UnicodeString pattern; LocalUResourceBundlePointer ownedResource(ures_open(NULL, desiredLocale.getName(), &status)); if (U_FAILURE(status)) { // We don't appear to have resource data available -- use the last-resort data status = U_USING_FALLBACK_WARNING; // When the data is unavailable, and locale isn't passed in, last resort data is used. symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(status)); if (symbolsToAdopt.isNull()) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } // Creates a DecimalFormat instance with the last resort number patterns. pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1); } else { // Loads the decimal symbols of the desired locale. symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(desiredLocale, status)); if (symbolsToAdopt.isNull()) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } UResourceBundle *resource = ownedResource.orphan(); UResourceBundle *numElements = ures_getByKeyWithFallback(resource, gNumberElements, NULL, &status); resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &status); resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); ownedResource.adoptInstead(resource); int32_t patLen = 0; const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status); // Didn't find a pattern specific to the numbering system, so fall back to "latn" if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(gLatn,ns->getName())) { status = U_ZERO_ERROR; resource = ures_getByKeyWithFallback(numElements, gLatn, resource, &status); resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status); } ures_close(numElements); // Creates the specified decimal format style of the desired locale. pattern.setTo(TRUE, patResStr, patLen); } if (U_FAILURE(status)) { return NULL; } if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO){ const UChar* currPattern = symbolsToAdopt->getCurrencyPattern(); if(currPattern!=NULL){ pattern.setTo(currPattern, u_strlen(currPattern)); } } NumberFormat *f; if (ns->isAlgorithmic()) { UnicodeString nsDesc; UnicodeString nsRuleSetGroup; UnicodeString nsRuleSetName; Locale nsLoc; URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM; nsDesc.setTo(ns->getDescription()); int32_t firstSlash = nsDesc.indexOf(gSlash); int32_t lastSlash = nsDesc.lastIndexOf(gSlash); if ( lastSlash > firstSlash ) { CharString nsLocID; nsLocID.appendInvariantChars(nsDesc.tempSubString(0, firstSlash), status); nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1); nsRuleSetName.setTo(nsDesc,lastSlash+1); nsLoc = Locale::createFromName(nsLocID.data()); UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules"); if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) { desiredRulesType = URBNF_SPELLOUT; } } else { nsLoc = desiredLocale; nsRuleSetName.setTo(nsDesc); } RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status); if (r == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } r->setDefaultRuleSet(nsRuleSetName,status); f = r; } else { // replace single currency sign in the pattern with double currency sign // if the style is UNUM_CURRENCY_ISO if (style == UNUM_CURRENCY_ISO) { pattern.findAndReplace(UnicodeString(TRUE, gSingleCurrencySign, 1), UnicodeString(TRUE, gDoubleCurrencySign, 2)); } // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails. DecimalFormatSymbols *syms = symbolsToAdopt.orphan(); f = new DecimalFormat(pattern, syms, style, status); if (f == NULL) { delete syms; status = U_MEMORY_ALLOCATION_ERROR; return NULL; } } f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status), ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status)); if (U_FAILURE(status)) { delete f; return NULL; } return f; }
/** * Test hiding of parse() and format() APIs in the Format hierarchy. * We test the entire hierarchy, even though this test is located in * the DateFormat API test. */ void IntlTestDateFormatAPI::TestNameHiding(void) { // N.B.: This test passes if it COMPILES, since it's a test of // compile-time name hiding. UErrorCode status = U_ZERO_ERROR; Formattable dateObj(0, Formattable::kIsDate); Formattable numObj(3.1415926535897932384626433832795); Formattable obj; UnicodeString str; FieldPosition fpos; ParsePosition ppos; // DateFormat calling Format API { logln("DateFormat"); DateFormat *dateFmt = DateFormat::createInstance(); if (dateFmt) { dateFmt->format(dateObj, str, status); dateFmt->format(dateObj, str, fpos, status); delete dateFmt; } else { errln("FAIL: Can't create DateFormat"); } } // SimpleDateFormat calling Format & DateFormat API { logln("SimpleDateFormat"); status = U_ZERO_ERROR; SimpleDateFormat sdf(status); // Format API sdf.format(dateObj, str, status); sdf.format(dateObj, str, fpos, status); // DateFormat API sdf.format((UDate)0, str, fpos); sdf.format((UDate)0, str); sdf.parse(str, status); sdf.parse(str, ppos); } // NumberFormat calling Format API { logln("NumberFormat"); status = U_ZERO_ERROR; NumberFormat *fmt = NumberFormat::createInstance(status); if (fmt) { fmt->format(numObj, str, status); fmt->format(numObj, str, fpos, status); delete fmt; } else { errln("FAIL: Can't create NumberFormat()"); } } // DecimalFormat calling Format & NumberFormat API { logln("DecimalFormat"); status = U_ZERO_ERROR; DecimalFormat fmt(status); if(U_SUCCESS(status)) { // Format API fmt.format(numObj, str, status); fmt.format(numObj, str, fpos, status); // NumberFormat API fmt.format(2.71828, str); fmt.format((int32_t)1234567, str); fmt.format(1.41421, str, fpos); fmt.format((int32_t)9876543, str, fpos); fmt.parse(str, obj, ppos); fmt.parse(str, obj, status); } else { errln("FAIL: Couldn't instantiate DecimalFormat, error %s. Quitting test", u_errorName(status)); } } // ChoiceFormat calling Format & NumberFormat API { logln("ChoiceFormat"); status = U_ZERO_ERROR; ChoiceFormat fmt("0#foo|1#foos|2#foos", status); // Format API fmt.format(numObj, str, status); fmt.format(numObj, str, fpos, status); // NumberFormat API fmt.format(2.71828, str); fmt.format((int32_t)1234567, str); fmt.format(1.41421, str, fpos); fmt.format((int32_t)9876543, str, fpos); fmt.parse(str, obj, ppos); fmt.parse(str, obj, status); } // MessageFormat calling Format API { logln("MessageFormat"); status = U_ZERO_ERROR; MessageFormat fmt("", status); // Format API // We use dateObj, which MessageFormat should reject. // We're testing name hiding, not the format method. fmt.format(dateObj, str, status); fmt.format(dateObj, str, fpos, status); } }
void MessageFormatRegressionTest::Test4031438() { UErrorCode status = U_ZERO_ERROR; UnicodeString pattern1("Impossible {1} has occurred -- status code is {0} and message is {2}."); UnicodeString pattern2("Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'."); MessageFormat *messageFormatter = new MessageFormat("", status); failure(status, "new MessageFormat"); const UBool possibleDataError = TRUE; //try { logln("Apply with pattern : " + pattern1); messageFormatter->applyPattern(pattern1, status); failure(status, "messageFormat->applyPattern"); //Object[] params = {new Integer(7)}; Formattable params []= { Formattable((int32_t)7) }; UnicodeString tempBuffer; FieldPosition pos(FieldPosition::DONT_CARE); tempBuffer = messageFormatter->format(params, 1, tempBuffer, pos, status); if(tempBuffer != "Impossible {1} has occurred -- status code is 7 and message is {2}." || failure(status, "MessageFormat::format")) dataerrln("Tests arguments < substitution failed"); logln("Formatted with 7 : " + tempBuffer); ParsePosition pp(0); int32_t count = 0; Formattable *objs = messageFormatter->parse(tempBuffer, pp, count); //if(objs[7/*params.length*/] != NULL) // errln("Parse failed with more than expected arguments"); NumberFormat *fmt = 0; UnicodeString temp, temp1; for (int i = 0; i < count; i++) { // convert to string if not already Formattable obj = objs[i]; temp.remove(); if(obj.getType() == Formattable::kString) temp = obj.getString(temp); else { fmt = NumberFormat::createInstance(status); switch (obj.getType()) { case Formattable::kLong: fmt->format(obj.getLong(), temp); break; case Formattable::kInt64: fmt->format(obj.getInt64(), temp); break; case Formattable::kDouble: fmt->format(obj.getDouble(), temp); break; default: break; } } // convert to string if not already Formattable obj1 = params[i]; temp1.remove(); if(obj1.getType() == Formattable::kString) temp1 = obj1.getString(temp1); else { fmt = NumberFormat::createInstance(status); switch (obj1.getType()) { case Formattable::kLong: fmt->format(obj1.getLong(), temp1); break; case Formattable::kInt64: fmt->format(obj1.getInt64(), temp1); break; case Formattable::kDouble: fmt->format(obj1.getDouble(), temp1); break; default: break; } } //if (objs[i] != NULL && objs[i].getString(temp1) != params[i].getString(temp2)) { if (temp != temp1) { errln("Parse failed on object " + objs[i].getString(temp1) + " at index : " + i); } } delete fmt; delete [] objs; // {sfb} does this apply? no way to really pass a null Formattable, // only a null array /*tempBuffer = messageFormatter->format(null, tempBuffer, FieldPosition(FieldPosition::DONT_CARE), status); if (tempBuffer != "Impossible {1} has occurred -- status code is {0} and message is {2}." || failure(status, "messageFormat->format")) errln("Tests with no arguments failed"); logln("Formatted with null : " + tempBuffer);*/ logln("Apply with pattern : " + pattern2); messageFormatter->applyPattern(pattern2, status); failure(status, "messageFormatter->applyPattern", possibleDataError); tempBuffer.remove(); tempBuffer = messageFormatter->format(params, 1, tempBuffer, pos, status); if (tempBuffer != "Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.") dataerrln("quote format test (w/ params) failed. - %s", u_errorName(status)); logln("Formatted with params : " + tempBuffer); /*tempBuffer = messageFormatter->format(null); if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff.")) errln("quote format test (w/ null) failed."); logln("Formatted with null : " + tempBuffer); logln("toPattern : " + messageFormatter.toPattern());*/ /*} catch (Exception foo) { errln("Exception when formatting in bug 4031438. "+foo.getMessage()); }*/ delete messageFormatter; }
// test RBNF extensions to message format void TestMessageFormat::TestRBNF(void) { // WARNING: this depends on the RBNF formats for en_US Locale locale("en", "US", ""); UErrorCode ec = U_ZERO_ERROR; UnicodeString values[] = { // decimal values do not format completely for ordinal or duration, and // do not always parse, so do not include them "0", "1", "12", "100", "123", "1001", "123,456", "-17", }; int32_t values_count = sizeof(values)/sizeof(values[0]); UnicodeString formats[] = { "There are {0,spellout} files to search.", "There are {0,spellout,%simplified} files to search.", "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.", "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse "Searching this file will take {0,duration} to complete.", "Searching this file will take {0,duration,%with-words} to complete.", }; int32_t formats_count = sizeof(formats)/sizeof(formats[0]); Formattable args[1]; NumberFormat* numFmt = NumberFormat::createInstance(locale, ec); if (U_FAILURE(ec)) { dataerrln("Error calling NumberFormat::createInstance()"); return; } for (int i = 0; i < formats_count; ++i) { MessageFormat* fmt = new MessageFormat(formats[i], locale, ec); logln((UnicodeString)"Testing format pattern: '" + formats[i] + "'"); for (int j = 0; j < values_count; ++j) { ec = U_ZERO_ERROR; numFmt->parse(values[j], args[0], ec); if (U_FAILURE(ec)) { errln((UnicodeString)"Failed to parse test argument " + values[j]); } else { FieldPosition fp(0); UnicodeString result; fmt->format(args, 1, result, fp, ec); logln((UnicodeString)"value: " + toString(args[0]) + " --> " + result + UnicodeString(" ec: ") + u_errorName(ec)); if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3) int32_t count = 0; Formattable* parseResult = fmt->parse(result, count, ec); if (count != 1) { errln((UnicodeString)"parse returned " + count + " args"); } else if (parseResult[0] != args[0]) { errln((UnicodeString)"parsed argument " + toString(parseResult[0]) + " != " + toString(args[0])); } delete []parseResult; } } } delete fmt; } delete numFmt; }
UBool TimeZone::parseCustomID(const UnicodeString& id, int32_t& sign, int32_t& hour, int32_t& min, int32_t& sec) { static const int32_t kParseFailed = -99999; NumberFormat* numberFormat = 0; UnicodeString idUppercase = id; idUppercase.toUpper(); if (id.length() > GMT_ID_LENGTH && idUppercase.startsWith(GMT_ID)) { ParsePosition pos(GMT_ID_LENGTH); sign = 1; hour = 0; min = 0; sec = 0; if (id[pos.getIndex()] == MINUS /*'-'*/) { sign = -1; } else if (id[pos.getIndex()] != PLUS /*'+'*/) { return FALSE; } pos.setIndex(pos.getIndex() + 1); UErrorCode success = U_ZERO_ERROR; numberFormat = NumberFormat::createInstance(success); if(U_FAILURE(success)){ return FALSE; } numberFormat->setParseIntegerOnly(TRUE); // Look for either hh:mm, hhmm, or hh int32_t start = pos.getIndex(); Formattable n(kParseFailed); numberFormat->parse(id, n, pos); if (pos.getIndex() == start) { delete numberFormat; return FALSE; } hour = n.getLong(); if (pos.getIndex() < id.length()) { if (pos.getIndex() - start > 2 || id[pos.getIndex()] != COLON) { delete numberFormat; return FALSE; } // hh:mm pos.setIndex(pos.getIndex() + 1); int32_t oldPos = pos.getIndex(); n.setLong(kParseFailed); numberFormat->parse(id, n, pos); if ((pos.getIndex() - oldPos) != 2) { // must be 2 digits delete numberFormat; return FALSE; } min = n.getLong(); if (pos.getIndex() < id.length()) { if (id[pos.getIndex()] != COLON) { delete numberFormat; return FALSE; } // [:ss] pos.setIndex(pos.getIndex() + 1); oldPos = pos.getIndex(); n.setLong(kParseFailed); numberFormat->parse(id, n, pos); if (pos.getIndex() != id.length() || (pos.getIndex() - oldPos) != 2) { delete numberFormat; return FALSE; } sec = n.getLong(); } } else { // Supported formats are below - // // HHmmss // Hmmss // HHmm // Hmm // HH // H int32_t length = pos.getIndex() - start; if (length <= 0 || 6 < length) { // invalid length delete numberFormat; return FALSE; } switch (length) { case 1: case 2: // already set to hour break; case 3: case 4: min = hour % 100; hour /= 100; break; case 5: case 6: sec = hour % 100; min = (hour/100) % 100; hour /= 10000; break; } } delete numberFormat; if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN || sec > kMAX_CUSTOM_SEC) { return FALSE; } return TRUE; } return FALSE; }
/** * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of * NumberFormat. */ void IntlTestNumberFormatAPI::testAPI(/* char* par */) { UErrorCode status = U_ZERO_ERROR; // ======= Test constructors logln("Testing NumberFormat constructors"); NumberFormat *def = NumberFormat::createInstance(status); if(U_FAILURE(status)) { errln("ERROR: Could not create NumberFormat (default)"); } status = U_ZERO_ERROR; NumberFormat *fr = NumberFormat::createInstance(Locale::getFrench(), status); if(U_FAILURE(status)) { errln("ERROR: Could not create NumberFormat (French)"); } NumberFormat *cur = NumberFormat::createCurrencyInstance(status); if(U_FAILURE(status)) { errln("ERROR: Could not create NumberFormat (currency, default)"); } status = U_ZERO_ERROR; NumberFormat *cur_fr = NumberFormat::createCurrencyInstance(Locale::getFrench(), status); if(U_FAILURE(status)) { errln("ERROR: Could not create NumberFormat (currency, French)"); } NumberFormat *per = NumberFormat::createPercentInstance(status); if(U_FAILURE(status)) { errln("ERROR: Could not create NumberFormat (percent, default)"); } status = U_ZERO_ERROR; NumberFormat *per_fr = NumberFormat::createPercentInstance(Locale::getFrench(), status); if(U_FAILURE(status)) { errln("ERROR: Could not create NumberFormat (percent, French)"); } // ======= Test equality if (per_fr != NULL && cur_fr != NULL) { logln("Testing equality operator"); if( *per_fr == *cur_fr || ! ( *per_fr != *cur_fr) ) { errln("ERROR: == failed"); } } // ======= Test various format() methods if (cur_fr != NULL) { logln("Testing various format() methods"); double d = -10456.0037; int32_t l = 100000000; Formattable fD(d); Formattable fL(l); UnicodeString res1, res2, res3, res4, res5, res6; FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); res1 = cur_fr->format(d, res1); logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); res2 = cur_fr->format(l, res2); logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); res3 = cur_fr->format(d, res3, pos1); logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res3); res4 = cur_fr->format(l, res4, pos2); logln((UnicodeString) "" + (int32_t) l + " formatted to " + res4); status = U_ZERO_ERROR; res5 = cur_fr->format(fD, res5, pos3, status); if(U_FAILURE(status)) { errln("ERROR: format(Formattable [double]) failed"); } logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res5); status = U_ZERO_ERROR; res6 = cur_fr->format(fL, res6, pos4, status); if(U_FAILURE(status)) { errln("ERROR: format(Formattable [long]) failed"); } logln((UnicodeString) "" + fL.getLong() + " formatted to " + res6); } // ======= Test parse() if (fr != NULL) { logln("Testing parse()"); double d = -10456.0037; UnicodeString text("-10,456.0037"); Formattable result1, result2, result3; ParsePosition pos(0), pos01(0); fr->parseObject(text, result1, pos); if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { errln("ERROR: Roundtrip failed (via parse()) for " + text); } logln(text + " parsed into " + (int32_t) result1.getDouble()); fr->parse(text, result2, pos01); if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { errln("ERROR: Roundtrip failed (via parse()) for " + text); } logln(text + " parsed into " + (int32_t) result2.getDouble()); status = U_ZERO_ERROR; fr->parse(text, result3, status); if(U_FAILURE(status)) { errln("ERROR: parse() failed"); } if(result3.getType() != Formattable::kDouble && result3.getDouble() != d) { errln("ERROR: Roundtrip failed (via parse()) for " + text); } logln(text + " parsed into " + (int32_t) result3.getDouble()); } // ======= Test getters and setters if (fr != NULL && def != NULL) { logln("Testing getters and setters"); int32_t count = 0; const Locale *locales = NumberFormat::getAvailableLocales(count); logln((UnicodeString) "Got " + count + " locales" ); for(int32_t i = 0; i < count; i++) { UnicodeString name(locales[i].getName(),""); logln(name); } fr->setParseIntegerOnly( def->isParseIntegerOnly() ); if(fr->isParseIntegerOnly() != def->isParseIntegerOnly() ) { errln("ERROR: setParseIntegerOnly() failed"); } fr->setGroupingUsed( def->isGroupingUsed() ); if(fr->isGroupingUsed() != def->isGroupingUsed() ) { errln("ERROR: setGroupingUsed() failed"); } fr->setMaximumIntegerDigits( def->getMaximumIntegerDigits() ); if(fr->getMaximumIntegerDigits() != def->getMaximumIntegerDigits() ) { errln("ERROR: setMaximumIntegerDigits() failed"); } fr->setMinimumIntegerDigits( def->getMinimumIntegerDigits() ); if(fr->getMinimumIntegerDigits() != def->getMinimumIntegerDigits() ) { errln("ERROR: setMinimumIntegerDigits() failed"); } fr->setMaximumFractionDigits( def->getMaximumFractionDigits() ); if(fr->getMaximumFractionDigits() != def->getMaximumFractionDigits() ) { errln("ERROR: setMaximumFractionDigits() failed"); } fr->setMinimumFractionDigits( def->getMinimumFractionDigits() ); if(fr->getMinimumFractionDigits() != def->getMinimumFractionDigits() ) { errln("ERROR: setMinimumFractionDigits() failed"); } } // ======= Test getStaticClassID() logln("Testing getStaticClassID()"); status = U_ZERO_ERROR; NumberFormat *test = new DecimalFormat(status); if(U_FAILURE(status)) { errln("ERROR: Couldn't create a NumberFormat"); } if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { errln("ERROR: getDynamicClassID() didn't return the expected value"); } delete test; delete def; delete fr; delete cur; delete cur_fr; delete per; delete per_fr; }
NumberFormat* NumberFormat::makeInstance(const Locale& desiredLocale, EStyles style, UErrorCode& status) { if (U_FAILURE(status)) return NULL; if (style < 0 || style >= kStyleCount) { status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } #ifdef U_WINDOWS char buffer[8]; int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status); // if the locale has "@compat=host", create a host-specific NumberFormat if (count > 0 && uprv_strcmp(buffer, "host") == 0) { Win32NumberFormat *f = NULL; UBool curr = TRUE; switch (style) { case kNumberStyle: curr = FALSE; // fall-through case kCurrencyStyle: case kIsoCurrencyStyle: // do not support plural formatting here case kPluralCurrencyStyle: f = new Win32NumberFormat(desiredLocale, curr, status); if (U_SUCCESS(status)) { return f; } delete f; break; default: break; } } #endif NumberFormat* f = NULL; DecimalFormatSymbols* symbolsToAdopt = NULL; UnicodeString pattern; UResourceBundle *resource = ures_open((char *)0, desiredLocale.getName(), &status); UResourceBundle *numberPatterns = ures_getByKey(resource, DecimalFormat::fgNumberPatterns, NULL, &status); NumberingSystem *ns = NULL; UBool deleteSymbols = TRUE; UHashtable * cache = NULL; int32_t hashKey; UBool getCache = FALSE; UBool deleteNS = FALSE; if (U_FAILURE(status)) { // We don't appear to have resource data available -- use the last-resort data status = U_USING_FALLBACK_WARNING; // When the data is unavailable, and locale isn't passed in, last resort data is used. symbolsToAdopt = new DecimalFormatSymbols(status); // Creates a DecimalFormat instance with the last resort number patterns. pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1); } else { // If not all the styled patterns exists for the NumberFormat in this locale, // sets the status code to failure and returns nil. if (ures_getSize(numberPatterns) < (int32_t)(sizeof(gLastResortNumberPatterns)/sizeof(gLastResortNumberPatterns[0])) -2 ) { //minus 2: ISO and plural status = U_INVALID_FORMAT_ERROR; goto cleanup; } // Loads the decimal symbols of the desired locale. symbolsToAdopt = new DecimalFormatSymbols(desiredLocale, status); int32_t patLen = 0; /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE, * the pattern is the same as the pattern of CURRENCYSTYLE * but by replacing the single currency sign with * double currency sign or triple currency sign. */ int styleInNumberPattern = ((style == kIsoCurrencyStyle || style == kPluralCurrencyStyle) ? kCurrencyStyle : style); const UChar *patResStr = ures_getStringByIndex(numberPatterns, (int32_t)styleInNumberPattern, &patLen, &status); // Creates the specified decimal format style of the desired locale. pattern.setTo(TRUE, patResStr, patLen); } if (U_FAILURE(status) || symbolsToAdopt == NULL) { goto cleanup; } if(style==kCurrencyStyle || style == kIsoCurrencyStyle){ const UChar* currPattern = symbolsToAdopt->getCurrencyPattern(); if(currPattern!=NULL){ pattern.setTo(currPattern, u_strlen(currPattern)); } } // Use numbering system cache hashtable UMTX_CHECK(&nscacheMutex, (UBool)(cache != NumberingSystem_cache), getCache); if (getCache) { umtx_lock(&nscacheMutex); cache = NumberingSystem_cache; umtx_unlock(&nscacheMutex); } // Check cache we got, create if non-existant status = U_ZERO_ERROR; if (cache == NULL) { cache = uhash_open(uhash_hashLong, uhash_compareLong, NULL, &status); if (cache == NULL || U_FAILURE(status)) { // cache not created - out of memory cache = NULL; } else { // cache created uhash_setValueDeleter(cache, deleteNumberingSystem); // set final NumberingSystem_cache value UHashtable* h = NULL; UMTX_CHECK(&nscacheMutex, (UBool)(h != NumberingSystem_cache), getCache); if (getCache) { umtx_lock(&nscacheMutex); h = NumberingSystem_cache; umtx_unlock(&nscacheMutex); } if (h == NULL) { umtx_lock(&nscacheMutex); NumberingSystem_cache = h = cache; cache = NULL; ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup); umtx_unlock(&nscacheMutex); } if(cache != NULL) { uhash_close(cache); } cache = h; } } // Get cached numbering system if (cache != NULL) { hashKey = desiredLocale.hashCode(); umtx_lock(&nscacheMutex); ns = (NumberingSystem *)uhash_iget(cache, hashKey); if (ns == NULL) { ns = NumberingSystem::createInstance(desiredLocale,status); uhash_iput(cache, hashKey, (void*)ns, &status); } umtx_unlock(&nscacheMutex); } else { ns = NumberingSystem::createInstance(desiredLocale,status); deleteNS = TRUE; } // check results of getting a numbering system if ((ns == NULL) || (U_FAILURE(status))) { goto cleanup; } if (ns->isAlgorithmic()) { UnicodeString nsDesc; UnicodeString nsRuleSetGroup; UnicodeString nsRuleSetName; Locale nsLoc; URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM; nsDesc.setTo(ns->getDescription()); int32_t firstSlash = nsDesc.indexOf(gSlash); int32_t lastSlash = nsDesc.lastIndexOf(gSlash); if ( lastSlash > firstSlash ) { char nsLocID[ULOC_FULLNAME_CAPACITY]; nsDesc.extract(0,firstSlash,nsLocID,ULOC_FULLNAME_CAPACITY,US_INV); nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1); nsRuleSetName.setTo(nsDesc,lastSlash+1); nsLoc = Locale::createFromName(nsLocID); UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules"); if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) { desiredRulesType = URBNF_SPELLOUT; } } else { nsLoc = desiredLocale; nsRuleSetName.setTo(nsDesc); } RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status); if (U_FAILURE(status) || r == NULL) { goto cleanup; } r->setDefaultRuleSet(nsRuleSetName,status); f = (NumberFormat *) r; } else { // replace single currency sign in the pattern with double currency sign // if the style is kIsoCurrencyStyle if (style == kIsoCurrencyStyle) { pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign); } f = new DecimalFormat(pattern, symbolsToAdopt, style, status); if (U_FAILURE(status) || f == NULL) { goto cleanup; } deleteSymbols = FALSE; } f->setLocaleIDs(ures_getLocaleByType(numberPatterns, ULOC_VALID_LOCALE, &status), ures_getLocaleByType(numberPatterns, ULOC_ACTUAL_LOCALE, &status)); cleanup: ures_close(numberPatterns); ures_close(resource); if (deleteNS && ns) { delete ns; } if (U_FAILURE(status)) { /* If f exists, then it will delete the symbols */ if (f==NULL) { delete symbolsToAdopt; } else { delete f; } return NULL; } if (f == NULL || symbolsToAdopt == NULL) { status = U_MEMORY_ALLOCATION_ERROR; f = NULL; } if (deleteSymbols && symbolsToAdopt != NULL) { delete symbolsToAdopt; } return f; }