number_multiplier.cpp (4619B)
1 // © 2018 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 4 #include "unicode/utypes.h" 5 6 #if !UCONFIG_NO_FORMATTING 7 8 // Allow implicit conversion from char16_t* to UnicodeString for this file: 9 // Helpful in toString methods and elsewhere. 10 #define UNISTR_FROM_STRING_EXPLICIT 11 12 #include "number_decnum.h" 13 #include "number_types.h" 14 #include "number_multiplier.h" 15 #include "numparse_validators.h" 16 #include "number_utils.h" 17 #include "decNumber.h" 18 19 using namespace icu; 20 using namespace icu::number; 21 using namespace icu::number::impl; 22 using namespace icu::numparse::impl; 23 24 25 Scale::Scale(int32_t magnitude, DecNum* arbitraryToAdopt) 26 : fMagnitude(magnitude), fArbitrary(arbitraryToAdopt), fError(U_ZERO_ERROR) { 27 if (fArbitrary != nullptr) { 28 // Attempt to convert the DecNum to a magnitude multiplier. 29 fArbitrary->normalize(); 30 if (fArbitrary->getRawDecNumber()->digits == 1 && fArbitrary->getRawDecNumber()->lsu[0] == 1 && 31 !fArbitrary->isNegative()) { 32 // Success! 33 fMagnitude += fArbitrary->getRawDecNumber()->exponent; 34 delete fArbitrary; 35 fArbitrary = nullptr; 36 } 37 } 38 } 39 40 Scale::Scale(const Scale& other) 41 : fMagnitude(other.fMagnitude), fArbitrary(nullptr), fError(other.fError) { 42 if (other.fArbitrary != nullptr) { 43 UErrorCode localStatus = U_ZERO_ERROR; 44 fArbitrary = new DecNum(*other.fArbitrary, localStatus); 45 } 46 } 47 48 Scale& Scale::operator=(const Scale& other) { 49 if (this == &other) { return *this; } // self-assignment: no-op 50 fMagnitude = other.fMagnitude; 51 if (other.fArbitrary != nullptr) { 52 UErrorCode localStatus = U_ZERO_ERROR; 53 fArbitrary = new DecNum(*other.fArbitrary, localStatus); 54 } else { 55 fArbitrary = nullptr; 56 } 57 fError = other.fError; 58 return *this; 59 } 60 61 Scale::Scale(Scale&& src) noexcept 62 : fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) { 63 // Take ownership away from src if necessary 64 src.fArbitrary = nullptr; 65 } 66 67 Scale& Scale::operator=(Scale&& src) noexcept { 68 fMagnitude = src.fMagnitude; 69 delete fArbitrary; 70 fArbitrary = src.fArbitrary; 71 fError = src.fError; 72 // Take ownership away from src if necessary 73 src.fArbitrary = nullptr; 74 return *this; 75 } 76 77 Scale::~Scale() { 78 delete fArbitrary; 79 } 80 81 82 Scale Scale::none() { 83 return {0, nullptr}; 84 } 85 86 Scale Scale::powerOfTen(int32_t power) { 87 return {power, nullptr}; 88 } 89 90 Scale Scale::byDecimal(StringPiece multiplicand) { 91 UErrorCode localError = U_ZERO_ERROR; 92 LocalPointer<DecNum> decnum(new DecNum(), localError); 93 if (U_FAILURE(localError)) { 94 return {localError}; 95 } 96 decnum->setTo(multiplicand, localError); 97 if (U_FAILURE(localError)) { 98 return {localError}; 99 } 100 return {0, decnum.orphan()}; 101 } 102 103 Scale Scale::byDouble(double multiplicand) { 104 UErrorCode localError = U_ZERO_ERROR; 105 LocalPointer<DecNum> decnum(new DecNum(), localError); 106 if (U_FAILURE(localError)) { 107 return {localError}; 108 } 109 decnum->setTo(multiplicand, localError); 110 if (U_FAILURE(localError)) { 111 return {localError}; 112 } 113 return {0, decnum.orphan()}; 114 } 115 116 Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) { 117 UErrorCode localError = U_ZERO_ERROR; 118 LocalPointer<DecNum> decnum(new DecNum(), localError); 119 if (U_FAILURE(localError)) { 120 return {localError}; 121 } 122 decnum->setTo(multiplicand, localError); 123 if (U_FAILURE(localError)) { 124 return {localError}; 125 } 126 return {power, decnum.orphan()}; 127 } 128 129 void Scale::applyTo(impl::DecimalQuantity& quantity) const { 130 quantity.adjustMagnitude(fMagnitude); 131 if (fArbitrary != nullptr) { 132 UErrorCode localStatus = U_ZERO_ERROR; 133 quantity.multiplyBy(*fArbitrary, localStatus); 134 } 135 } 136 137 void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const { 138 quantity.adjustMagnitude(-fMagnitude); 139 if (fArbitrary != nullptr) { 140 UErrorCode localStatus = U_ZERO_ERROR; 141 quantity.divideBy(*fArbitrary, localStatus); 142 } 143 } 144 145 146 void 147 MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) { 148 fMultiplier = multiplier; 149 fParent = parent; 150 } 151 152 void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros, 153 UErrorCode& status) const { 154 fParent->processQuantity(quantity, micros, status); 155 fMultiplier.applyTo(quantity); 156 } 157 158 #endif /* #if !UCONFIG_NO_FORMATTING */