1*0e209d39SAndroid Build Coastguard Worker // © 2017 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_PATTERNSTRING_H__ 8*0e209d39SAndroid Build Coastguard Worker #define __NUMBER_PATTERNSTRING_H__ 9*0e209d39SAndroid Build Coastguard Worker 10*0e209d39SAndroid Build Coastguard Worker 11*0e209d39SAndroid Build Coastguard Worker #include <cstdint> 12*0e209d39SAndroid Build Coastguard Worker #include "unicode/unum.h" 13*0e209d39SAndroid Build Coastguard Worker #include "unicode/unistr.h" 14*0e209d39SAndroid Build Coastguard Worker #include "number_types.h" 15*0e209d39SAndroid Build Coastguard Worker #include "number_decimalquantity.h" 16*0e209d39SAndroid Build Coastguard Worker #include "number_decimfmtprops.h" 17*0e209d39SAndroid Build Coastguard Worker #include "number_affixutils.h" 18*0e209d39SAndroid Build Coastguard Worker 19*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN 20*0e209d39SAndroid Build Coastguard Worker namespace number::impl { 21*0e209d39SAndroid Build Coastguard Worker 22*0e209d39SAndroid Build Coastguard Worker // Forward declaration 23*0e209d39SAndroid Build Coastguard Worker class PatternParser; 24*0e209d39SAndroid Build Coastguard Worker 25*0e209d39SAndroid Build Coastguard Worker // Note: the order of fields in this enum matters for parsing. 26*0e209d39SAndroid Build Coastguard Worker enum PatternSignType { 27*0e209d39SAndroid Build Coastguard Worker /** Render using normal positive subpattern rules */ 28*0e209d39SAndroid Build Coastguard Worker PATTERN_SIGN_TYPE_POS, 29*0e209d39SAndroid Build Coastguard Worker /** Render using rules to force the display of a plus sign */ 30*0e209d39SAndroid Build Coastguard Worker PATTERN_SIGN_TYPE_POS_SIGN, 31*0e209d39SAndroid Build Coastguard Worker /** Render using negative subpattern rules */ 32*0e209d39SAndroid Build Coastguard Worker PATTERN_SIGN_TYPE_NEG, 33*0e209d39SAndroid Build Coastguard Worker /** Count for looping over the possibilities */ 34*0e209d39SAndroid Build Coastguard Worker PATTERN_SIGN_TYPE_COUNT 35*0e209d39SAndroid Build Coastguard Worker }; 36*0e209d39SAndroid Build Coastguard Worker 37*0e209d39SAndroid Build Coastguard Worker // Exported as U_I18N_API because it is a public member field of exported ParsedSubpatternInfo 38*0e209d39SAndroid Build Coastguard Worker struct U_I18N_API Endpoints { 39*0e209d39SAndroid Build Coastguard Worker int32_t start = 0; 40*0e209d39SAndroid Build Coastguard Worker int32_t end = 0; 41*0e209d39SAndroid Build Coastguard Worker }; 42*0e209d39SAndroid Build Coastguard Worker 43*0e209d39SAndroid Build Coastguard Worker // Exported as U_I18N_API because it is a public member field of exported ParsedPatternInfo 44*0e209d39SAndroid Build Coastguard Worker struct U_I18N_API ParsedSubpatternInfo { 45*0e209d39SAndroid Build Coastguard Worker uint64_t groupingSizes = 0x0000ffffffff0000L; 46*0e209d39SAndroid Build Coastguard Worker int32_t integerLeadingHashSigns = 0; 47*0e209d39SAndroid Build Coastguard Worker int32_t integerTrailingHashSigns = 0; 48*0e209d39SAndroid Build Coastguard Worker int32_t integerNumerals = 0; 49*0e209d39SAndroid Build Coastguard Worker int32_t integerAtSigns = 0; 50*0e209d39SAndroid Build Coastguard Worker int32_t integerTotal = 0; // for convenience 51*0e209d39SAndroid Build Coastguard Worker int32_t fractionNumerals = 0; 52*0e209d39SAndroid Build Coastguard Worker int32_t fractionHashSigns = 0; 53*0e209d39SAndroid Build Coastguard Worker int32_t fractionTotal = 0; // for convenience 54*0e209d39SAndroid Build Coastguard Worker bool hasDecimal = false; 55*0e209d39SAndroid Build Coastguard Worker int32_t widthExceptAffixes = 0; 56*0e209d39SAndroid Build Coastguard Worker // Note: NullableValue causes issues here with std::move. 57*0e209d39SAndroid Build Coastguard Worker bool hasPadding = false; 58*0e209d39SAndroid Build Coastguard Worker UNumberFormatPadPosition paddingLocation = UNUM_PAD_BEFORE_PREFIX; 59*0e209d39SAndroid Build Coastguard Worker DecimalQuantity rounding; 60*0e209d39SAndroid Build Coastguard Worker bool exponentHasPlusSign = false; 61*0e209d39SAndroid Build Coastguard Worker int32_t exponentZeros = 0; 62*0e209d39SAndroid Build Coastguard Worker bool hasPercentSign = false; 63*0e209d39SAndroid Build Coastguard Worker bool hasPerMilleSign = false; 64*0e209d39SAndroid Build Coastguard Worker bool hasCurrencySign = false; 65*0e209d39SAndroid Build Coastguard Worker bool hasCurrencyDecimal = false; 66*0e209d39SAndroid Build Coastguard Worker bool hasMinusSign = false; 67*0e209d39SAndroid Build Coastguard Worker bool hasPlusSign = false; 68*0e209d39SAndroid Build Coastguard Worker 69*0e209d39SAndroid Build Coastguard Worker Endpoints prefixEndpoints; 70*0e209d39SAndroid Build Coastguard Worker Endpoints suffixEndpoints; 71*0e209d39SAndroid Build Coastguard Worker Endpoints paddingEndpoints; 72*0e209d39SAndroid Build Coastguard Worker }; 73*0e209d39SAndroid Build Coastguard Worker 74*0e209d39SAndroid Build Coastguard Worker // Exported as U_I18N_API because it is needed for the unit test PatternStringTest 75*0e209d39SAndroid Build Coastguard Worker struct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemory { 76*0e209d39SAndroid Build Coastguard Worker UnicodeString pattern; 77*0e209d39SAndroid Build Coastguard Worker ParsedSubpatternInfo positive; 78*0e209d39SAndroid Build Coastguard Worker ParsedSubpatternInfo negative; 79*0e209d39SAndroid Build Coastguard Worker ParsedPatternInfoParsedPatternInfo80*0e209d39SAndroid Build Coastguard Worker ParsedPatternInfo() 81*0e209d39SAndroid Build Coastguard Worker : state(this->pattern), currentSubpattern(nullptr) {} 82*0e209d39SAndroid Build Coastguard Worker 83*0e209d39SAndroid Build Coastguard Worker ~ParsedPatternInfo() override = default; 84*0e209d39SAndroid Build Coastguard Worker 85*0e209d39SAndroid Build Coastguard Worker // Need to declare this explicitly because of the destructor 86*0e209d39SAndroid Build Coastguard Worker ParsedPatternInfo& operator=(ParsedPatternInfo&& src) noexcept = default; 87*0e209d39SAndroid Build Coastguard Worker 88*0e209d39SAndroid Build Coastguard Worker static int32_t getLengthFromEndpoints(const Endpoints& endpoints); 89*0e209d39SAndroid Build Coastguard Worker 90*0e209d39SAndroid Build Coastguard Worker char16_t charAt(int32_t flags, int32_t index) const override; 91*0e209d39SAndroid Build Coastguard Worker 92*0e209d39SAndroid Build Coastguard Worker int32_t length(int32_t flags) const override; 93*0e209d39SAndroid Build Coastguard Worker 94*0e209d39SAndroid Build Coastguard Worker UnicodeString getString(int32_t flags) const override; 95*0e209d39SAndroid Build Coastguard Worker 96*0e209d39SAndroid Build Coastguard Worker bool positiveHasPlusSign() const override; 97*0e209d39SAndroid Build Coastguard Worker 98*0e209d39SAndroid Build Coastguard Worker bool hasNegativeSubpattern() const override; 99*0e209d39SAndroid Build Coastguard Worker 100*0e209d39SAndroid Build Coastguard Worker bool negativeHasMinusSign() const override; 101*0e209d39SAndroid Build Coastguard Worker 102*0e209d39SAndroid Build Coastguard Worker bool hasCurrencySign() const override; 103*0e209d39SAndroid Build Coastguard Worker 104*0e209d39SAndroid Build Coastguard Worker bool containsSymbolType(AffixPatternType type, UErrorCode& status) const override; 105*0e209d39SAndroid Build Coastguard Worker 106*0e209d39SAndroid Build Coastguard Worker bool hasBody() const override; 107*0e209d39SAndroid Build Coastguard Worker 108*0e209d39SAndroid Build Coastguard Worker bool currencyAsDecimal() const override; 109*0e209d39SAndroid Build Coastguard Worker 110*0e209d39SAndroid Build Coastguard Worker private: 111*0e209d39SAndroid Build Coastguard Worker struct U_I18N_API ParserState { 112*0e209d39SAndroid Build Coastguard Worker const UnicodeString& pattern; // reference to the parent 113*0e209d39SAndroid Build Coastguard Worker int32_t offset = 0; 114*0e209d39SAndroid Build Coastguard Worker ParserStateParsedPatternInfo::ParserState115*0e209d39SAndroid Build Coastguard Worker explicit ParserState(const UnicodeString& _pattern) 116*0e209d39SAndroid Build Coastguard Worker : pattern(_pattern) {} 117*0e209d39SAndroid Build Coastguard Worker 118*0e209d39SAndroid Build Coastguard Worker ParserState& operator=(ParserState&& src) noexcept { 119*0e209d39SAndroid Build Coastguard Worker // Leave pattern reference alone; it will continue to point to the same place in memory, 120*0e209d39SAndroid Build Coastguard Worker // which gets overwritten by ParsedPatternInfo's implicit move assignment. 121*0e209d39SAndroid Build Coastguard Worker offset = src.offset; 122*0e209d39SAndroid Build Coastguard Worker return *this; 123*0e209d39SAndroid Build Coastguard Worker } 124*0e209d39SAndroid Build Coastguard Worker 125*0e209d39SAndroid Build Coastguard Worker /** Returns the next code point, or -1 if string is too short. */ 126*0e209d39SAndroid Build Coastguard Worker UChar32 peek(); 127*0e209d39SAndroid Build Coastguard Worker 128*0e209d39SAndroid Build Coastguard Worker /** Returns the code point after the next code point, or -1 if string is too short. */ 129*0e209d39SAndroid Build Coastguard Worker UChar32 peek2(); 130*0e209d39SAndroid Build Coastguard Worker 131*0e209d39SAndroid Build Coastguard Worker /** Returns the next code point and then steps forward. */ 132*0e209d39SAndroid Build Coastguard Worker UChar32 next(); 133*0e209d39SAndroid Build Coastguard Worker 134*0e209d39SAndroid Build Coastguard Worker // TODO: We don't currently do anything with the message string. 135*0e209d39SAndroid Build Coastguard Worker // This method is here as a shell for Java compatibility. toParseExceptionParsedPatternInfo::ParserState136*0e209d39SAndroid Build Coastguard Worker inline void toParseException(const char16_t* message) { (void) message; } 137*0e209d39SAndroid Build Coastguard Worker } state; 138*0e209d39SAndroid Build Coastguard Worker 139*0e209d39SAndroid Build Coastguard Worker // NOTE: In Java, these are written as pure functions. 140*0e209d39SAndroid Build Coastguard Worker // In C++, they're written as methods. 141*0e209d39SAndroid Build Coastguard Worker // The behavior is the same. 142*0e209d39SAndroid Build Coastguard Worker 143*0e209d39SAndroid Build Coastguard Worker // Mutable transient pointer: 144*0e209d39SAndroid Build Coastguard Worker ParsedSubpatternInfo* currentSubpattern; 145*0e209d39SAndroid Build Coastguard Worker 146*0e209d39SAndroid Build Coastguard Worker // In Java, "negative == null" tells us whether or not we had a negative subpattern. 147*0e209d39SAndroid Build Coastguard Worker // In C++, we need to remember in another boolean. 148*0e209d39SAndroid Build Coastguard Worker bool fHasNegativeSubpattern = false; 149*0e209d39SAndroid Build Coastguard Worker 150*0e209d39SAndroid Build Coastguard Worker const Endpoints& getEndpoints(int32_t flags) const; 151*0e209d39SAndroid Build Coastguard Worker 152*0e209d39SAndroid Build Coastguard Worker /** Run the recursive descent parser. */ 153*0e209d39SAndroid Build Coastguard Worker void consumePattern(const UnicodeString& patternString, UErrorCode& status); 154*0e209d39SAndroid Build Coastguard Worker 155*0e209d39SAndroid Build Coastguard Worker void consumeSubpattern(UErrorCode& status); 156*0e209d39SAndroid Build Coastguard Worker 157*0e209d39SAndroid Build Coastguard Worker void consumePadding(PadPosition paddingLocation, UErrorCode& status); 158*0e209d39SAndroid Build Coastguard Worker 159*0e209d39SAndroid Build Coastguard Worker void consumeAffix(Endpoints& endpoints, UErrorCode& status); 160*0e209d39SAndroid Build Coastguard Worker 161*0e209d39SAndroid Build Coastguard Worker void consumeLiteral(UErrorCode& status); 162*0e209d39SAndroid Build Coastguard Worker 163*0e209d39SAndroid Build Coastguard Worker void consumeFormat(UErrorCode& status); 164*0e209d39SAndroid Build Coastguard Worker 165*0e209d39SAndroid Build Coastguard Worker void consumeIntegerFormat(UErrorCode& status); 166*0e209d39SAndroid Build Coastguard Worker 167*0e209d39SAndroid Build Coastguard Worker void consumeFractionFormat(UErrorCode& status); 168*0e209d39SAndroid Build Coastguard Worker 169*0e209d39SAndroid Build Coastguard Worker void consumeExponent(UErrorCode& status); 170*0e209d39SAndroid Build Coastguard Worker 171*0e209d39SAndroid Build Coastguard Worker friend class PatternParser; 172*0e209d39SAndroid Build Coastguard Worker }; 173*0e209d39SAndroid Build Coastguard Worker 174*0e209d39SAndroid Build Coastguard Worker enum IgnoreRounding { 175*0e209d39SAndroid Build Coastguard Worker IGNORE_ROUNDING_NEVER = 0, IGNORE_ROUNDING_IF_CURRENCY = 1, IGNORE_ROUNDING_ALWAYS = 2 176*0e209d39SAndroid Build Coastguard Worker }; 177*0e209d39SAndroid Build Coastguard Worker 178*0e209d39SAndroid Build Coastguard Worker class U_I18N_API PatternParser { 179*0e209d39SAndroid Build Coastguard Worker public: 180*0e209d39SAndroid Build Coastguard Worker /** 181*0e209d39SAndroid Build Coastguard Worker * Runs the recursive descent parser on the given pattern string, returning a data structure with raw information 182*0e209d39SAndroid Build Coastguard Worker * about the pattern string. 183*0e209d39SAndroid Build Coastguard Worker * 184*0e209d39SAndroid Build Coastguard Worker * <p> 185*0e209d39SAndroid Build Coastguard Worker * To obtain a more useful form of the data, consider using {@link #parseToProperties} instead. 186*0e209d39SAndroid Build Coastguard Worker * 187*0e209d39SAndroid Build Coastguard Worker * TODO: Change argument type to const char16_t* instead of UnicodeString? 188*0e209d39SAndroid Build Coastguard Worker * 189*0e209d39SAndroid Build Coastguard Worker * @param patternString 190*0e209d39SAndroid Build Coastguard Worker * The LDML decimal format pattern (Excel-style pattern) to parse. 191*0e209d39SAndroid Build Coastguard Worker * @return The results of the parse. 192*0e209d39SAndroid Build Coastguard Worker */ 193*0e209d39SAndroid Build Coastguard Worker static void parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo& patternInfo, 194*0e209d39SAndroid Build Coastguard Worker UErrorCode& status); 195*0e209d39SAndroid Build Coastguard Worker 196*0e209d39SAndroid Build Coastguard Worker /** 197*0e209d39SAndroid Build Coastguard Worker * Parses a pattern string into a new property bag. 198*0e209d39SAndroid Build Coastguard Worker * 199*0e209d39SAndroid Build Coastguard Worker * @param pattern 200*0e209d39SAndroid Build Coastguard Worker * The pattern string, like "#,##0.00" 201*0e209d39SAndroid Build Coastguard Worker * @param ignoreRounding 202*0e209d39SAndroid Build Coastguard Worker * Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the 203*0e209d39SAndroid Build Coastguard Worker * pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used 204*0e209d39SAndroid Build Coastguard Worker * instead. 205*0e209d39SAndroid Build Coastguard Worker * @return A property bag object. 206*0e209d39SAndroid Build Coastguard Worker * @throws IllegalArgumentException 207*0e209d39SAndroid Build Coastguard Worker * If there is a syntax error in the pattern string. 208*0e209d39SAndroid Build Coastguard Worker */ 209*0e209d39SAndroid Build Coastguard Worker static DecimalFormatProperties parseToProperties(const UnicodeString& pattern, 210*0e209d39SAndroid Build Coastguard Worker IgnoreRounding ignoreRounding, UErrorCode& status); 211*0e209d39SAndroid Build Coastguard Worker 212*0e209d39SAndroid Build Coastguard Worker static DecimalFormatProperties parseToProperties(const UnicodeString& pattern, UErrorCode& status); 213*0e209d39SAndroid Build Coastguard Worker 214*0e209d39SAndroid Build Coastguard Worker /** 215*0e209d39SAndroid Build Coastguard Worker * Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string 216*0e209d39SAndroid Build Coastguard Worker * will be overwritten with either their default value or with the value coming from the pattern string. Properties 217*0e209d39SAndroid Build Coastguard Worker * that cannot be encoded into a pattern string, such as rounding mode, are not modified. 218*0e209d39SAndroid Build Coastguard Worker * 219*0e209d39SAndroid Build Coastguard Worker * @param pattern 220*0e209d39SAndroid Build Coastguard Worker * The pattern string, like "#,##0.00" 221*0e209d39SAndroid Build Coastguard Worker * @param properties 222*0e209d39SAndroid Build Coastguard Worker * The property bag object to overwrite. 223*0e209d39SAndroid Build Coastguard Worker * @param ignoreRounding 224*0e209d39SAndroid Build Coastguard Worker * See {@link #parseToProperties(String pattern, int ignoreRounding)}. 225*0e209d39SAndroid Build Coastguard Worker * @throws IllegalArgumentException 226*0e209d39SAndroid Build Coastguard Worker * If there was a syntax error in the pattern string. 227*0e209d39SAndroid Build Coastguard Worker */ 228*0e209d39SAndroid Build Coastguard Worker static void parseToExistingProperties(const UnicodeString& pattern, 229*0e209d39SAndroid Build Coastguard Worker DecimalFormatProperties& properties, 230*0e209d39SAndroid Build Coastguard Worker IgnoreRounding ignoreRounding, UErrorCode& status); 231*0e209d39SAndroid Build Coastguard Worker 232*0e209d39SAndroid Build Coastguard Worker private: 233*0e209d39SAndroid Build Coastguard Worker static void parseToExistingPropertiesImpl(const UnicodeString& pattern, 234*0e209d39SAndroid Build Coastguard Worker DecimalFormatProperties& properties, 235*0e209d39SAndroid Build Coastguard Worker IgnoreRounding ignoreRounding, UErrorCode& status); 236*0e209d39SAndroid Build Coastguard Worker 237*0e209d39SAndroid Build Coastguard Worker /** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */ 238*0e209d39SAndroid Build Coastguard Worker static void patternInfoToProperties(DecimalFormatProperties& properties, 239*0e209d39SAndroid Build Coastguard Worker ParsedPatternInfo& patternInfo, IgnoreRounding _ignoreRounding, 240*0e209d39SAndroid Build Coastguard Worker UErrorCode& status); 241*0e209d39SAndroid Build Coastguard Worker }; 242*0e209d39SAndroid Build Coastguard Worker 243*0e209d39SAndroid Build Coastguard Worker class U_I18N_API PatternStringUtils { 244*0e209d39SAndroid Build Coastguard Worker public: 245*0e209d39SAndroid Build Coastguard Worker /** 246*0e209d39SAndroid Build Coastguard Worker * Determine whether a given roundingIncrement should be ignored for formatting 247*0e209d39SAndroid Build Coastguard Worker * based on the current maxFrac value (maximum fraction digits). For example a 248*0e209d39SAndroid Build Coastguard Worker * roundingIncrement of 0.01 should be ignored if maxFrac is 1, but not if maxFrac 249*0e209d39SAndroid Build Coastguard Worker * is 2 or more. Note that roundingIncrements are rounded up in significance, so 250*0e209d39SAndroid Build Coastguard Worker * a roundingIncrement of 0.006 is treated like 0.01 for this determination, i.e. 251*0e209d39SAndroid Build Coastguard Worker * it should not be ignored if maxFrac is 2 or more (but a roundingIncrement of 252*0e209d39SAndroid Build Coastguard Worker * 0.005 is treated like 0.001 for significance). 253*0e209d39SAndroid Build Coastguard Worker * 254*0e209d39SAndroid Build Coastguard Worker * This test is needed for both NumberPropertyMapper::oldToNew and 255*0e209d39SAndroid Build Coastguard Worker * PatternStringUtils::propertiesToPatternString. In Java it cannot be 256*0e209d39SAndroid Build Coastguard Worker * exported by NumberPropertyMapper (package private) so it is in 257*0e209d39SAndroid Build Coastguard Worker * PatternStringUtils, do the same in C. 258*0e209d39SAndroid Build Coastguard Worker * 259*0e209d39SAndroid Build Coastguard Worker * @param roundIncr 260*0e209d39SAndroid Build Coastguard Worker * The roundingIncrement to be checked. Must be non-zero. 261*0e209d39SAndroid Build Coastguard Worker * @param maxFrac 262*0e209d39SAndroid Build Coastguard Worker * The current maximum fraction digits value. 263*0e209d39SAndroid Build Coastguard Worker * @return true if roundIncr should be ignored for formatting. 264*0e209d39SAndroid Build Coastguard Worker */ 265*0e209d39SAndroid Build Coastguard Worker static bool ignoreRoundingIncrement(double roundIncr, int32_t maxFrac); 266*0e209d39SAndroid Build Coastguard Worker 267*0e209d39SAndroid Build Coastguard Worker /** 268*0e209d39SAndroid Build Coastguard Worker * Creates a pattern string from a property bag. 269*0e209d39SAndroid Build Coastguard Worker * 270*0e209d39SAndroid Build Coastguard Worker * <p> 271*0e209d39SAndroid Build Coastguard Worker * Since pattern strings support only a subset of the functionality available in a property bag, a new property bag 272*0e209d39SAndroid Build Coastguard Worker * created from the string returned by this function may not be the same as the original property bag. 273*0e209d39SAndroid Build Coastguard Worker * 274*0e209d39SAndroid Build Coastguard Worker * @param properties 275*0e209d39SAndroid Build Coastguard Worker * The property bag to serialize. 276*0e209d39SAndroid Build Coastguard Worker * @return A pattern string approximately serializing the property bag. 277*0e209d39SAndroid Build Coastguard Worker */ 278*0e209d39SAndroid Build Coastguard Worker static UnicodeString propertiesToPatternString(const DecimalFormatProperties& properties, 279*0e209d39SAndroid Build Coastguard Worker UErrorCode& status); 280*0e209d39SAndroid Build Coastguard Worker 281*0e209d39SAndroid Build Coastguard Worker 282*0e209d39SAndroid Build Coastguard Worker /** 283*0e209d39SAndroid Build Coastguard Worker * Converts a pattern between standard notation and localized notation. Localized notation means that instead of 284*0e209d39SAndroid Build Coastguard Worker * using generic placeholders in the pattern, you use the corresponding locale-specific characters instead. For 285*0e209d39SAndroid Build Coastguard Worker * example, in locale <em>fr-FR</em>, the period in the pattern "0.000" means "decimal" in standard notation (as it 286*0e209d39SAndroid Build Coastguard Worker * does in every other locale), but it means "grouping" in localized notation. 287*0e209d39SAndroid Build Coastguard Worker * 288*0e209d39SAndroid Build Coastguard Worker * <p> 289*0e209d39SAndroid Build Coastguard Worker * A greedy string-substitution strategy is used to substitute locale symbols. If two symbols are ambiguous or have 290*0e209d39SAndroid Build Coastguard Worker * the same prefix, the result is not well-defined. 291*0e209d39SAndroid Build Coastguard Worker * 292*0e209d39SAndroid Build Coastguard Worker * <p> 293*0e209d39SAndroid Build Coastguard Worker * Locale symbols are not allowed to contain the ASCII quote character. 294*0e209d39SAndroid Build Coastguard Worker * 295*0e209d39SAndroid Build Coastguard Worker * <p> 296*0e209d39SAndroid Build Coastguard Worker * This method is provided for backwards compatibility and should not be used in any new code. 297*0e209d39SAndroid Build Coastguard Worker * 298*0e209d39SAndroid Build Coastguard Worker * TODO(C++): This method is not yet implemented. 299*0e209d39SAndroid Build Coastguard Worker * 300*0e209d39SAndroid Build Coastguard Worker * @param input 301*0e209d39SAndroid Build Coastguard Worker * The pattern to convert. 302*0e209d39SAndroid Build Coastguard Worker * @param symbols 303*0e209d39SAndroid Build Coastguard Worker * The symbols corresponding to the localized pattern. 304*0e209d39SAndroid Build Coastguard Worker * @param toLocalized 305*0e209d39SAndroid Build Coastguard Worker * true to convert from standard to localized notation; false to convert from localized to standard 306*0e209d39SAndroid Build Coastguard Worker * notation. 307*0e209d39SAndroid Build Coastguard Worker * @return The pattern expressed in the other notation. 308*0e209d39SAndroid Build Coastguard Worker */ 309*0e209d39SAndroid Build Coastguard Worker static UnicodeString convertLocalized(const UnicodeString& input, const DecimalFormatSymbols& symbols, 310*0e209d39SAndroid Build Coastguard Worker bool toLocalized, UErrorCode& status); 311*0e209d39SAndroid Build Coastguard Worker 312*0e209d39SAndroid Build Coastguard Worker /** 313*0e209d39SAndroid Build Coastguard Worker * This method contains the heart of the logic for rendering LDML affix strings. It handles 314*0e209d39SAndroid Build Coastguard Worker * sign-always-shown resolution, whether to use the positive or negative subpattern, permille 315*0e209d39SAndroid Build Coastguard Worker * substitution, and plural forms for CurrencyPluralInfo. 316*0e209d39SAndroid Build Coastguard Worker */ 317*0e209d39SAndroid Build Coastguard Worker static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, 318*0e209d39SAndroid Build Coastguard Worker PatternSignType patternSignType, 319*0e209d39SAndroid Build Coastguard Worker bool approximately, 320*0e209d39SAndroid Build Coastguard Worker StandardPlural::Form plural, 321*0e209d39SAndroid Build Coastguard Worker bool perMilleReplacesPercent, 322*0e209d39SAndroid Build Coastguard Worker bool dropCurrencySymbols, 323*0e209d39SAndroid Build Coastguard Worker UnicodeString& output); 324*0e209d39SAndroid Build Coastguard Worker 325*0e209d39SAndroid Build Coastguard Worker static PatternSignType resolveSignDisplay(UNumberSignDisplay signDisplay, Signum signum); 326*0e209d39SAndroid Build Coastguard Worker 327*0e209d39SAndroid Build Coastguard Worker private: 328*0e209d39SAndroid Build Coastguard Worker /** @return The number of chars inserted. */ 329*0e209d39SAndroid Build Coastguard Worker static int escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex, 330*0e209d39SAndroid Build Coastguard Worker UErrorCode& status); 331*0e209d39SAndroid Build Coastguard Worker }; 332*0e209d39SAndroid Build Coastguard Worker 333*0e209d39SAndroid Build Coastguard Worker } // namespace number::impl 334*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END 335*0e209d39SAndroid Build Coastguard Worker 336*0e209d39SAndroid Build Coastguard Worker 337*0e209d39SAndroid Build Coastguard Worker #endif //__NUMBER_PATTERNSTRING_H__ 338*0e209d39SAndroid Build Coastguard Worker 339*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */ 340