int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity, NumberStringBuilder& string, UErrorCode& status) { int32_t length = 0; if (quantity.isInfinite()) { length += string.insert( length, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kInfinitySymbol), UNUM_INTEGER_FIELD, status); } else if (quantity.isNaN()) { length += string.insert( length, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kNaNSymbol), UNUM_INTEGER_FIELD, status); } else { // Add the integer digits length += writeIntegerDigits(micros, quantity, string, status); // Add the decimal point if (quantity.getLowerDisplayMagnitude() < 0 || micros.decimal == UNUM_DECIMAL_SEPARATOR_ALWAYS) { length += string.insert( length, micros.useCurrency ? micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol) : micros .symbols ->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kDecimalSeparatorSymbol), UNUM_DECIMAL_SEPARATOR_FIELD, status); } // Add the fraction digits length += writeFractionDigits(micros, quantity, string, status); } return length; }
int32_t ScientificModifier::apply(NumberStringBuilder &output, int32_t /*leftIndex*/, int32_t rightIndex, UErrorCode &status) const { // FIXME: Localized exponent separator location. int i = rightIndex; // Append the exponent separator and sign i += output.insert( i, fHandler->fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kExponentialSymbol), UNUM_EXPONENT_SYMBOL_FIELD, status); if (fExponent < 0 && fHandler->fSettings.fExponentSignDisplay != UNUM_SIGN_NEVER) { i += output.insert( i, fHandler->fSymbols ->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol), UNUM_EXPONENT_SIGN_FIELD, status); } else if (fExponent >= 0 && fHandler->fSettings.fExponentSignDisplay == UNUM_SIGN_ALWAYS) { i += output.insert( i, fHandler->fSymbols ->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol), UNUM_EXPONENT_SIGN_FIELD, status); } // Append the exponent digits (using a simple inline algorithm) int32_t disp = std::abs(fExponent); for (int j = 0; j < fHandler->fSettings.fMinExponentDigits || disp > 0; j++, disp /= 10) { auto d = static_cast<int8_t>(disp % 10); i += utils::insertDigitFromSymbols( output, i - j, d, *fHandler->fSymbols, UNUM_EXPONENT_FIELD, status); } return i - rightIndex; }
int32_t AffixUtils::unescape(const CharSequence &affixPattern, NumberStringBuilder &output, int32_t position, const SymbolProvider &provider, UErrorCode &status) { int32_t length = 0; AffixTag tag; while (hasNext(tag, affixPattern)) { tag = nextToken(tag, affixPattern, status); if (U_FAILURE(status)) { return length; } if (tag.type == TYPE_CURRENCY_OVERFLOW) { // Don't go to the provider for this special case length += output.insertCodePoint(position + length, 0xFFFD, UNUM_CURRENCY_FIELD, status); } else if (tag.type < 0) { length += output.insert( position + length, provider.getSymbol(tag.type), getFieldForType(tag.type), status); } else { length += output.insertCodePoint(position + length, tag.codePoint, UNUM_FIELD_COUNT, status); } } return length; }
int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity, NumberStringBuilder& string, 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( 0, micros.useCurrency ? micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol) : micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kGroupingSeparatorSymbol), UNUM_GROUPING_SEPARATOR_FIELD, status); } // Get and append the next digit value int8_t nextDigit = quantity.getDigit(i); length += utils::insertDigitFromSymbols( string, 0, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status); } return length; }