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
19using namespace icu;
20using namespace icu::number;
21using namespace icu::number::impl;
22using namespace icu::numparse::impl;
23
24
25Scale::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
40Scale::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
48Scale& 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
60Scale::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
66Scale& 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
78Scale::~Scale() {
79 delete fArbitrary;
80}
81
82
83Scale Scale::none() {
84 return {0, nullptr};
85}
86
87Scale Scale::powerOfTen(int32_t power) {
88 return {power, nullptr};
89}
90
91Scale 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
104Scale 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
117Scale 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
130void 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
138void 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
147void
148MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
149 fMultiplier = multiplier;
150 fParent = parent;
151}
152
153void 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 */
160