// If the maximum base 10 exponent were 4, then the largest number would // be 99,999 which has 5 digits. // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999 const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits = 2000000000; const int32_t icu::NumberFormat::gDefaultMinIntegerDigits = 127;
UnicodeString&
NumberFormat::format(int64_t /* unused number */,
UnicodeString& toAppendTo,
FieldPositionIterator* /* unused posIter */,
UErrorCode& status) const
{ if (!U_FAILURE(status)) {
status = U_UNSUPPORTED_ERROR;
} return toAppendTo;
}
// ------------------------------------------ // These functions add the status code, just fall back to the non-status versions
UnicodeString&
NumberFormat::format(double number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const { if(U_SUCCESS(status)) { return format(number,appendTo,pos);
} else { return appendTo;
}
}
// ------------------------------------- // Decimal Number format() default implementation // Subclasses do not normally override this function, but rather the DigitList // formatting functions.. // The expected call chain from here is // this function -> // NumberFormat::format(Formattable -> // DecimalFormat::format(DigitList // // Or, for subclasses of Formattable that do not know about DigitList, // this Function -> // NumberFormat::format(Formattable -> // NumberFormat::format(DigitList -> // XXXFormat::format(double
/** * // Formats the number object and save the format // result in the toAppendTo string buffer.
// utility to save/restore state, used in two overloads // of format(const Formattable&...) below. * * Old purpose of ArgExtractor was to avoid const. Not thread safe! * * keeping it around as a shim.
*/ class ArgExtractor { const Formattable* num;
char16_t save[4];
UBool fWasCurrency;
const UObject* o = obj.getObject(); // most commonly o==nullptr const CurrencyAmount* amt; if (o != nullptr && (amt = dynamic_cast<const CurrencyAmount*>(o)) != nullptr) { // getISOCurrency() returns a pointer to internal storage, so we // copy it to retain it across the call to setCurrency(). //const char16_t* curr = amt->getISOCurrency();
u_strcpy(save, amt->getISOCurrency());
num = &amt->getNumber();
fWasCurrency=true;
} else {
save[0]=0;
}
}
ArgExtractor::~ArgExtractor() {
}
UnicodeString& NumberFormat::format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPositionIterator* posIter,
UErrorCode& status) const { // DecimalFormat overrides this function, and handles DigitList based big decimals. // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists, // so this default implementation falls back to formatting decimal numbers as doubles. if (U_FAILURE(status)) { return appendTo;
} double dnum = number.toDouble();
format(dnum, appendTo, posIter, status); return appendTo;
}
UnicodeString&
NumberFormat::format(const number::impl::DecimalQuantity &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const { // DecimalFormat overrides this function, and handles DigitList based big decimals. // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists, // so this default implementation falls back to formatting decimal numbers as doubles. if (U_FAILURE(status)) { return appendTo;
} double dnum = number.toDouble();
format(dnum, appendTo, pos, status); return appendTo;
}
if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) { // trying to format a different currency. // Right now, we clone.
LocalPointer<NumberFormat> cloneFmt(this->clone());
cloneFmt->setCurrency(iso, status); // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount. return cloneFmt->format(*n, appendTo, pos, status);
}
if (n->isNumeric() && n->getDecimalQuantity() != nullptr) { // Decimal Number. We will have a DigitList available if the value was // set to a decimal number, or if the value originated with a parse. // // The default implementation for formatting a DigitList converts it // to a double, and formats that, allowing formatting classes that don't // know about DigitList to continue to operate as they had. // // DecimalFormat overrides the DigitList formatting functions.
format(*n->getDecimalQuantity(), appendTo, pos, status);
} else { switch (n->getType()) { case Formattable::kDouble:
format(n->getDouble(), appendTo, pos, status); break; case Formattable::kLong:
format(n->getLong(), appendTo, pos, status); break; case Formattable::kInt64:
format(n->getInt64(), appendTo, pos, status); break; default:
status = U_INVALID_FORMAT_ERROR; break;
}
}
return appendTo;
}
// -------------------------------------x // Formats the number object and save the format // result in the toAppendTo string buffer.
if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) { // trying to format a different currency. // Right now, we clone.
LocalPointer<NumberFormat> cloneFmt(this->clone());
cloneFmt->setCurrency(iso, status); // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount. return cloneFmt->format(*n, appendTo, posIter, status);
}
if (n->isNumeric() && n->getDecimalQuantity() != nullptr) { // Decimal Number
format(*n->getDecimalQuantity(), appendTo, posIter, status);
} else { switch (n->getType()) { case Formattable::kDouble:
format(n->getDouble(), appendTo, posIter, status); break; case Formattable::kLong:
format(n->getLong(), appendTo, posIter, status); break; case Formattable::kInt64:
format(n->getInt64(), appendTo, posIter, status); break; default:
status = U_INVALID_FORMAT_ERROR; break;
}
}
return appendTo;
}
// -------------------------------------
UnicodeString&
NumberFormat::format(int64_t number,
UnicodeString& appendTo,
FieldPosition& pos) const
{ // default so we don't introduce a new abstract method return format(static_cast<int32_t>(number), appendTo, pos);
}
// ------------------------------------- // Parses the string and save the result object as well // as the final parsed position.
// ------------------------------------- // Parses the text and save the result object. If the returned // parse position is 0, that means the parsing failed, the status // code needs to be set to failure. Ignores the returned parse // position, otherwise.
UObject* result = _delegate->createFormat(loc, static_cast<UNumberFormatStyle>(kind)); if (result == nullptr) {
result = service->getKey(const_cast<ICUServiceKey&>(key) /* cast away const */, nullptr, this, status);
} return result;
} return nullptr;
}
protected: /** * Return the set of ids that this factory supports (visible or * otherwise). This can be called often and might need to be * cached if it is expensive to create.
*/ virtualconst Hashtable* getSupportedIDs(UErrorCode& status) const override
{ if (U_SUCCESS(status)) { if (!_ids) {
int32_t count = 0; const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status); const_cast<NFFactory*>(this)->_ids = new Hashtable(status); /* cast away const */ if (_ids) { for (int i = 0; i < count; ++i) {
_ids->put(idlist[i], (void*)this, status);
}
}
} return _ids;
} return nullptr;
}
};
void NumberFormat::setContext(UDisplayContext value, UErrorCode& status)
{ if (U_FAILURE(status)) return; if (static_cast<UDisplayContextType>(static_cast<uint32_t>(value) >> 8) == UDISPCTX_TYPE_CAPITALIZATION) {
fCapitalizationContext = value;
} else {
status = U_ILLEGAL_ARGUMENT_ERROR;
}
}
UDisplayContext NumberFormat::getContext(UDisplayContextType type, UErrorCode& status) const
{ if (U_FAILURE(status)) returnstatic_cast<UDisplayContext>(0); if (type != UDISPCTX_TYPE_CAPITALIZATION) {
status = U_ILLEGAL_ARGUMENT_ERROR; returnstatic_cast<UDisplayContext>(0);
} return fCapitalizationContext;
}
// ------------------------------------- // Creates the NumberFormat instance of the specified style (number, currency, // or percent) for the desired locale.
staticvoid U_CALLCONV nscacheInit() {
U_ASSERT(NumberingSystem_cache == nullptr);
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
UErrorCode status = U_ZERO_ERROR;
NumberingSystem_cache = uhash_open(uhash_hashLong,
uhash_compareLong,
nullptr,
&status); if (U_FAILURE(status)) { // Number Format code will run with no cache if creation fails.
NumberingSystem_cache = nullptr; return;
}
uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem);
}
if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) {
status = U_ILLEGAL_ARGUMENT_ERROR; return nullptr;
}
// For the purposes of general number formatting, UNUM_NUMBERING_SYSTEM should behave the same // was as UNUM_DECIMAL. In both cases, you get either a DecimalFormat or a RuleBasedNumberFormat // depending on the locale's numbering system (either the default one for the locale or a specific // one specified by using the "@numbers=" or "-u-nu-" parameter in the locale ID. if (style == UNUM_NUMBERING_SYSTEM) {
style = UNUM_DECIMAL;
}
// 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 nullptr;
}
case UNUM_CURRENCY: case UNUM_CURRENCY_ISO: // do not support plural formatting here case UNUM_CURRENCY_PLURAL: case UNUM_CURRENCY_ACCOUNTING: case UNUM_CASH_CURRENCY: case UNUM_CURRENCY_STANDARD:
{
LocalPointer<Win32NumberFormat> f(new Win32NumberFormat(desiredLocale, curr, status), status); if (U_SUCCESS(status)) { return f.orphan();
}
} break; default: break;
}
}
} #endif // Use numbering system cache hashtable
umtx_initOnce(gNSCacheInitOnce, &nscacheInit);
// Get cached numbering system
LocalPointer<NumberingSystem> ownedNs;
NumberingSystem *ns = nullptr; if (NumberingSystem_cache != nullptr) { // TODO: Bad hash key usage, see ticket #8504.
int32_t hashKey = desiredLocale.hashCode();
RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status); if (r == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return nullptr;
}
r->setDefaultRuleSet(nsRuleSetName,status);
f.adoptInstead(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 argument if its memory allocation fails. // So we can't use adoptInsteadAndCheckErrorCode as we need to know if the 'new' failed.
DecimalFormatSymbols *syms = symbolsToAdopt.getAlias();
LocalPointer<DecimalFormat> df(new DecimalFormat(pattern, syms, style, status));
if (df.isValid()) { // if the DecimalFormat object was successfully new'ed, then it will own symbolsToAdopt, even if the status is a failure.
symbolsToAdopt.orphan();
} else {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(status)) { return nullptr;
}
// if it is cash currency style, setCurrencyUsage with usage if (style == UNUM_CASH_CURRENCY){
df->setCurrencyUsage(UCURR_USAGE_CASH, &status);
}
/** * Get the rounding mode. * @return A rounding mode
*/
NumberFormat::ERoundingMode NumberFormat::getRoundingMode() const { // Default value. ICU4J throws an exception and we can't change this API. return NumberFormat::ERoundingMode::kRoundUnnecessary;
}
/** * Set the rounding mode. This has no effect unless the rounding * increment is greater than zero. * @param roundingMode A rounding mode
*/ void NumberFormat::setRoundingMode(NumberFormat::ERoundingMode /*roundingMode*/) { // No-op ICU4J throws an exception, and we can't change this API.
}
U_NAMESPACE_END
#endif/* #if !UCONFIG_NO_FORMATTING */
//eof
Messung V0.5
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.