blob: 9ecd776b3b4795512159c3e60c3b2c32cbb81c50 [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
Victor Changce4bf3c2021-01-19 16:34:24 +0000139 inline void setTo(const AffixPatternProvider* provider, UErrorCode& status) {
140 if (auto ptr = dynamic_cast<const PropertiesAffixPatternProvider*>(provider)) {
141 propertiesAPP = *ptr;
142 } else if (auto ptr = dynamic_cast<const CurrencyPluralInfoAffixProvider*>(provider)) {
143 currencyPluralInfoAPP = *ptr;
144 } else {
145 status = U_INTERNAL_PROGRAM_ERROR;
146 }
147 }
148
Victor Changd8aa9d52021-01-05 23:49:57 +0000149 inline const AffixPatternProvider& get() const {
150 if (!currencyPluralInfoAPP.isBogus()) {
151 return currencyPluralInfoAPP;
152 } else {
153 return propertiesAPP;
154 }
155 }
156
157 private:
158 PropertiesAffixPatternProvider propertiesAPP;
159 CurrencyPluralInfoAffixProvider currencyPluralInfoAPP;
Victor Chang73229502020-09-17 13:39:19 +0100160};
161
162
163/**
164 * A struct for ownership of a few objects needed for formatting.
165 */
Victor Changce4bf3c2021-01-19 16:34:24 +0000166struct DecimalFormatWarehouse : public UMemory {
Victor Changd8aa9d52021-01-05 23:49:57 +0000167 AutoAffixPatternProvider affixProvider;
Victor Changce4bf3c2021-01-19 16:34:24 +0000168 LocalPointer<PluralRules> rules;
Victor Chang73229502020-09-17 13:39:19 +0100169};
170
171
172/**
173* Internal fields for DecimalFormat.
174* TODO: Make some of these fields by value instead of by LocalPointer?
175*/
176struct DecimalFormatFields : public UMemory {
177
178 DecimalFormatFields() {}
179
180 DecimalFormatFields(const DecimalFormatProperties& propsToCopy)
181 : properties(propsToCopy) {}
182
183 /** The property bag corresponding to user-specified settings and settings from the pattern string. */
184 DecimalFormatProperties properties;
185
186 /** The symbols for the current locale. */
187 LocalPointer<const DecimalFormatSymbols> symbols;
188
189 /**
190 * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
191 * #format} method uses the formatter directly without needing to synchronize.
192 */
193 LocalizedNumberFormatter formatter;
194
195 /** The lazy-computed parser for .parse() */
196 std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {};
197
198 /** The lazy-computed parser for .parseCurrency() */
199 std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicCurrencyParser = {};
200
201 /** Small object ownership warehouse for the formatter and parser */
202 DecimalFormatWarehouse warehouse;
203
204 /** The effective properties as exported from the formatter object. Used by some getters. */
205 DecimalFormatProperties exportedProperties;
206
207 // Data for fastpath
208 bool canUseFastFormat = false;
209 struct FastFormatData {
210 char16_t cpZero;
211 char16_t cpGroupingSeparator;
212 char16_t cpMinusSign;
213 int8_t minInt;
214 int8_t maxInt;
215 } fastData;
216};
217
218
219/**
220 * Utilities for converting between a DecimalFormatProperties and a MacroProps.
221 */
222class NumberPropertyMapper {
223 public:
224 /** Convenience method to create a NumberFormatter directly from Properties. */
225 static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
226 const DecimalFormatSymbols& symbols,
227 DecimalFormatWarehouse& warehouse, UErrorCode& status);
228
229 /** Convenience method to create a NumberFormatter directly from Properties. */
230 static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties,
231 const DecimalFormatSymbols& symbols,
232 DecimalFormatWarehouse& warehouse,
233 DecimalFormatProperties& exportedProperties,
234 UErrorCode& status);
235
236 /**
237 * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties}
238 * object. In other words, maps Properties to MacroProps. This function is used by the
239 * JDK-compatibility API to call into the ICU 60 fluent number formatting pipeline.
240 *
241 * @param properties
242 * The property bag to be mapped.
243 * @param symbols
244 * The symbols associated with the property bag.
245 * @param exportedProperties
246 * A property bag in which to store validated properties. Used by some DecimalFormat
247 * getters.
248 * @return A new MacroProps containing all of the information in the Properties.
249 */
250 static MacroProps oldToNew(const DecimalFormatProperties& properties,
251 const DecimalFormatSymbols& symbols, DecimalFormatWarehouse& warehouse,
252 DecimalFormatProperties* exportedProperties, UErrorCode& status);
253};
254
255
256} // namespace impl
257} // namespace numparse
258U_NAMESPACE_END
259
260#endif //__NUMBER_MAPPER_H__
261#endif /* #if !UCONFIG_NO_FORMATTING */