/src/icu/icu4c/source/i18n/number_microprops.h
Line | Count | Source (jump to first uncovered line) |
1 | | // © 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 | | #include "util.h" |
22 | | |
23 | | U_NAMESPACE_BEGIN |
24 | | namespace number::impl { |
25 | | |
26 | | /** |
27 | | * A copyable container for the integer values of mixed unit measurements. |
28 | | * |
29 | | * If memory allocation fails during copying, no values are copied and status is |
30 | | * set to U_MEMORY_ALLOCATION_ERROR. |
31 | | */ |
32 | | class IntMeasures : public MaybeStackArray<int64_t, 2> { |
33 | | public: |
34 | | /** |
35 | | * Default constructor initializes with internal T[stackCapacity] buffer. |
36 | | * |
37 | | * Stack Capacity: most mixed units are expected to consist of two or three |
38 | | * subunits, so one or two integer measures should be enough. |
39 | | */ |
40 | 1.27M | IntMeasures() : MaybeStackArray<int64_t, 2>() {} |
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 | 0 | IntMeasures(const IntMeasures &other) : MaybeStackArray<int64_t, 2>() { |
49 | 0 | this->operator=(other); |
50 | 0 | } |
51 | | |
52 | | // Assignment operator |
53 | 1.26M | IntMeasures &operator=(const IntMeasures &rhs) { |
54 | 1.26M | if (this == &rhs) { |
55 | 0 | return *this; |
56 | 0 | } |
57 | 1.26M | copyFrom(rhs, status); |
58 | 1.26M | return *this; |
59 | 1.26M | } |
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 | | struct SimpleMicroProps : public UMemory { |
71 | | Grouper grouping; |
72 | | bool useCurrency = false; |
73 | | UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_AUTO; |
74 | | |
75 | | // Currency symbol to be used as the decimal separator |
76 | | UnicodeString currencyAsDecimal = ICU_Utility::makeBogusString(); |
77 | | |
78 | | // Note: This struct has no direct ownership of the following pointer. |
79 | | const DecimalFormatSymbols* symbols = nullptr; |
80 | | }; |
81 | | |
82 | | /** |
83 | | * MicroProps is the first MicroPropsGenerator that should be should be called, |
84 | | * producing an initialized MicroProps instance that will be passed on and |
85 | | * modified throughout the rest of the chain of MicroPropsGenerator instances. |
86 | | */ |
87 | | struct MicroProps : public MicroPropsGenerator { |
88 | | SimpleMicroProps simple; |
89 | | |
90 | | // NOTE: All of these fields are properly initialized in NumberFormatterImpl. |
91 | | RoundingImpl rounder; |
92 | | Padder padding; |
93 | | IntegerWidth integerWidth; |
94 | | UNumberSignDisplay sign; |
95 | | char nsName[9]; |
96 | | |
97 | | // No ownership: must point at a string which will outlive MicroProps |
98 | | // instances, e.g. a string with static storage duration, or just a string |
99 | | // that will never be deallocated or modified. |
100 | | const char *gender; |
101 | | |
102 | | // Note: This struct has no direct ownership of the following pointers. |
103 | | |
104 | | // Pointers to Modifiers provided by the number formatting pipeline (when |
105 | | // the value is known): |
106 | | |
107 | | // A Modifier provided by LongNameHandler, used for currency long names and |
108 | | // units. If there is no LongNameHandler needed, this should be an |
109 | | // EmptyModifier. (This is typically the third modifier applied.) |
110 | | const Modifier* modOuter; |
111 | | // A Modifier for short currencies and compact notation. (This is typically |
112 | | // the second modifier applied.) |
113 | | const Modifier* modMiddle = nullptr; |
114 | | // A Modifier provided by ScientificHandler, used for scientific notation. |
115 | | // This is typically the first modifier applied. |
116 | | const Modifier* modInner; |
117 | | |
118 | | // The following "helper" fields may optionally be used during the MicroPropsGenerator. |
119 | | // They live here to retain memory. |
120 | | struct { |
121 | | // The ScientificModifier for which ScientificHandler is responsible. |
122 | | // ScientificHandler::processQuantity() modifies this Modifier. |
123 | | ScientificModifier scientificModifier; |
124 | | // EmptyModifier used for modOuter |
125 | | EmptyModifier emptyWeakModifier{false}; |
126 | | // EmptyModifier used for modInner |
127 | | EmptyModifier emptyStrongModifier{true}; |
128 | | MultiplierFormatHandler multiplier; |
129 | | // A Modifier used for Mixed Units. When formatting mixed units, |
130 | | // LongNameHandler assigns this Modifier. |
131 | | SimpleModifier mixedUnitModifier; |
132 | | } helpers; |
133 | | |
134 | | // The MeasureUnit with which the output is represented. May also have |
135 | | // UMEASURE_UNIT_MIXED complexity, in which case mixedMeasures comes into |
136 | | // play. |
137 | | MeasureUnit outputUnit; |
138 | | |
139 | | // Contains all the values of each unit in mixed units. For quantity (which is the floating value of |
140 | | // the smallest unit in the mixed unit), the value stores in `quantity`. |
141 | | // NOTE: the value of quantity in `mixedMeasures` will be left unset. |
142 | | IntMeasures mixedMeasures; |
143 | | |
144 | | // Points to quantity position, -1 if the position is not set yet. |
145 | | int32_t indexOfQuantity = -1; |
146 | | |
147 | | // Number of mixedMeasures that have been populated |
148 | | int32_t mixedMeasuresCount = 0; |
149 | | |
150 | 1.27M | MicroProps() = default; |
151 | | |
152 | | MicroProps(const MicroProps& other) = default; |
153 | | |
154 | 1.26M | MicroProps& operator=(const MicroProps& other) = default; |
155 | | |
156 | | /** |
157 | | * As MicroProps is the "base instance", this implementation of |
158 | | * MicroPropsGenerator::processQuantity() just ensures that the output |
159 | | * `micros` is correctly initialized. |
160 | | * |
161 | | * For the "safe" invocation of this function, micros must not be *this, |
162 | | * such that a copy of the base instance is made. For the "unsafe" path, |
163 | | * this function can be used only once, because the base MicroProps instance |
164 | | * will be modified and thus not be available for re-use. |
165 | | * |
166 | | * @param quantity The quantity for consideration and optional mutation. |
167 | | * @param micros The MicroProps instance to populate. If this parameter is |
168 | | * not already `*this`, it will be overwritten with a copy of `*this`. |
169 | | */ |
170 | | void processQuantity(DecimalQuantity &quantity, MicroProps µs, |
171 | 1.27M | UErrorCode &status) const override { |
172 | 1.27M | (void) quantity; |
173 | 1.27M | (void) status; |
174 | 1.27M | if (this == µs) { |
175 | | // Unsafe path: no need to perform a copy. |
176 | 11.0k | U_ASSERT(!exhausted); |
177 | 11.0k | micros.exhausted = true; |
178 | 11.0k | U_ASSERT(exhausted); |
179 | 1.26M | } else { |
180 | | // Safe path: copy self into the output micros. |
181 | 1.26M | U_ASSERT(!exhausted); |
182 | 1.26M | micros = *this; |
183 | 1.26M | } |
184 | 1.27M | } |
185 | | |
186 | | private: |
187 | | // Internal fields: |
188 | | bool exhausted = false; |
189 | | }; |
190 | | |
191 | | } // namespace number::impl |
192 | | U_NAMESPACE_END |
193 | | |
194 | | #endif // __NUMBER_MICROPROPS_H__ |
195 | | |
196 | | #endif /* #if !UCONFIG_NO_FORMATTING */ |