blob: 67f2316a9cd4bdfb72f2ee8a325167ebd78162d0 [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_LONGNAMES_H__
8#define __NUMBER_LONGNAMES_H__
9
Victor Changce4bf3c2021-01-19 16:34:24 +000010#include "cmemory.h"
11#include "unicode/listformatter.h"
Victor Chang73229502020-09-17 13:39:19 +010012#include "unicode/uversion.h"
13#include "number_utils.h"
14#include "number_modifiers.h"
15
16U_NAMESPACE_BEGIN namespace number {
17namespace impl {
18
19class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory {
20 public:
21 static UnicodeString getUnitDisplayName(
22 const Locale& loc,
23 const MeasureUnit& unit,
24 UNumberUnitWidth width,
25 UErrorCode& status);
26
27 static UnicodeString getUnitPattern(
28 const Locale& loc,
29 const MeasureUnit& unit,
30 UNumberUnitWidth width,
31 StandardPlural::Form pluralForm,
32 UErrorCode& status);
33
34 static LongNameHandler*
35 forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency, const PluralRules *rules,
36 const MicroPropsGenerator *parent, UErrorCode &status);
37
Victor Changce4bf3c2021-01-19 16:34:24 +000038 /**
39 * Construct a localized LongNameHandler for the specified MeasureUnit.
40 *
41 * Compound units can be constructed via `unit` and `perUnit`. Both of these
42 * must then be built-in units.
43 *
44 * Mixed units are not supported, use MixedUnitLongNameHandler::forMeasureUnit.
45 *
46 * This function uses a fillIn intead of returning a pointer, because we
47 * want to fill in instances in a MemoryPool (which cannot adopt pointers it
48 * didn't create itself).
49 *
50 * @param loc The desired locale.
51 * @param unit The measure unit to construct a LongNameHandler for. If
52 * `perUnit` is also defined, `unit` must not be a mixed unit.
53 * @param perUnit If `unit` is a mixed unit, `perUnit` must be "none".
54 * @param width Specifies the desired unit rendering.
55 * @param rules Does not take ownership.
56 * @param parent Does not take ownership.
57 * @param fillIn Required.
58 */
59 static void forMeasureUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
60 const UNumberUnitWidth &width, const PluralRules *rules,
61 const MicroPropsGenerator *parent, LongNameHandler *fillIn,
62 UErrorCode &status);
Victor Chang73229502020-09-17 13:39:19 +010063
Victor Changce4bf3c2021-01-19 16:34:24 +000064 /**
65 * Selects the plural-appropriate Modifier from the set of fModifiers based
66 * on the plural form.
67 */
Victor Chang73229502020-09-17 13:39:19 +010068 void
69 processQuantity(DecimalQuantity &quantity, MicroProps &micros, UErrorCode &status) const U_OVERRIDE;
70
Victor Changce4bf3c2021-01-19 16:34:24 +000071 // TODO(units): investigate whether we might run into Mixed Unit trouble
72 // with this. This override for ModifierStore::getModifier does not support
73 // mixed units: investigate under which circumstances it gets called (check
74 // both ImmutablePatternModifier and in NumberRangeFormatterImpl).
Victor Chang73229502020-09-17 13:39:19 +010075 const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE;
76
77 private:
Victor Changce4bf3c2021-01-19 16:34:24 +000078 // A set of pre-computed modifiers, one for each plural form.
Victor Chang73229502020-09-17 13:39:19 +010079 SimpleModifier fModifiers[StandardPlural::Form::COUNT];
Victor Changce4bf3c2021-01-19 16:34:24 +000080 // Not owned
Victor Chang73229502020-09-17 13:39:19 +010081 const PluralRules *rules;
Victor Changce4bf3c2021-01-19 16:34:24 +000082 // Not owned
Victor Chang73229502020-09-17 13:39:19 +010083 const MicroPropsGenerator *parent;
84
85 LongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent)
Victor Changce4bf3c2021-01-19 16:34:24 +000086 : rules(rules), parent(parent) {
87 }
Victor Chang73229502020-09-17 13:39:19 +010088
Victor Changce4bf3c2021-01-19 16:34:24 +000089 LongNameHandler() : rules(nullptr), parent(nullptr) {
90 }
Victor Chang73229502020-09-17 13:39:19 +010091
Victor Changce4bf3c2021-01-19 16:34:24 +000092 // Enables MemoryPool<LongNameHandler>::emplaceBack(): requires access to
93 // the private constructors.
94 friend class MemoryPool<LongNameHandler>;
95
96 // Allow macrosToMicroGenerator to call the private default constructor.
97 friend class NumberFormatterImpl;
98
99 // Fills in LongNameHandler fields for formatting compound units identified
100 // via `unit` and `perUnit`. Both `unit` and `perUnit` need to be built-in
101 // units (for which data exists).
102 static void forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
103 const UNumberUnitWidth &width, const PluralRules *rules,
104 const MicroPropsGenerator *parent, LongNameHandler *fillIn,
105 UErrorCode &status);
106
107 // Sets fModifiers to use the patterns from `simpleFormats`.
Victor Chang73229502020-09-17 13:39:19 +0100108 void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, UErrorCode &status);
Victor Changce4bf3c2021-01-19 16:34:24 +0000109
110 // Sets fModifiers to a combination of `leadFormats` (one per plural form)
111 // and `trailFormat` appended to each.
112 //
113 // With a leadFormat of "{0}m" and a trailFormat of "{0}/s", it produces a
114 // pattern of "{0}m/s" by inserting the leadFormat pattern into trailFormat.
Victor Chang73229502020-09-17 13:39:19 +0100115 void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
116 Field field, UErrorCode &status);
117};
118
Victor Changce4bf3c2021-01-19 16:34:24 +0000119// Similar to LongNameHandler, but only for MIXED units.
120class MixedUnitLongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory {
121 public:
122 /**
123 * Construct a localized MixedUnitLongNameHandler for the specified
124 * MeasureUnit. It must be a MIXED unit.
125 *
126 * This function uses a fillIn intead of returning a pointer, because we
127 * want to fill in instances in a MemoryPool (which cannot adopt pointers it
128 * didn't create itself).
129 *
130 * @param loc The desired locale.
131 * @param mixedUnit The mixed measure unit to construct a
132 * MixedUnitLongNameHandler for.
133 * @param width Specifies the desired unit rendering.
134 * @param rules Does not take ownership.
135 * @param parent Does not take ownership.
136 * @param fillIn Required.
137 */
138 static void forMeasureUnit(const Locale &loc, const MeasureUnit &mixedUnit,
139 const UNumberUnitWidth &width, const PluralRules *rules,
140 const MicroPropsGenerator *parent, MixedUnitLongNameHandler *fillIn,
141 UErrorCode &status);
142
143 /**
144 * Produces a plural-appropriate Modifier for a mixed unit: `quantity` is
145 * taken as the final smallest unit, while the larger unit values must be
146 * provided via `micros.mixedMeasures`.
147 */
148 void processQuantity(DecimalQuantity &quantity, MicroProps &micros,
149 UErrorCode &status) const U_OVERRIDE;
150
151 // Required for ModifierStore. And ModifierStore is required by
152 // SimpleModifier constructor's last parameter. We assert his will never get
153 // called though.
154 const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE;
155
156 private:
157 // Not owned
158 const PluralRules *rules;
159 // Not owned
160 const MicroPropsGenerator *parent;
161
162 // Total number of units in the MeasureUnit this handler was configured for:
163 // for "foot-and-inch", this will be 2.
164 int32_t fMixedUnitCount = 1;
165 // Stores unit data for each of the individual units. For each unit, it
166 // stores ARRAY_LENGTH strings, as returned by getMeasureData. (Each unit
167 // with index `i` has ARRAY_LENGTH strings starting at index
168 // `i*ARRAY_LENGTH` in this array.)
169 LocalArray<UnicodeString> fMixedUnitData;
170 // A localized NumberFormatter used to format the integer-valued bigger
171 // units of Mixed Unit measurements.
172 LocalizedNumberFormatter fIntegerFormatter;
173 // A localised list formatter for joining mixed units together.
174 LocalPointer<ListFormatter> fListFormatter;
175
176 MixedUnitLongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent)
177 : rules(rules), parent(parent) {
178 }
179
180 MixedUnitLongNameHandler() : rules(nullptr), parent(nullptr) {
181 }
182
183 // Allow macrosToMicroGenerator to call the private default constructor.
184 friend class NumberFormatterImpl;
185
186 // Enables MemoryPool<LongNameHandler>::emplaceBack(): requires access to
187 // the private constructors.
188 friend class MemoryPool<MixedUnitLongNameHandler>;
189
190 // For a mixed unit, returns a Modifier that takes only one parameter: the
191 // smallest and final unit of the set. The bigger units' values and labels
192 // get baked into this Modifier, together with the unit label of the final
193 // unit.
194 const Modifier *getMixedUnitModifier(DecimalQuantity &quantity, MicroProps &micros,
195 UErrorCode &status) const;
196};
197
198/**
199 * A MicroPropsGenerator that multiplexes between different LongNameHandlers,
200 * depending on the outputUnit.
201 *
202 * See processQuantity() for the input requirements.
203 */
204class LongNameMultiplexer : public MicroPropsGenerator, public UMemory {
205 public:
206 // Produces a multiplexer for LongNameHandlers, one for each unit in
207 // `units`. An individual unit might be a mixed unit.
208 static LongNameMultiplexer *forMeasureUnits(const Locale &loc,
209 const MaybeStackVector<MeasureUnit> &units,
210 const UNumberUnitWidth &width, const PluralRules *rules,
211 const MicroPropsGenerator *parent, UErrorCode &status);
212
213 // The output unit must be provided via `micros.outputUnit`, it must match
214 // one of the units provided to the factory function.
215 void processQuantity(DecimalQuantity &quantity, MicroProps &micros,
216 UErrorCode &status) const U_OVERRIDE;
217
218 private:
219 /**
220 * Because we only know which LongNameHandler we wish to call after calling
221 * earlier MicroPropsGenerators in the chain, LongNameMultiplexer keeps the
222 * parent link, while the LongNameHandlers are given no parents.
223 */
224 MemoryPool<LongNameHandler> fLongNameHandlers;
225 MemoryPool<MixedUnitLongNameHandler> fMixedUnitHandlers;
226 // Unowned pointers to instances owned by MaybeStackVectors.
227 MaybeStackArray<MicroPropsGenerator *, 8> fHandlers;
228 // Each MeasureUnit corresponds to the same-index MicroPropsGenerator
229 // pointed to in fHandlers.
230 LocalArray<MeasureUnit> fMeasureUnits;
231
232 const MicroPropsGenerator *fParent;
233
234 LongNameMultiplexer(const MicroPropsGenerator *parent) : fParent(parent) {
235 }
236};
237
Victor Chang73229502020-09-17 13:39:19 +0100238} // namespace impl
239} // namespace number
240U_NAMESPACE_END
241
242#endif //__NUMBER_LONGNAMES_H__
243
244#endif /* #if !UCONFIG_NO_FORMATTING */