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