| // © 2018 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| |
| #include "unicode/utypes.h" |
| |
| #if !UCONFIG_NO_FORMATTING |
| |
| // Allow implicit conversion from char16_t* to UnicodeString for this file: |
| // Helpful in toString methods and elsewhere. |
| #define UNISTR_FROM_STRING_EXPLICIT |
| |
| #include "number_decnum.h" |
| #include "number_types.h" |
| #include "number_multiplier.h" |
| #include "numparse_validators.h" |
| #include "number_utils.h" |
| #include "decNumber.h" |
| |
| using namespace icu; |
| using namespace icu::number; |
| using namespace icu::number::impl; |
| using namespace icu::numparse::impl; |
| |
| |
| Scale::Scale(int32_t magnitude, DecNum* arbitraryToAdopt) |
| : fMagnitude(magnitude), fArbitrary(arbitraryToAdopt), fError(U_ZERO_ERROR) { |
| if (fArbitrary != nullptr) { |
| // Attempt to convert the DecNum to a magnitude multiplier. |
| fArbitrary->normalize(); |
| if (fArbitrary->getRawDecNumber()->digits == 1 && fArbitrary->getRawDecNumber()->lsu[0] == 1 && |
| !fArbitrary->isNegative()) { |
| // Success! |
| fMagnitude += fArbitrary->getRawDecNumber()->exponent; |
| delete fArbitrary; |
| fArbitrary = nullptr; |
| } |
| } |
| } |
| |
| Scale::Scale(const Scale& other) |
| : fMagnitude(other.fMagnitude), fArbitrary(nullptr), fError(other.fError) { |
| if (other.fArbitrary != nullptr) { |
| UErrorCode localStatus = U_ZERO_ERROR; |
| fArbitrary = new DecNum(*other.fArbitrary, localStatus); |
| } |
| } |
| |
| Scale& Scale::operator=(const Scale& other) { |
| fMagnitude = other.fMagnitude; |
| if (other.fArbitrary != nullptr) { |
| UErrorCode localStatus = U_ZERO_ERROR; |
| fArbitrary = new DecNum(*other.fArbitrary, localStatus); |
| } else { |
| fArbitrary = nullptr; |
| } |
| fError = other.fError; |
| return *this; |
| } |
| |
| Scale::Scale(Scale&& src) U_NOEXCEPT |
| : fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) { |
| // Take ownership away from src if necessary |
| src.fArbitrary = nullptr; |
| } |
| |
| Scale& Scale::operator=(Scale&& src) U_NOEXCEPT { |
| fMagnitude = src.fMagnitude; |
| if (fArbitrary != nullptr) { |
| delete fArbitrary; |
| } |
| fArbitrary = src.fArbitrary; |
| fError = src.fError; |
| // Take ownership away from src if necessary |
| src.fArbitrary = nullptr; |
| return *this; |
| } |
| |
| Scale::~Scale() { |
| delete fArbitrary; |
| } |
| |
| |
| Scale Scale::none() { |
| return {0, nullptr}; |
| } |
| |
| Scale Scale::powerOfTen(int32_t power) { |
| return {power, nullptr}; |
| } |
| |
| Scale Scale::byDecimal(StringPiece multiplicand) { |
| UErrorCode localError = U_ZERO_ERROR; |
| LocalPointer<DecNum> decnum(new DecNum(), localError); |
| if (U_FAILURE(localError)) { |
| return {localError}; |
| } |
| decnum->setTo(multiplicand, localError); |
| if (U_FAILURE(localError)) { |
| return {localError}; |
| } |
| return {0, decnum.orphan()}; |
| } |
| |
| Scale Scale::byDouble(double multiplicand) { |
| UErrorCode localError = U_ZERO_ERROR; |
| LocalPointer<DecNum> decnum(new DecNum(), localError); |
| if (U_FAILURE(localError)) { |
| return {localError}; |
| } |
| decnum->setTo(multiplicand, localError); |
| if (U_FAILURE(localError)) { |
| return {localError}; |
| } |
| return {0, decnum.orphan()}; |
| } |
| |
| Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) { |
| UErrorCode localError = U_ZERO_ERROR; |
| LocalPointer<DecNum> decnum(new DecNum(), localError); |
| if (U_FAILURE(localError)) { |
| return {localError}; |
| } |
| decnum->setTo(multiplicand, localError); |
| if (U_FAILURE(localError)) { |
| return {localError}; |
| } |
| return {power, decnum.orphan()}; |
| } |
| |
| void Scale::applyTo(impl::DecimalQuantity& quantity) const { |
| quantity.adjustMagnitude(fMagnitude); |
| if (fArbitrary != nullptr) { |
| UErrorCode localStatus = U_ZERO_ERROR; |
| quantity.multiplyBy(*fArbitrary, localStatus); |
| } |
| } |
| |
| void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const { |
| quantity.adjustMagnitude(-fMagnitude); |
| if (fArbitrary != nullptr) { |
| UErrorCode localStatus = U_ZERO_ERROR; |
| quantity.divideBy(*fArbitrary, localStatus); |
| } |
| } |
| |
| |
| void |
| MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) { |
| fMultiplier = multiplier; |
| fParent = parent; |
| } |
| |
| void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros, |
| UErrorCode& status) const { |
| fParent->processQuantity(quantity, micros, status); |
| fMultiplier.applyTo(quantity); |
| } |
| |
| #endif /* #if !UCONFIG_NO_FORMATTING */ |