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