blob: 5cd549e54a363ffb9a3871aa1cd6694af732794f [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_FORMATIMPL_H__
8#define __NUMBER_FORMATIMPL_H__
9
10#include "number_types.h"
11#include "formatted_string_builder.h"
12#include "number_patternstring.h"
Victor Changce4bf3c2021-01-19 16:34:24 +000013#include "number_usageprefs.h"
Victor Chang73229502020-09-17 13:39:19 +010014#include "number_utils.h"
15#include "number_patternmodifier.h"
16#include "number_longnames.h"
17#include "number_compact.h"
18#include "number_microprops.h"
Victor Changce4bf3c2021-01-19 16:34:24 +000019#include "number_utypes.h"
Victor Chang73229502020-09-17 13:39:19 +010020
21U_NAMESPACE_BEGIN namespace number {
22namespace impl {
23
24/**
25 * This is the "brain" of the number formatting pipeline. It ties all the pieces together, taking in a MacroProps and a
26 * DecimalQuantity and outputting a properly formatted number string.
27 */
28class NumberFormatterImpl : public UMemory {
29 public:
30 /**
31 * Builds a "safe" MicroPropsGenerator, which is thread-safe and can be used repeatedly.
32 * The caller owns the returned NumberFormatterImpl.
33 */
34 NumberFormatterImpl(const MacroProps &macros, UErrorCode &status);
35
36 /**
37 * Builds and evaluates an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once.
38 */
Victor Changce4bf3c2021-01-19 16:34:24 +000039 static int32_t formatStatic(const MacroProps &macros, UFormattedNumberData *results,
40 UErrorCode &status);
Victor Chang73229502020-09-17 13:39:19 +010041
42 /**
43 * Prints only the prefix and suffix; used for DecimalFormat getters.
44 *
45 * @return The index into the output at which the prefix ends and the suffix starts; in other words,
46 * the prefix length.
47 */
48 static int32_t getPrefixSuffixStatic(const MacroProps& macros, Signum signum,
49 StandardPlural::Form plural, FormattedStringBuilder& outString,
50 UErrorCode& status);
51
52 /**
53 * Evaluates the "safe" MicroPropsGenerator created by "fromMacros".
54 */
Victor Changce4bf3c2021-01-19 16:34:24 +000055 int32_t format(UFormattedNumberData *results, UErrorCode &status) const;
Victor Chang73229502020-09-17 13:39:19 +010056
57 /**
58 * Like format(), but saves the result into an output MicroProps without additional processing.
59 */
60 void preProcess(DecimalQuantity& inValue, MicroProps& microsOut, UErrorCode& status) const;
61
62 /**
63 * Like getPrefixSuffixStatic() but uses the safe compiled object.
64 */
65 int32_t getPrefixSuffix(Signum signum, StandardPlural::Form plural, FormattedStringBuilder& outString,
66 UErrorCode& status) const;
67
68 const MicroProps& getRawMicroProps() const {
69 return fMicros;
70 }
71
72 /**
73 * Synthesizes the output string from a MicroProps and DecimalQuantity.
74 * This method formats only the main number, not affixes.
75 */
76 static int32_t writeNumber(const MicroProps& micros, DecimalQuantity& quantity,
77 FormattedStringBuilder& string, int32_t index, UErrorCode& status);
78
79 /**
80 * Adds the affixes. Intended to be called immediately after formatNumber.
81 */
82 static int32_t writeAffixes(const MicroProps& micros, FormattedStringBuilder& string, int32_t start,
83 int32_t end, UErrorCode& status);
84
85 private:
Victor Changce4bf3c2021-01-19 16:34:24 +000086 // Head of the MicroPropsGenerator linked list. Subclasses' processQuantity
87 // methods process this list in a parent-first order, such that the last
88 // item added, which this points to, typically has its logic executed last.
Victor Chang73229502020-09-17 13:39:19 +010089 const MicroPropsGenerator *fMicroPropsGenerator = nullptr;
90
91 // Tail of the list:
92 MicroProps fMicros;
93
94 // Other fields possibly used by the number formatting pipeline:
95 // TODO: Convert more of these LocalPointers to value objects to reduce the number of news?
Victor Changce4bf3c2021-01-19 16:34:24 +000096 LocalPointer<const UsagePrefsHandler> fUsagePrefsHandler;
97 LocalPointer<const UnitConversionHandler> fUnitConversionHandler;
Victor Chang73229502020-09-17 13:39:19 +010098 LocalPointer<const DecimalFormatSymbols> fSymbols;
99 LocalPointer<const PluralRules> fRules;
100 LocalPointer<const ParsedPatternInfo> fPatternInfo;
101 LocalPointer<const ScientificHandler> fScientificHandler;
102 LocalPointer<MutablePatternModifier> fPatternModifier;
Victor Changd8aa9d52021-01-05 23:49:57 +0000103 LocalPointer<ImmutablePatternModifier> fImmutablePatternModifier;
Victor Changce4bf3c2021-01-19 16:34:24 +0000104 LocalPointer<LongNameHandler> fLongNameHandler;
105 // TODO: use a common base class that enables fLongNameHandler,
106 // fLongNameMultiplexer, and fMixedUnitLongNameHandler to be merged into one
107 // member?
108 LocalPointer<MixedUnitLongNameHandler> fMixedUnitLongNameHandler;
109 LocalPointer<const LongNameMultiplexer> fLongNameMultiplexer;
Victor Chang73229502020-09-17 13:39:19 +0100110 LocalPointer<const CompactHandler> fCompactHandler;
111
112 // Value objects possibly used by the number formatting pipeline:
113 struct Warehouse {
114 CurrencySymbols fCurrencySymbols;
115 } fWarehouse;
116
117
118 NumberFormatterImpl(const MacroProps &macros, bool safe, UErrorCode &status);
119
120 MicroProps& preProcessUnsafe(DecimalQuantity &inValue, UErrorCode &status);
121
122 int32_t getPrefixSuffixUnsafe(Signum signum, StandardPlural::Form plural,
123 FormattedStringBuilder& outString, UErrorCode& status);
124
125 /**
126 * If rulesPtr is non-null, return it. Otherwise, return a PluralRules owned by this object for the
127 * specified locale, creating it if necessary.
128 */
129 const PluralRules *
130 resolvePluralRules(const PluralRules *rulesPtr, const Locale &locale, UErrorCode &status);
131
132 /**
133 * Synthesizes the MacroProps into a MicroPropsGenerator. All information, including the locale, is encoded into the
134 * MicroPropsGenerator, except for the quantity itself, which is left abstract and must be provided to the returned
135 * MicroPropsGenerator instance.
136 *
137 * @see MicroPropsGenerator
138 * @param macros
139 * The {@link MacroProps} to consume. This method does not mutate the MacroProps instance.
140 * @param safe
141 * If true, the returned MicroPropsGenerator will be thread-safe. If false, the returned value will
142 * <em>not</em> be thread-safe, intended for a single "one-shot" use only. Building the thread-safe
143 * object is more expensive.
144 */
145 const MicroPropsGenerator *
146 macrosToMicroGenerator(const MacroProps &macros, bool safe, UErrorCode &status);
147
148 static int32_t
149 writeIntegerDigits(const MicroProps &micros, DecimalQuantity &quantity, FormattedStringBuilder &string,
150 int32_t index, UErrorCode &status);
151
152 static int32_t
153 writeFractionDigits(const MicroProps &micros, DecimalQuantity &quantity, FormattedStringBuilder &string,
154 int32_t index, UErrorCode &status);
155};
156
157} // namespace impl
158} // namespace number
159U_NAMESPACE_END
160
161
162#endif //__NUMBER_FORMATIMPL_H__
163
164#endif /* #if !UCONFIG_NO_FORMATTING */