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