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