xref: /aosp_15_r20/external/cronet/third_party/icu/source/i18n/number_mapper.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // © 2018 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_MAPPER_H__
8 #define __NUMBER_MAPPER_H__
9 
10 #include <atomic>
11 #include "number_types.h"
12 #include "unicode/currpinf.h"
13 #include "standardplural.h"
14 #include "number_patternstring.h"
15 #include "number_currencysymbols.h"
16 #include "numparse_impl.h"
17 
18 U_NAMESPACE_BEGIN
19 namespace number {
20 namespace impl {
21 
22 
23 class AutoAffixPatternProvider;
24 class CurrencyPluralInfoAffixProvider;
25 
26 
27 class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory {
28   public:
isBogus()29     bool isBogus() const {
30         return fBogus;
31     }
32 
setToBogus()33     void setToBogus() {
34         fBogus = true;
35     }
36 
37     void setTo(const DecimalFormatProperties& properties, UErrorCode& status);
38 
39     // AffixPatternProvider Methods:
40 
41     char16_t charAt(int32_t flags, int32_t i) const override;
42 
43     int32_t length(int32_t flags) const override;
44 
45     UnicodeString getString(int32_t flags) const override;
46 
47     bool hasCurrencySign() const override;
48 
49     bool positiveHasPlusSign() const override;
50 
51     bool hasNegativeSubpattern() const override;
52 
53     bool negativeHasMinusSign() const override;
54 
55     bool containsSymbolType(AffixPatternType, UErrorCode&) const override;
56 
57     bool hasBody() const override;
58 
59     bool currencyAsDecimal() const override;
60 
61   private:
62     UnicodeString posPrefix;
63     UnicodeString posSuffix;
64     UnicodeString negPrefix;
65     UnicodeString negSuffix;
66     bool isCurrencyPattern;
67     bool fCurrencyAsDecimal;
68 
69     PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state
70 
71     const UnicodeString& getStringInternal(int32_t flags) const;
72 
73     bool fBogus{true};
74 
75     friend class AutoAffixPatternProvider;
76     friend class CurrencyPluralInfoAffixProvider;
77 };
78 
79 
80 class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMemory {
81   public:
isBogus()82     bool isBogus() const {
83         return fBogus;
84     }
85 
setToBogus()86     void setToBogus() {
87         fBogus = true;
88     }
89 
90     void setTo(const CurrencyPluralInfo& cpi, const DecimalFormatProperties& properties,
91                UErrorCode& status);
92 
93     // AffixPatternProvider Methods:
94 
95     char16_t charAt(int32_t flags, int32_t i) const override;
96 
97     int32_t length(int32_t flags) const override;
98 
99     UnicodeString getString(int32_t flags) const override;
100 
101     bool hasCurrencySign() const override;
102 
103     bool positiveHasPlusSign() const override;
104 
105     bool hasNegativeSubpattern() const override;
106 
107     bool negativeHasMinusSign() const override;
108 
109     bool containsSymbolType(AffixPatternType, UErrorCode&) const override;
110 
111     bool hasBody() const override;
112 
113     bool currencyAsDecimal() const override;
114 
115   private:
116     PropertiesAffixPatternProvider affixesByPlural[StandardPlural::COUNT];
117 
118     CurrencyPluralInfoAffixProvider() = default;
119 
120     bool fBogus{true};
121 
122     friend class AutoAffixPatternProvider;
123 };
124 
125 
126 class AutoAffixPatternProvider {
127   public:
128     inline AutoAffixPatternProvider() = default;
129 
AutoAffixPatternProvider(const DecimalFormatProperties & properties,UErrorCode & status)130     inline AutoAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) {
131         setTo(properties, status);
132     }
133 
setTo(const DecimalFormatProperties & properties,UErrorCode & status)134     inline void setTo(const DecimalFormatProperties& properties, UErrorCode& status) {
135         if (properties.currencyPluralInfo.fPtr.isNull()) {
136             propertiesAPP.setTo(properties, status);
137             currencyPluralInfoAPP.setToBogus();
138         } else {
139             propertiesAPP.setToBogus();
140             currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status);
141         }
142     }
143 
setTo(const AffixPatternProvider * provider,UErrorCode & status)144     inline void setTo(const AffixPatternProvider* provider, UErrorCode& status) {
145         if (auto ptr = dynamic_cast<const PropertiesAffixPatternProvider*>(provider)) {
146             propertiesAPP = *ptr;
147         } else if (auto ptr = dynamic_cast<const CurrencyPluralInfoAffixProvider*>(provider)) {
148             currencyPluralInfoAPP = *ptr;
149         } else {
150             status = U_INTERNAL_PROGRAM_ERROR;
151         }
152     }
153 
get()154     inline const AffixPatternProvider& get() const {
155       if (!currencyPluralInfoAPP.isBogus()) {
156         return currencyPluralInfoAPP;
157       } else {
158         return propertiesAPP;
159       }
160     }
161 
162   private:
163     PropertiesAffixPatternProvider propertiesAPP;
164     CurrencyPluralInfoAffixProvider currencyPluralInfoAPP;
165 };
166 
167 
168 /**
169  * A struct for ownership of a few objects needed for formatting.
170  */
171 struct DecimalFormatWarehouse : public UMemory {
172     AutoAffixPatternProvider affixProvider;
173     LocalPointer<PluralRules> rules;
174 };
175 
176 
177 /**
178 * Internal fields for DecimalFormat.
179 * TODO: Make some of these fields by value instead of by LocalPointer?
180 */
181 struct DecimalFormatFields : public UMemory {
182 
DecimalFormatFieldsDecimalFormatFields183     DecimalFormatFields() {}
184 
DecimalFormatFieldsDecimalFormatFields185     DecimalFormatFields(const DecimalFormatProperties& propsToCopy)
186         : properties(propsToCopy) {}
187 
188     /** The property bag corresponding to user-specified settings and settings from the pattern string. */
189     DecimalFormatProperties properties;
190 
191     /** The symbols for the current locale. */
192     LocalPointer<const DecimalFormatSymbols> symbols;
193 
194     /**
195     * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
196     * #format} method uses the formatter directly without needing to synchronize.
197     */
198     LocalizedNumberFormatter formatter;
199 
200     /** The lazy-computed parser for .parse() */
201     std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {};
202 
203     /** The lazy-computed parser for .parseCurrency() */
204     std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicCurrencyParser = {};
205 
206     /** Small object ownership warehouse for the formatter and parser */
207     DecimalFormatWarehouse warehouse;
208 
209     /** The effective properties as exported from the formatter object. Used by some getters. */
210     DecimalFormatProperties exportedProperties;
211 
212     // Data for fastpath
213     bool canUseFastFormat = false;
214     struct FastFormatData {
215         char16_t cpZero;
216         char16_t cpGroupingSeparator;
217         char16_t cpMinusSign;
218         int8_t minInt;
219         int8_t maxInt;
220     } fastData;
221 };
222 
223 
224 /**
225  * Utilities for converting between a DecimalFormatProperties and a MacroProps.
226  */
227 class NumberPropertyMapper {
228   public:
229     /** Convenience method to create a NumberFormatter directly from Properties. */
230     static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
231                                              const DecimalFormatSymbols& symbols,
232                                              DecimalFormatWarehouse& warehouse, UErrorCode& status);
233 
234     /** Convenience method to create a NumberFormatter directly from Properties. */
235     static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
236                                              const DecimalFormatSymbols& symbols,
237                                              DecimalFormatWarehouse& warehouse,
238                                              DecimalFormatProperties& exportedProperties,
239                                              UErrorCode& status);
240 
241     /**
242      * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties}
243      * object. In other words, maps Properties to MacroProps. This function is used by the
244      * JDK-compatibility API to call into the ICU 60 fluent number formatting pipeline.
245      *
246      * @param properties
247      *            The property bag to be mapped.
248      * @param symbols
249      *            The symbols associated with the property bag.
250      * @param exportedProperties
251      *            A property bag in which to store validated properties. Used by some DecimalFormat
252      *            getters.
253      * @return A new MacroProps containing all of the information in the Properties.
254      */
255     static MacroProps oldToNew(const DecimalFormatProperties& properties,
256                                const DecimalFormatSymbols& symbols, DecimalFormatWarehouse& warehouse,
257                                DecimalFormatProperties* exportedProperties, UErrorCode& status);
258 };
259 
260 
261 } // namespace impl
262 } // namespace numparse
263 U_NAMESPACE_END
264 
265 #endif //__NUMBER_MAPPER_H__
266 #endif /* #if !UCONFIG_NO_FORMATTING */
267