// NOTE: C++ SPECIFIC DIFFERENCE FROM JAVA: // The "safe" apply method uses a new MicroProps. In the MicroPropsGenerator, fMicros is copied into the new instance. // The "unsafe" method simply re-uses fMicros, eliminating the extra copy operation. // See MicroProps::processQuantity() for details.
void NumberFormatterImpl::preProcess(DecimalQuantity& inValue, MicroProps& microsOut,
UErrorCode& status) const { if (U_FAILURE(status)) { return; } if (fMicroPropsGenerator == nullptr) {
status = U_INTERNAL_PROGRAM_ERROR; return;
}
fMicroPropsGenerator->processQuantity(inValue, microsOut, status);
microsOut.integerWidth.apply(inValue, status);
}
MicroProps& NumberFormatterImpl::preProcessUnsafe(DecimalQuantity& inValue, UErrorCode& status) { if (U_FAILURE(status)) { return fMicros; // must always return a value
} if (fMicroPropsGenerator == nullptr) {
status = U_INTERNAL_PROGRAM_ERROR; return fMicros; // must always return a value
}
fMicroPropsGenerator->processQuantity(inValue, fMicros, status);
fMicros.integerWidth.apply(inValue, status); return fMicros;
}
int32_t NumberFormatterImpl::getPrefixSuffix(Signum signum, StandardPlural::Form plural,
FormattedStringBuilder& outString, UErrorCode& status) const { if (U_FAILURE(status)) { return 0; } // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier). // Safe path: use fImmutablePatternModifier. const Modifier* modifier = fImmutablePatternModifier->getModifier(signum, plural);
modifier->apply(outString, 0, 0, status); if (U_FAILURE(status)) { return 0; } return modifier->getPrefixLength();
}
int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(Signum signum, StandardPlural::Form plural,
FormattedStringBuilder& outString, UErrorCode& status) { if (U_FAILURE(status)) { return 0; } // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier). // Unsafe path: use fPatternModifier.
fPatternModifier->setNumberProperties(signum, plural);
fPatternModifier->apply(outString, 0, 0, status); if (U_FAILURE(status)) { return 0; } return fPatternModifier->getPrefixLength();
}
// Check that macros is error-free before continuing. if (macros.copyErrorTo(status)) { return nullptr;
}
// TODO: Accept currency symbols from DecimalFormatSymbols?
// Pre-compute a few values for efficiency. bool isCurrency = utils::unitIsCurrency(macros.unit); bool isBaseUnit = utils::unitIsBaseUnit(macros.unit); bool isPercent = utils::unitIsPercent(macros.unit); bool isPermille = utils::unitIsPermille(macros.unit); bool isCompactNotation = macros.notation.fType == Notation::NTN_COMPACT; bool isAccounting =
macros.sign == UNUM_SIGN_ACCOUNTING ||
macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS ||
macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO ||
macros.sign == UNUM_SIGN_ACCOUNTING_NEGATIVE;
CurrencyUnit currency(u"", status); if (isCurrency) {
currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit
}
UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_SHORT; if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) {
unitWidth = macros.unitWidth;
} // Use CLDR unit data for all MeasureUnits (not currency and not // no-unit), except use the dedicated percent pattern for percent and // permille. However, use the CLDR unit data for percent/permille if a // long name was requested OR if compact notation is being used, since // compact notation overrides the middle modifier (micros.modMiddle) // normally used for the percent pattern. bool isCldrUnit = !isCurrency
&& !isBaseUnit
&& (unitWidth == UNUM_UNIT_WIDTH_FULL_NAME
|| !(isPercent || isPermille)
|| isCompactNotation
); bool isMixedUnit = isCldrUnit && (uprv_strcmp(macros.unit.getType(), "") == 0) &&
macros.unit.getComplexity(status) == UMEASURE_UNIT_MIXED;
// Select the numbering system.
LocalPointer<const NumberingSystem> nsLocal; const NumberingSystem* ns; if (macros.symbols.isNumberingSystem()) {
ns = macros.symbols.getNumberingSystem();
} else { // TODO: Is there a way to avoid creating the NumberingSystem object?
ns = NumberingSystem::createInstance(macros.locale, status); // Give ownership to the function scope.
nsLocal.adoptInstead(ns);
} constchar* nsName = U_SUCCESS(status) ? ns->getName() : "latn";
uprv_strncpy(fMicros.nsName, nsName, 8);
fMicros.nsName[8] = 0; // guarantee NUL-terminated
// Default gender: none.
fMicros.gender = "";
// Resolve the symbols. Do this here because currency may need to customize them. if (macros.symbols.isDecimalFormatSymbols()) {
fMicros.simple.symbols = macros.symbols.getDecimalFormatSymbols();
} else {
LocalPointer<DecimalFormatSymbols> newSymbols( new DecimalFormatSymbols(macros.locale, *ns, status), status); if (U_FAILURE(status)) { return nullptr;
} if (isCurrency) {
newSymbols->setCurrency(currency.getISOCurrency(), status); if (U_FAILURE(status)) { return nullptr;
}
}
fMicros.simple.symbols = newSymbols.getAlias();
fSymbols.adoptInstead(newSymbols.orphan());
}
// Load and parse the pattern string. It is used for grouping sizes and affixes only. // If we are formatting currency, check for a currency-specific pattern. const char16_t* pattern = nullptr; if (isCurrency && fMicros.simple.symbols->getCurrencyPattern() != nullptr) {
pattern = fMicros.simple.symbols->getCurrencyPattern();
} if (pattern == nullptr) {
CldrPatternStyle patternStyle; if (isCldrUnit) {
patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
} elseif (isPercent || isPermille) {
patternStyle = CLDR_PATTERN_STYLE_PERCENT;
} elseif (!isCurrency || unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
} elseif (isAccounting) { // NOTE: Although ACCOUNTING and ACCOUNTING_ALWAYS are only supported in currencies right now, // the API contract allows us to add support to other units in the future.
patternStyle = CLDR_PATTERN_STYLE_ACCOUNTING;
} else {
patternStyle = CLDR_PATTERN_STYLE_CURRENCY;
}
pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status); if (U_FAILURE(status)) { return nullptr;
}
} auto* patternInfo = new ParsedPatternInfo(); if (patternInfo == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return nullptr;
}
fPatternInfo.adoptInstead(patternInfo);
PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status); if (U_FAILURE(status)) { return nullptr;
}
///////////////////////////////////////////////////////////////////////////////////// /// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR /// /////////////////////////////////////////////////////////////////////////////////////
// Unit Preferences and Conversions as our first step if (macros.usage.isSet()) { if (!isCldrUnit) { // We only support "usage" when the input unit is specified, and is // a CLDR Unit.
status = U_ILLEGAL_ARGUMENT_ERROR; return nullptr;
} auto* usagePrefsHandler = new UsagePrefsHandler(macros.locale, macros.unit, macros.usage.fValue, chain, status);
fUsagePrefsHandler.adoptInsteadAndCheckErrorCode(usagePrefsHandler, status);
chain = fUsagePrefsHandler.getAlias();
} elseif (isMixedUnit) { auto* unitConversionHandler = new UnitConversionHandler(macros.unit, chain, status);
fUnitConversionHandler.adoptInsteadAndCheckErrorCode(unitConversionHandler, status);
chain = fUnitConversionHandler.getAlias();
}
// Always add the pattern modifier as the last element of the chain. if (safe) {
fImmutablePatternModifier->addToChain(chain);
chain = fImmutablePatternModifier.getAlias();
} else {
patternModifier->addToChain(chain);
chain = patternModifier;
}
if (length == 0) { // Force output of the digit for value 0
length += utils::insertDigitFromSymbols(
string,
index,
0,
*micros.symbols,
{UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD},
status);
}
}
return length;
}
int32_t NumberFormatterImpl::writeIntegerDigits( const SimpleMicroProps& micros,
DecimalQuantity& quantity,
FormattedStringBuilder& string,
int32_t index,
UErrorCode& status) { int length = 0; int integerCount = quantity.getUpperDisplayMagnitude() + 1; for (int i = 0; i < integerCount; i++) { // Add grouping separator if (micros.grouping.groupAtPosition(i, quantity)) {
length += string.insert(
index,
micros.useCurrency ? micros.symbols->getSymbol(
DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol)
: micros.symbols->getSymbol(
DecimalFormatSymbols::ENumberFormatSymbol::kGroupingSeparatorSymbol),
{UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD},
status);
}
// Get and append the next digit value
int8_t nextDigit = quantity.getDigit(i);
length += utils::insertDigitFromSymbols(
string,
index,
nextDigit,
*micros.symbols,
{UFIELD_CATEGORY_NUMBER,
UNUM_INTEGER_FIELD},
status);
} return length;
}
int32_t NumberFormatterImpl::writeFractionDigits( const SimpleMicroProps& micros,
DecimalQuantity& quantity,
FormattedStringBuilder& string,
int32_t index,
UErrorCode& status) { int length = 0; int fractionCount = -quantity.getLowerDisplayMagnitude(); for (int i = 0; i < fractionCount; i++) { // Get and append the next digit value
int8_t nextDigit = quantity.getDigit(-i - 1);
length += utils::insertDigitFromSymbols(
string,
length + index,
nextDigit,
*micros.symbols,
{UFIELD_CATEGORY_NUMBER, UNUM_FRACTION_FIELD},
status);
} return length;
}
#endif/* #if !UCONFIG_NO_FORMATTING */
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 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.