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