]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/number_multiplier.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / number_multiplier.cpp
CommitLineData
0f5d89e8
A
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 fArbitrary = src.fArbitrary;
69 fError = src.fError;
70 // Take ownership away from src if necessary
71 src.fArbitrary = nullptr;
72 return *this;
73}
74
75Scale::~Scale() {
76 delete fArbitrary;
77}
78
79
80Scale Scale::none() {
81 return {0, nullptr};
82}
83
84Scale Scale::powerOfTen(int32_t power) {
85 return {power, nullptr};
86}
87
88Scale 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
101Scale 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
114Scale 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
127void 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
135void 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
144void
145MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
146 this->multiplier = multiplier;
147 this->parent = parent;
148}
149
150void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros,
151 UErrorCode& status) const {
152 parent->processQuantity(quantity, micros, status);
153 multiplier.applyTo(quantity);
154}
155
156#endif /* #if !UCONFIG_NO_FORMATTING */