blob: 058c5923b4567b64db2571fe992870e83a363e89 [file] [log] [blame]
Victor Chang73229502020-09-17 13:39:19 +01001// © 2017 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#ifndef __NUMBER_MICROPROPS_H__
8#define __NUMBER_MICROPROPS_H__
9
10// TODO: minimize includes
11#include "unicode/numberformatter.h"
12#include "number_types.h"
13#include "number_decimalquantity.h"
14#include "number_scientific.h"
15#include "number_patternstring.h"
16#include "number_modifiers.h"
17#include "number_multiplier.h"
18#include "number_roundingutils.h"
19#include "decNumber.h"
20#include "charstr.h"
21
22U_NAMESPACE_BEGIN namespace number {
23namespace impl {
24
Victor Changce4bf3c2021-01-19 16:34:24 +000025/**
26 * A copyable container for the integer values of mixed unit measurements.
27 *
28 * If memory allocation fails during copying, no values are copied and status is
29 * set to U_MEMORY_ALLOCATION_ERROR.
30 */
31class IntMeasures : public MaybeStackArray<int64_t, 2> {
32 public:
33 /**
34 * Default constructor initializes with internal T[stackCapacity] buffer.
35 *
36 * Stack Capacity: most mixed units are expected to consist of two or three
37 * subunits, so one or two integer measures should be enough.
38 */
39 IntMeasures() : MaybeStackArray<int64_t, 2>() {
40 }
41
42 /**
43 * Copy constructor.
44 *
45 * If memory allocation fails during copying, no values are copied and
46 * status is set to U_MEMORY_ALLOCATION_ERROR.
47 */
48 IntMeasures(const IntMeasures &other) : MaybeStackArray<int64_t, 2>() {
49 this->operator=(other);
50 }
51
52 // Assignment operator
53 IntMeasures &operator=(const IntMeasures &rhs) {
54 if (this == &rhs) {
55 return *this;
56 }
57 copyFrom(rhs, status);
58 return *this;
59 }
60
61 /** Move constructor */
62 IntMeasures(IntMeasures &&src) = default;
63
64 /** Move assignment */
65 IntMeasures &operator=(IntMeasures &&src) = default;
66
67 UErrorCode status = U_ZERO_ERROR;
68};
69
70/**
71 * MicroProps is the first MicroPropsGenerator that should be should be called,
72 * producing an initialized MicroProps instance that will be passed on and
73 * modified throughout the rest of the chain of MicroPropsGenerator instances.
74 */
Victor Chang73229502020-09-17 13:39:19 +010075struct MicroProps : public MicroPropsGenerator {
76
77 // NOTE: All of these fields are properly initialized in NumberFormatterImpl.
78 RoundingImpl rounder;
79 Grouper grouping;
80 Padder padding;
81 IntegerWidth integerWidth;
82 UNumberSignDisplay sign;
83 UNumberDecimalSeparatorDisplay decimal;
84 bool useCurrency;
85 char nsName[9];
86
87 // Note: This struct has no direct ownership of the following pointers.
88 const DecimalFormatSymbols* symbols;
Victor Changce4bf3c2021-01-19 16:34:24 +000089
90 // Pointers to Modifiers provided by the number formatting pipeline (when
91 // the value is known):
92
93 // A Modifier provided by LongNameHandler, used for currency long names and
94 // units. If there is no LongNameHandler needed, this should be an
95 // EmptyModifier. (This is typically the third modifier applied.)
Victor Chang73229502020-09-17 13:39:19 +010096 const Modifier* modOuter;
Victor Changce4bf3c2021-01-19 16:34:24 +000097 // A Modifier for short currencies and compact notation. (This is typically
98 // the second modifier applied.)
Victor Changd8aa9d52021-01-05 23:49:57 +000099 const Modifier* modMiddle = nullptr;
Victor Changce4bf3c2021-01-19 16:34:24 +0000100 // A Modifier provided by ScientificHandler, used for scientific notation.
101 // This is typically the first modifier applied.
Victor Chang73229502020-09-17 13:39:19 +0100102 const Modifier* modInner;
103
104 // The following "helper" fields may optionally be used during the MicroPropsGenerator.
105 // They live here to retain memory.
106 struct {
Victor Changce4bf3c2021-01-19 16:34:24 +0000107 // The ScientificModifier for which ScientificHandler is responsible.
108 // ScientificHandler::processQuantity() modifies this Modifier.
Victor Chang73229502020-09-17 13:39:19 +0100109 ScientificModifier scientificModifier;
Victor Changce4bf3c2021-01-19 16:34:24 +0000110 // EmptyModifier used for modOuter
Victor Chang73229502020-09-17 13:39:19 +0100111 EmptyModifier emptyWeakModifier{false};
Victor Changce4bf3c2021-01-19 16:34:24 +0000112 // EmptyModifier used for modInner
Victor Chang73229502020-09-17 13:39:19 +0100113 EmptyModifier emptyStrongModifier{true};
114 MultiplierFormatHandler multiplier;
Victor Changce4bf3c2021-01-19 16:34:24 +0000115 // A Modifier used for Mixed Units. When formatting mixed units,
116 // LongNameHandler assigns this Modifier.
117 SimpleModifier mixedUnitModifier;
Victor Chang73229502020-09-17 13:39:19 +0100118 } helpers;
119
Victor Changce4bf3c2021-01-19 16:34:24 +0000120 // The MeasureUnit with which the output is represented. May also have
121 // UMEASURE_UNIT_MIXED complexity, in which case mixedMeasures comes into
122 // play.
123 MeasureUnit outputUnit;
124
125 // In the case of mixed units, this is the set of integer-only units
126 // *preceding* the final unit.
127 IntMeasures mixedMeasures;
128 // Number of mixedMeasures that have been populated
129 int32_t mixedMeasuresCount = 0;
Victor Chang73229502020-09-17 13:39:19 +0100130
131 MicroProps() = default;
132
133 MicroProps(const MicroProps& other) = default;
134
135 MicroProps& operator=(const MicroProps& other) = default;
136
Victor Changce4bf3c2021-01-19 16:34:24 +0000137 /**
138 * As MicroProps is the "base instance", this implementation of
139 * MicroPropsGenerator::processQuantity() just ensures that the output
140 * `micros` is correctly initialized.
141 *
142 * For the "safe" invocation of this function, micros must not be *this,
143 * such that a copy of the base instance is made. For the "unsafe" path,
144 * this function can be used only once, because the base MicroProps instance
145 * will be modified and thus not be available for re-use.
146 *
147 * @param quantity The quantity for consideration and optional mutation.
148 * @param micros The MicroProps instance to populate. If this parameter is
149 * not already `*this`, it will be overwritten with a copy of `*this`.
150 */
151 void processQuantity(DecimalQuantity &quantity, MicroProps &micros,
152 UErrorCode &status) const U_OVERRIDE {
153 (void) quantity;
Victor Chang73229502020-09-17 13:39:19 +0100154 (void) status;
155 if (this == &micros) {
156 // Unsafe path: no need to perform a copy.
157 U_ASSERT(!exhausted);
158 micros.exhausted = true;
159 U_ASSERT(exhausted);
160 } else {
161 // Safe path: copy self into the output micros.
Victor Changce4bf3c2021-01-19 16:34:24 +0000162 U_ASSERT(!exhausted);
Victor Chang73229502020-09-17 13:39:19 +0100163 micros = *this;
164 }
165 }
166
167 private:
168 // Internal fields:
169 bool exhausted = false;
170};
171
172} // namespace impl
173} // namespace number
174U_NAMESPACE_END
175
176#endif // __NUMBER_MICROPROPS_H__
177
178#endif /* #if !UCONFIG_NO_FORMATTING */