xref: /aosp_15_r20/external/icu/icu4c/source/i18n/number_multiplier.cpp (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
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 
Scale(int32_t magnitude,DecNum * arbitraryToAdopt)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 
Scale(const Scale & other)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 
operator =(const Scale & other)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 
Scale(Scale && src)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 
operator =(Scale && src)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 
~Scale()77 Scale::~Scale() {
78     delete fArbitrary;
79 }
80 
81 
none()82 Scale Scale::none() {
83     return {0, nullptr};
84 }
85 
powerOfTen(int32_t power)86 Scale Scale::powerOfTen(int32_t power) {
87     return {power, nullptr};
88 }
89 
byDecimal(StringPiece multiplicand)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 
byDouble(double multiplicand)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 
byDoubleAndPowerOfTen(double multiplicand,int32_t power)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 
applyTo(impl::DecimalQuantity & quantity) const129 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 
applyReciprocalTo(impl::DecimalQuantity & quantity) const137 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
setAndChain(const Scale & multiplier,const MicroPropsGenerator * parent)147 MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
148     fMultiplier = multiplier;
149     fParent = parent;
150 }
151 
processQuantity(DecimalQuantity & quantity,MicroProps & micros,UErrorCode & status) const152 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 */
159