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