number_scientific.cpp [plain text]
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include <cstdlib>
#include "number_scientific.h"
#include "number_utils.h"
#include "number_stringbuilder.h"
#include "unicode/unum.h"
#include "number_microprops.h"
using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
ScientificModifier::ScientificModifier() : fExponent(0), fHandler(nullptr) {}
void ScientificModifier::set(int32_t exponent, const ScientificHandler *handler) {
U_ASSERT(fHandler == nullptr);
fExponent = exponent;
fHandler = handler;
}
int32_t ScientificModifier::apply(NumberStringBuilder &output, int32_t , int32_t rightIndex,
UErrorCode &status) const {
int i = rightIndex;
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);
}
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 ScientificModifier::getPrefixLength() const {
return 0;
}
int32_t ScientificModifier::getCodePointCount() const {
return 999;
}
bool ScientificModifier::isStrong() const {
return true;
}
bool ScientificModifier::containsField(UNumberFormatFields field) const {
(void)field;
UPRV_UNREACHABLE;
}
void ScientificModifier::getParameters(Parameters& output) const {
output.obj = nullptr;
}
bool ScientificModifier::semanticallyEquivalent(const Modifier& other) const {
auto* _other = dynamic_cast<const ScientificModifier*>(&other);
if (_other == nullptr) {
return false;
}
return fExponent == _other->fExponent;
}
icu::number::impl::ScientificHandler::ScientificHandler(const Notation *notation, const DecimalFormatSymbols *symbols,
const MicroPropsGenerator *parent) :
fSettings(notation->fUnion.scientific), fSymbols(symbols), fParent(parent) {}
void ScientificHandler::processQuantity(DecimalQuantity &quantity, MicroProps µs,
UErrorCode &status) const {
fParent->processQuantity(quantity, micros, status);
if (U_FAILURE(status)) { return; }
int32_t exponent;
if (quantity.isZero()) {
if (fSettings.fRequireMinInt && micros.rounder.isSignificantDigits()) {
micros.rounder.apply(quantity, fSettings.fEngineeringInterval, status);
exponent = 0;
} else {
micros.rounder.apply(quantity, status);
exponent = 0;
}
} else {
exponent = -micros.rounder.chooseMultiplierAndApply(quantity, *this, status);
}
ScientificModifier &mod = micros.helpers.scientificModifier;
mod.set(exponent, this);
micros.modInner = &mod;
micros.rounder = RoundingImpl::passThrough();
}
int32_t ScientificHandler::getMultiplier(int32_t magnitude) const {
int32_t interval = fSettings.fEngineeringInterval;
int32_t digitsShown;
if (fSettings.fRequireMinInt) {
digitsShown = interval;
} else if (interval <= 1) {
digitsShown = 1;
} else {
digitsShown = ((magnitude % interval + interval) % interval) + 1;
}
return digitsShown - magnitude - 1;
}
#endif