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