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 fMagnitude = other.fMagnitude;
50 if (other.fArbitrary != nullptr) {
51 UErrorCode localStatus = U_ZERO_ERROR;
52 fArbitrary = new DecNum(*other.fArbitrary, localStatus);
53 } else {
54 fArbitrary = nullptr;
55 }
56 fError = other.fError;
57 return *this;
58 }
59
Scale(Scale && src)60 Scale::Scale(Scale&& src) U_NOEXCEPT
61 : fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) {
62 // Take ownership away from src if necessary
63 src.fArbitrary = nullptr;
64 }
65
operator =(Scale && src)66 Scale& Scale::operator=(Scale&& src) U_NOEXCEPT {
67 fMagnitude = src.fMagnitude;
68 fArbitrary = src.fArbitrary;
69 fError = src.fError;
70 // Take ownership away from src if necessary
71 src.fArbitrary = nullptr;
72 return *this;
73 }
74
~Scale()75 Scale::~Scale() {
76 delete fArbitrary;
77 }
78
79
none()80 Scale Scale::none() {
81 return {0, nullptr};
82 }
83
powerOfTen(int32_t power)84 Scale Scale::powerOfTen(int32_t power) {
85 return {power, nullptr};
86 }
87
byDecimal(StringPiece multiplicand)88 Scale Scale::byDecimal(StringPiece multiplicand) {
89 UErrorCode localError = U_ZERO_ERROR;
90 LocalPointer<DecNum> decnum(new DecNum(), localError);
91 if (U_FAILURE(localError)) {
92 return {localError};
93 }
94 decnum->setTo(multiplicand, localError);
95 if (U_FAILURE(localError)) {
96 return {localError};
97 }
98 return {0, decnum.orphan()};
99 }
100
byDouble(double multiplicand)101 Scale Scale::byDouble(double multiplicand) {
102 UErrorCode localError = U_ZERO_ERROR;
103 LocalPointer<DecNum> decnum(new DecNum(), localError);
104 if (U_FAILURE(localError)) {
105 return {localError};
106 }
107 decnum->setTo(multiplicand, localError);
108 if (U_FAILURE(localError)) {
109 return {localError};
110 }
111 return {0, decnum.orphan()};
112 }
113
byDoubleAndPowerOfTen(double multiplicand,int32_t power)114 Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) {
115 UErrorCode localError = U_ZERO_ERROR;
116 LocalPointer<DecNum> decnum(new DecNum(), localError);
117 if (U_FAILURE(localError)) {
118 return {localError};
119 }
120 decnum->setTo(multiplicand, localError);
121 if (U_FAILURE(localError)) {
122 return {localError};
123 }
124 return {power, decnum.orphan()};
125 }
126
applyTo(impl::DecimalQuantity & quantity) const127 void Scale::applyTo(impl::DecimalQuantity& quantity) const {
128 quantity.adjustMagnitude(fMagnitude);
129 if (fArbitrary != nullptr) {
130 UErrorCode localStatus = U_ZERO_ERROR;
131 quantity.multiplyBy(*fArbitrary, localStatus);
132 }
133 }
134
applyReciprocalTo(impl::DecimalQuantity & quantity) const135 void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const {
136 quantity.adjustMagnitude(-fMagnitude);
137 if (fArbitrary != nullptr) {
138 UErrorCode localStatus = U_ZERO_ERROR;
139 quantity.divideBy(*fArbitrary, localStatus);
140 }
141 }
142
143
144 void
setAndChain(const Scale & multiplier,const MicroPropsGenerator * parent)145 MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
146 fMultiplier = multiplier;
147 fParent = parent;
148 }
149
processQuantity(DecimalQuantity & quantity,MicroProps & micros,UErrorCode & status) const150 void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros,
151 UErrorCode& status) const {
152 fParent->processQuantity(quantity, micros, status);
153 fMultiplier.applyTo(quantity);
154 }
155
156 #endif /* #if !UCONFIG_NO_FORMATTING */
157