Coverage Report

Created: 2025-06-24 06:43

/src/icu/source/i18n/number_multiplier.cpp
Line
Count
Source (jump to first uncovered line)
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
0
        : fMagnitude(magnitude), fArbitrary(arbitraryToAdopt), fError(U_ZERO_ERROR) {
27
0
    if (fArbitrary != nullptr) {
28
        // Attempt to convert the DecNum to a magnitude multiplier.
29
0
        fArbitrary->normalize();
30
0
        if (fArbitrary->getRawDecNumber()->digits == 1 && fArbitrary->getRawDecNumber()->lsu[0] == 1 &&
31
0
            !fArbitrary->isNegative()) {
32
            // Success!
33
0
            fMagnitude += fArbitrary->getRawDecNumber()->exponent;
34
0
            delete fArbitrary;
35
0
            fArbitrary = nullptr;
36
0
        }
37
0
    }
38
0
}
39
40
Scale::Scale(const Scale& other)
41
0
        : fMagnitude(other.fMagnitude), fArbitrary(nullptr), fError(other.fError) {
42
0
    if (other.fArbitrary != nullptr) {
43
0
        UErrorCode localStatus = U_ZERO_ERROR;
44
0
        fArbitrary = new DecNum(*other.fArbitrary, localStatus);
45
0
    }
46
0
}
47
48
0
Scale& Scale::operator=(const Scale& other) {
49
0
    if (this == &other) { return *this; }  // self-assignment: no-op
50
0
    fMagnitude = other.fMagnitude;
51
0
    if (other.fArbitrary != nullptr) {
52
0
        UErrorCode localStatus = U_ZERO_ERROR;
53
0
        fArbitrary = new DecNum(*other.fArbitrary, localStatus);
54
0
    } else {
55
0
        fArbitrary = nullptr;
56
0
    }
57
0
    fError = other.fError;
58
0
    return *this;
59
0
}
60
61
Scale::Scale(Scale&& src) U_NOEXCEPT
62
0
        : fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) {
63
    // Take ownership away from src if necessary
64
0
    src.fArbitrary = nullptr;
65
0
}
66
67
0
Scale& Scale::operator=(Scale&& src) U_NOEXCEPT {
68
0
    fMagnitude = src.fMagnitude;
69
0
    if (fArbitrary != nullptr) {
70
0
        delete fArbitrary;
71
0
    }
72
0
    fArbitrary = src.fArbitrary;
73
0
    fError = src.fError;
74
    // Take ownership away from src if necessary
75
0
    src.fArbitrary = nullptr;
76
0
    return *this;
77
0
}
78
79
0
Scale::~Scale() {
80
0
    delete fArbitrary;
81
0
}
82
83
84
0
Scale Scale::none() {
85
0
    return {0, nullptr};
86
0
}
87
88
0
Scale Scale::powerOfTen(int32_t power) {
89
0
    return {power, nullptr};
90
0
}
91
92
0
Scale Scale::byDecimal(StringPiece multiplicand) {
93
0
    UErrorCode localError = U_ZERO_ERROR;
94
0
    LocalPointer<DecNum> decnum(new DecNum(), localError);
95
0
    if (U_FAILURE(localError)) {
96
0
        return {localError};
97
0
    }
98
0
    decnum->setTo(multiplicand, localError);
99
0
    if (U_FAILURE(localError)) {
100
0
        return {localError};
101
0
    }
102
0
    return {0, decnum.orphan()};
103
0
}
104
105
0
Scale Scale::byDouble(double multiplicand) {
106
0
    UErrorCode localError = U_ZERO_ERROR;
107
0
    LocalPointer<DecNum> decnum(new DecNum(), localError);
108
0
    if (U_FAILURE(localError)) {
109
0
        return {localError};
110
0
    }
111
0
    decnum->setTo(multiplicand, localError);
112
0
    if (U_FAILURE(localError)) {
113
0
        return {localError};
114
0
    }
115
0
    return {0, decnum.orphan()};
116
0
}
117
118
0
Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) {
119
0
    UErrorCode localError = U_ZERO_ERROR;
120
0
    LocalPointer<DecNum> decnum(new DecNum(), localError);
121
0
    if (U_FAILURE(localError)) {
122
0
        return {localError};
123
0
    }
124
0
    decnum->setTo(multiplicand, localError);
125
0
    if (U_FAILURE(localError)) {
126
0
        return {localError};
127
0
    }
128
0
    return {power, decnum.orphan()};
129
0
}
130
131
0
void Scale::applyTo(impl::DecimalQuantity& quantity) const {
132
0
    quantity.adjustMagnitude(fMagnitude);
133
0
    if (fArbitrary != nullptr) {
134
0
        UErrorCode localStatus = U_ZERO_ERROR;
135
0
        quantity.multiplyBy(*fArbitrary, localStatus);
136
0
    }
137
0
}
138
139
0
void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const {
140
0
    quantity.adjustMagnitude(-fMagnitude);
141
0
    if (fArbitrary != nullptr) {
142
0
        UErrorCode localStatus = U_ZERO_ERROR;
143
0
        quantity.divideBy(*fArbitrary, localStatus);
144
0
    }
145
0
}
146
147
148
void
149
0
MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) {
150
0
    fMultiplier = multiplier;
151
0
    fParent = parent;
152
0
}
153
154
void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros,
155
0
                                              UErrorCode& status) const {
156
0
    fParent->processQuantity(quantity, micros, status);
157
0
    fMultiplier.applyTo(quantity);
158
0
}
159
160
#endif /* #if !UCONFIG_NO_FORMATTING */