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