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