1ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// © 2017 and later: Unicode, Inc. and others.
2ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
4ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "unicode/utypes.h"
5ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
6ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT
7ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#ifndef __NUMBER_PATTERNSTRING_H__
8ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#define __NUMBER_PATTERNSTRING_H__
9ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
10ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
11ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include <cstdint>
12ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "unicode/unum.h"
13ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "unicode/unistr.h"
14ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "number_types.h"
15ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "number_decimalquantity.h"
16ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "number_decimfmtprops.h"
17ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#include "number_affixutils.h"
18ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
19ffdc27edd5503111189fc11165c5a11289a71f79Fredrik RoubertU_NAMESPACE_BEGIN namespace number {
20ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertnamespace impl {
21ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
22ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// Forward declaration
23ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertclass PatternParser;
24ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
25ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// Exported as U_I18N_API because it is a public member field of exported ParsedSubpatternInfo
26ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertstruct U_I18N_API Endpoints {
27ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t start = 0;
28ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t end = 0;
29ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert};
30ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
31ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// Exported as U_I18N_API because it is a public member field of exported ParsedPatternInfo
32ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertstruct U_I18N_API ParsedSubpatternInfo {
33ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int64_t groupingSizes = 0x0000ffffffff0000L;
34ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t integerLeadingHashSigns = 0;
35ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t integerTrailingHashSigns = 0;
36ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t integerNumerals = 0;
37ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t integerAtSigns = 0;
38ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t integerTotal = 0; // for convenience
39ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t fractionNumerals = 0;
40ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t fractionHashSigns = 0;
41ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t fractionTotal = 0; // for convenience
42ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasDecimal = false;
43ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t widthExceptAffixes = 0;
44ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    NullableValue<UNumberFormatPadPosition> paddingLocation;
45ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    DecimalQuantity rounding;
46ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool exponentHasPlusSign = false;
47ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t exponentZeros = 0;
48ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasPercentSign = false;
49ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasPerMilleSign = false;
50ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasCurrencySign = false;
51ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasMinusSign = false;
52ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasPlusSign = false;
53ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
54ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    Endpoints prefixEndpoints;
55ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    Endpoints suffixEndpoints;
56ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    Endpoints paddingEndpoints;
57ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert};
58ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
59ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert// Exported as U_I18N_API because it is needed for the unit test PatternStringTest
60ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertstruct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemory {
61ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    UnicodeString pattern;
62ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    ParsedSubpatternInfo positive;
63ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    ParsedSubpatternInfo negative;
64ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
65ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    ParsedPatternInfo() : state(this->pattern), currentSubpattern(nullptr) {}
66ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
67ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    ~ParsedPatternInfo() U_OVERRIDE = default;
68ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
69ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static int32_t getLengthFromEndpoints(const Endpoints &endpoints);
70ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
71ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    char16_t charAt(int32_t flags, int32_t index) const U_OVERRIDE;
72ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
73ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t length(int32_t flags) const U_OVERRIDE;
74ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
75ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    UnicodeString getString(int32_t flags) const;
76ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
77ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool positiveHasPlusSign() const U_OVERRIDE;
78ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
79ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasNegativeSubpattern() const U_OVERRIDE;
80ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
81ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool negativeHasMinusSign() const U_OVERRIDE;
82ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
83ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool hasCurrencySign() const U_OVERRIDE;
84ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
85ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool containsSymbolType(AffixPatternType type, UErrorCode &status) const U_OVERRIDE;
86ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
87ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  private:
88ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    struct U_I18N_API ParserState {
89ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        const UnicodeString &pattern; // reference to the parent
90ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        int32_t offset = 0;
91ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
92ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        explicit ParserState(const UnicodeString &_pattern) : pattern(_pattern) {};
93ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
94ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        UChar32 peek();
95ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
96ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        UChar32 next();
97ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
98ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        // TODO: We don't currently do anything with the message string.
99ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        // This method is here as a shell for Java compatibility.
100ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        inline void toParseException(const char16_t *message) { (void)message; }
101ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
102ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    state;
103ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
104ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    // NOTE: In Java, these are written as pure functions.
105ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    // In C++, they're written as methods.
106ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    // The behavior is the same.
107ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
108ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    // Mutable transient pointer:
109ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    ParsedSubpatternInfo *currentSubpattern;
110ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
111ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    // In Java, "negative == null" tells us whether or not we had a negative subpattern.
112ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    // In C++, we need to remember in another boolean.
113ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    bool fHasNegativeSubpattern = false;
114ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
115ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    const Endpoints &getEndpoints(int32_t flags) const;
116ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
117ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /** Run the recursive descent parser. */
118ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumePattern(const UnicodeString &patternString, UErrorCode &status);
119ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
120ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeSubpattern(UErrorCode &status);
121ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
122ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumePadding(PadPosition paddingLocation, UErrorCode &status);
123ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
124ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeAffix(Endpoints &endpoints, UErrorCode &status);
125ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
126ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeLiteral(UErrorCode &status);
127ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
128ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeFormat(UErrorCode &status);
129ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
130ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeIntegerFormat(UErrorCode &status);
131ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
132ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeFractionFormat(UErrorCode &status);
133ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
134ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    void consumeExponent(UErrorCode &status);
135ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
136ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    friend class PatternParser;
137ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert};
138ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
139ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertclass U_I18N_API PatternParser {
140ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  public:
141ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /**
142ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Runs the recursive descent parser on the given pattern string, returning a data structure with raw information
143ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * about the pattern string.
144ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
145ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * <p>
146ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * To obtain a more useful form of the data, consider using {@link #parseToProperties} instead.
147ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
148ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * TODO: Change argument type to const char16_t* instead of UnicodeString?
149ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
150ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param patternString
151ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The LDML decimal format pattern (Excel-style pattern) to parse.
152ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @return The results of the parse.
153ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     */
154ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static void
155ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo &patternInfo, UErrorCode &status);
156ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
157ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    enum IgnoreRounding {
158ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        IGNORE_ROUNDING_NEVER = 0, IGNORE_ROUNDING_IF_CURRENCY = 1, IGNORE_ROUNDING_ALWAYS = 2
159ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    };
160ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
161ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /**
162ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Parses a pattern string into a new property bag.
163ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
164ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param pattern
165ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The pattern string, like "#,##0.00"
166ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param ignoreRounding
167ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the
168ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used
169ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            instead.
170ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @return A property bag object.
171ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @throws IllegalArgumentException
172ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *             If there is a syntax error in the pattern string.
173ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     */
174ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static DecimalFormatProperties
175ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    parseToProperties(const UnicodeString& pattern, IgnoreRounding ignoreRounding, UErrorCode &status);
176ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
177ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /**
178ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string
179ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * will be overwritten with either their default value or with the value coming from the pattern string. Properties
180ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * that cannot be encoded into a pattern string, such as rounding mode, are not modified.
181ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
182ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param pattern
183ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The pattern string, like "#,##0.00"
184ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param properties
185ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The property bag object to overwrite.
186ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param ignoreRounding
187ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            See {@link #parseToProperties(String pattern, int ignoreRounding)}.
188ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @throws IllegalArgumentException
189ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *             If there was a syntax error in the pattern string.
190ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     */
191ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static void parseToExistingProperties(const UnicodeString& pattern, DecimalFormatProperties& properties,
192ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                                          IgnoreRounding ignoreRounding, UErrorCode &status);
193ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
194ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  private:
195ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static void
196ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    parseToExistingPropertiesImpl(const UnicodeString& pattern, DecimalFormatProperties &properties,
197ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                                  IgnoreRounding ignoreRounding, UErrorCode &status);
198ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
199ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */
200ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static void
201ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    patternInfoToProperties(DecimalFormatProperties &properties, ParsedPatternInfo& patternInfo,
202ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                            IgnoreRounding _ignoreRounding, UErrorCode &status);
203ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert};
204ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
205ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertclass U_I18N_API PatternStringUtils {
206ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  public:
207ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /**
208ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Creates a pattern string from a property bag.
209ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
210ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * <p>
211ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Since pattern strings support only a subset of the functionality available in a property bag, a new property bag
212ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * created from the string returned by this function may not be the same as the original property bag.
213ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
214ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param properties
215ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The property bag to serialize.
216ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @return A pattern string approximately serializing the property bag.
217ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     */
218ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static UnicodeString
219ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    propertiesToPatternString(const DecimalFormatProperties &properties, UErrorCode &status);
220ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
221ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
222ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /**
223ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Converts a pattern between standard notation and localized notation. Localized notation means that instead of
224ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * using generic placeholders in the pattern, you use the corresponding locale-specific characters instead. For
225ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * example, in locale <em>fr-FR</em>, the period in the pattern "0.000" means "decimal" in standard notation (as it
226ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * does in every other locale), but it means "grouping" in localized notation.
227ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
228ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * <p>
229ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * A greedy string-substitution strategy is used to substitute locale symbols. If two symbols are ambiguous or have
230ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * the same prefix, the result is not well-defined.
231ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
232ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * <p>
233ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * Locale symbols are not allowed to contain the ASCII quote character.
234ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
235ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * <p>
236ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * This method is provided for backwards compatibility and should not be used in any new code.
237ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
238ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * TODO(C++): This method is not yet implemented.
239ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *
240ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param input
241ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The pattern to convert.
242ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param symbols
243ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            The symbols corresponding to the localized pattern.
244ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @param toLocalized
245ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            true to convert from standard to localized notation; false to convert from localized to standard
246ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     *            notation.
247ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     * @return The pattern expressed in the other notation.
248ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert     */
249ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static UnicodeString
250ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    convertLocalized(UnicodeString input, DecimalFormatSymbols symbols, bool toLocalized,
251ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                     UErrorCode &status);
252ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
253ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  private:
254ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    /** @return The number of chars inserted. */
255ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    static int
256ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    escapePaddingString(UnicodeString input, UnicodeString &output, int startIndex, UErrorCode &status);
257ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert};
258ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
259ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert} // namespace impl
260ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert} // namespace number
261ffdc27edd5503111189fc11165c5a11289a71f79Fredrik RoubertU_NAMESPACE_END
262ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
263ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
264ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#endif //__NUMBER_PATTERNSTRING_H__
265ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
266ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert#endif /* #if !UCONFIG_NO_FORMATTING */
267