You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.6 KiB
161 lines
4.6 KiB
4 months ago
|
// © 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) {
|
||
|
if (this == &other) { return *this; } // self-assignment: no-op
|
||
|
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 */
|