1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/*
2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*******************************************************************************
3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 1997-2014, International Business Machines Corporation and    *
4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* others. All Rights Reserved.                                                *
5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*******************************************************************************
6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/
7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uassert.h"
9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "decimalformatpattern.h"
10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_FORMATTING
12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/dcfmtsym.h"
14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/format.h"
15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utf16.h"
16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifdef FMT_DEBUG
18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#else
20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define debug(x)
21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternZeroDigit            ((UChar)0x0030) /*'0'*/
24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternSignificantDigit     ((UChar)0x0040) /*'@'*/
25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternGroupingSeparator    ((UChar)0x002C) /*','*/
26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternDecimalSeparator     ((UChar)0x002E) /*'.'*/
27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternPerMill              ((UChar)0x2030)
28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternPercent              ((UChar)0x0025) /*'%'*/
29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternDigit                ((UChar)0x0023) /*'#'*/
30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternSeparator            ((UChar)0x003B) /*';'*/
31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternExponent             ((UChar)0x0045) /*'E'*/
32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternPlus                 ((UChar)0x002B) /*'+'*/
33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternMinus                ((UChar)0x002D) /*'-'*/
34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kPatternPadEscape            ((UChar)0x002A) /*'*'*/
35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kQuote                       ((UChar)0x0027) /*'\''*/
36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kCurrencySign                ((UChar)0x00A4)
38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define kDefaultPad                  ((UChar)0x0020) /* */
39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN
41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// TODO: Travis Keep: Copied from numfmt.cpp
43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t kDoubleIntegerDigits  = 309;
44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t kDoubleFractionDigits = 340;
45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// TODO: Travis Keep: Copied from numfmt.cpp
48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t gDefaultMaxIntegerDigits = 2000000000;
49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// TODO: Travis Keep: This function was copied from format.cpp
51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic void syntaxError(const UnicodeString& pattern,
52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                         int32_t pos,
53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                         UParseError& parseError) {
54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    parseError.offset = pos;
55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    parseError.line=0;  // we are not using line number
56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // for pre-context
58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t start = (pos < U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN-1
59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                                                             /* subtract 1 so that we have room for null*/));
60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t stop  = pos;
61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    pattern.extract(start,stop-start,parseError.preContext,0);
62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    //null terminate the buffer
63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    parseError.preContext[stop-start] = 0;
64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    //for post-context
66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    start = pos+1;
67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    stop  = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+(U_PARSE_CONTEXT_LEN-1)) :
68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        pattern.length();
69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    pattern.extract(start,stop-start,parseError.postContext,0);
70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    //null terminate the buffer
71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    parseError.postContext[stop-start]= 0;
72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusDecimalFormatPattern::DecimalFormatPattern()
75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        : fMinimumIntegerDigits(1),
76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMaximumIntegerDigits(gDefaultMaxIntegerDigits),
77fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMinimumFractionDigits(0),
78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMaximumFractionDigits(3),
79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fUseSignificantDigits(FALSE),
80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMinimumSignificantDigits(1),
81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMaximumSignificantDigits(6),
82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fUseExponentialNotation(FALSE),
83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMinExponentDigits(0),
84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fExponentSignAlwaysShown(FALSE),
85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fCurrencySignCount(fgCurrencySignCountZero),
86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fGroupingUsed(TRUE),
87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fGroupingSize(0),
88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fGroupingSize2(0),
89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fMultiplier(1),
90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fDecimalSeparatorAlwaysShown(FALSE),
91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fFormatWidth(0),
92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fRoundingIncrementUsed(FALSE),
93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fRoundingIncrement(),
94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fPad(kPatternPadEscape),
95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fNegPatternsBogus(TRUE),
96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fPosPatternsBogus(TRUE),
97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fNegPrefixPattern(),
98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fNegSuffixPattern(),
99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fPosPrefixPattern(),
100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fPosSuffixPattern(),
101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius          fPadPosition(DecimalFormatPattern::kPadBeforePrefix) {
102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusDecimalFormatPatternParser::DecimalFormatPatternParser() :
106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fZeroDigit(kPatternZeroDigit),
107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fSigDigit(kPatternSignificantDigit),
108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fGroupingSeparator((UChar)kPatternGroupingSeparator),
109fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fDecimalSeparator((UChar)kPatternDecimalSeparator),
110fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPercent((UChar)kPatternPercent),
111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPerMill((UChar)kPatternPerMill),
112fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fDigit((UChar)kPatternDigit),
113fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fSeparator((UChar)kPatternSeparator),
114fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fExponent((UChar)kPatternExponent),
115fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPlus((UChar)kPatternPlus),
116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fMinus((UChar)kPatternMinus),
117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPadEscape((UChar)kPatternPadEscape) {
118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid DecimalFormatPatternParser::useSymbols(
121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const DecimalFormatSymbols& symbols) {
122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fZeroDigit = symbols.getConstSymbol(
123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fSigDigit = symbols.getConstSymbol(
125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fGroupingSeparator = symbols.getConstSymbol(
127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kGroupingSeparatorSymbol);
128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fDecimalSeparator = symbols.getConstSymbol(
129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kDecimalSeparatorSymbol);
130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPercent = symbols.getConstSymbol(
131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kPercentSymbol);
132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPerMill = symbols.getConstSymbol(
133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kPerMillSymbol);
134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fDigit = symbols.getConstSymbol(
135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kDigitSymbol);
136fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fSeparator = symbols.getConstSymbol(
137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kPatternSeparatorSymbol);
138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fExponent = symbols.getConstSymbol(
139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kExponentialSymbol);
140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPlus = symbols.getConstSymbol(
141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kPlusSignSymbol);
142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fMinus = symbols.getConstSymbol(
143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kMinusSignSymbol);
144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fPadEscape = symbols.getConstSymbol(
145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            DecimalFormatSymbols::kPadEscapeSymbol);
146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusDecimalFormatPatternParser::applyPatternWithoutExpandAffix(
150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const UnicodeString& pattern,
151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        DecimalFormatPattern& out,
152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UParseError& parseError,
153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UErrorCode& status) {
154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_FAILURE(status))
155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    {
156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return;
157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    out = DecimalFormatPattern();
159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Clear error struct
161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    parseError.offset = -1;
162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // TODO: Travis Keep: This won't always work.
165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UChar nineDigit = (UChar)(fZeroDigit + 9);
166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t digitLen = fDigit.length();
167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t groupSepLen = fGroupingSeparator.length();
168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t decimalSepLen = fDecimalSeparator.length();
169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t pos = 0;
171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    int32_t patLen = pattern.length();
172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // Part 0 is the positive pattern.  Part 1, if present, is the negative
173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // pattern.
174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    for (int32_t part=0; part<2 && pos<patLen; ++part) {
175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // 2=suffix, 3=prefix in quote, 4=suffix in quote.  Subpart 0 is
177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // between the prefix and suffix, and consists of pattern
178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // characters.  In the prefix and suffix, percent, perMill, and
179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // currency symbols are recognized and translated.
180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // It's important that we don't change any fields of this object
183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // prematurely.  We set the following variables for the multiplier,
184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // grouping, etc., and then only change the actual object fields if
185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // everything parses correctly.  This also lets us register
186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // the data from part 0 and ignore the part 1, except for the
187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // prefix and suffix.
188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UnicodeString prefix;
189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UnicodeString suffix;
190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t decimalPos = -1;
191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t multiplier = 1;
192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int8_t groupingCount = -1;
194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int8_t groupingCount2 = -1;
195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t padPos = -1;
196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar32 padChar = 0;
197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t roundingPos = -1;
198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        DigitList roundingInc;
199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int8_t expDigits = -1;
200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UBool expSignAlways = FALSE;
201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // The affix is either the prefix or the suffix.
203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UnicodeString* affix = &prefix;
204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t start = pos;
206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UBool isPartDone = FALSE;
207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar32 ch;
208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        for (; !isPartDone && pos < patLen; ) {
210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Todo: account for surrogate pairs
211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            ch = pattern.char32At(pos);
212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            switch (subpart) {
213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case 0: // Pattern proper subpart (between prefix & suffix)
214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // Process the digits, decimal, and grouping characters.  We
215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // record five pieces of information.  We expect the digits
216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // to occur in the pattern ####00.00####, and we record the
217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // number of left digits, zero (central) digits, and right
218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // digits.  The position of the last grouping character is
219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // recorded (should be somewhere within the first two blocks
220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // of characters), as is the position of the decimal point,
221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // if any (should be in the zero digits).  If there is no
222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // decimal point, then there should be no right digits.
223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if (pattern.compare(pos, digitLen, fDigit) == 0) {
224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (zeroDigitCount > 0 || sigDigitCount > 0) {
225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++digitRightCount;
226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++digitLeftCount;
228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (groupingCount >= 0 && decimalPos < 0) {
230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++groupingCount;
231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += digitLen;
233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if ((ch >= fZeroDigit && ch <= nineDigit) ||
234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                           ch == fSigDigit) {
235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (digitRightCount > 0) {
236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Unexpected '0'
237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Unexpected '0'")
238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_UNEXPECTED_TOKEN;
239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (ch == fSigDigit) {
243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++sigDigitCount;
244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if (ch != fZeroDigit && roundingPos < 0) {
246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            roundingPos = digitLeftCount + zeroDigitCount;
247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if (roundingPos >= 0) {
249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            roundingInc.append((char)(ch - fZeroDigit + '0'));
250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++zeroDigitCount;
252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (groupingCount >= 0 && decimalPos < 0) {
254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++groupingCount;
255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += U16_LENGTH(ch);
257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, groupSepLen, fGroupingSeparator) == 0) {
258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (decimalPos >= 0) {
259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Grouping separator after decimal
260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Grouping separator after decimal")
261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_UNEXPECTED_TOKEN;
262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    groupingCount2 = groupingCount;
266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    groupingCount = 0;
267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += groupSepLen;
268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, decimalSepLen, fDecimalSeparator) == 0) {
269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (decimalPos >= 0) {
270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Multiple decimal separators
271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Multiple decimal separators")
272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_MULTIPLE_DECIMAL_SEPARATORS;
273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Intentionally incorporate the digitRightCount,
277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // even though it is illegal for this to be > 0
278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // at this point.  We check pattern syntax below.
279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += decimalSepLen;
281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else {
282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (pattern.compare(pos, fExponent.length(), fExponent) == 0) {
283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if (expDigits >= 0) {
284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            // Multiple exponential symbols
285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            debug("Multiple exponential symbols")
286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            status = U_MULTIPLE_EXPONENTIAL_SYMBOLS;
287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            syntaxError(pattern,pos,parseError);
288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            return;
289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if (groupingCount >= 0) {
291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            // Grouping separator in exponential pattern
292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            debug("Grouping separator in exponential pattern")
293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            status = U_MALFORMED_EXPONENTIAL_PATTERN;
294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            syntaxError(pattern,pos,parseError);
295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            return;
296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        pos += fExponent.length();
298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Check for positive prefix
299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if (pos < patLen
300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            && pattern.compare(pos, fPlus.length(), fPlus) == 0) {
301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            expSignAlways = TRUE;
302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            pos += fPlus.length();
303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Use lookahead to parse out the exponential part of the
305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // pattern, then jump into suffix subpart.
306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        expDigits = 0;
307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        while (pos < patLen &&
308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                               pattern.char32At(pos) == fZeroDigit) {
309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            ++expDigits;
310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            pos += U16_LENGTH(fZeroDigit);
311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // 1. Require at least one mantissa pattern digit
314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // 2. Disallow "#+ @" in mantissa
315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // 3. Require at least one exponent pattern digit
316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if (((digitLeftCount + zeroDigitCount) < 1 &&
317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                             (sigDigitCount + digitRightCount) < 1) ||
318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            (sigDigitCount > 0 && digitLeftCount > 0) ||
319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            expDigits < 1) {
320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            // Malformed exponential pattern
321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            debug("Malformed exponential pattern")
322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            status = U_MALFORMED_EXPONENTIAL_PATTERN;
323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            syntaxError(pattern,pos,parseError);
324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            return;
325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Transition to suffix subpart
328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    subpart = 2; // suffix subpart
329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix = &suffix;
330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    sub0Limit = pos;
331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    continue;
332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                break;
334fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case 1: // Prefix subpart
335fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case 2: // Suffix subpart
336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // Process the prefix / suffix characters
337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // Process unquoted characters seen in prefix or suffix
338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // subpart.
339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
340fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // Several syntax characters implicitly begins the
341fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // next subpart if we are in the prefix; otherwise
342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // they are illegal if unquoted.
343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if (!pattern.compare(pos, digitLen, fDigit) ||
344fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    !pattern.compare(pos, groupSepLen, fGroupingSeparator) ||
345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    !pattern.compare(pos, decimalSepLen, fDecimalSeparator) ||
346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    (ch >= fZeroDigit && ch <= nineDigit) ||
347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    ch == fSigDigit) {
348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (subpart == 1) { // prefix subpart
349fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        subpart = 0; // pattern proper subpart
350fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        sub0Start = pos; // Reprocess this character
351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        continue;
352fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
353fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_UNQUOTED_SPECIAL;
354fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
355fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
356fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
357fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (ch == kCurrencySign) {
358fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kQuote); // Encode currency
359fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Use lookahead to determine if the currency sign is
360fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // doubled or not.
361fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    U_ASSERT(U16_LENGTH(kCurrencySign) == 1);
362fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) {
363fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        affix->append(kCurrencySign);
364fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        ++pos; // Skip over the doubled character
365fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        if ((pos+1) < pattern.length() &&
366fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            pattern[pos+1] == kCurrencySign) {
367fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            affix->append(kCurrencySign);
368fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            ++pos; // Skip over the doubled character
369fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            out.fCurrencySignCount = fgCurrencySignCountInPluralFormat;
370fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        } else {
371fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                            out.fCurrencySignCount = fgCurrencySignCountInISOFormat;
372fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        }
373fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
374fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        out.fCurrencySignCount = fgCurrencySignCountInSymbolFormat;
375fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
376fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Fall through to append(ch)
377fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (ch == kQuote) {
378fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // A quote outside quotes indicates either the opening
379fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // quote or two quotes, which is a quote literal.  That is,
380fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // we have the first quote in 'do' or o''clock.
381fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    U_ASSERT(U16_LENGTH(kQuote) == 1);
382fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    ++pos;
383fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (pos < pattern.length() && pattern[pos] == kQuote) {
384fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        affix->append(kQuote); // Encode quote
385fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Fall through to append(ch)
386fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
387fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        subpart += 2; // open quote
388fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        continue;
389fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
390fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, fSeparator.length(), fSeparator) == 0) {
391fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Don't allow separators in the prefix, and don't allow
392fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // separators in the second pattern (part == 1).
393fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (subpart == 1 || part == 1) {
394fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Unexpected separator
395fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Unexpected separator")
396fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_UNEXPECTED_TOKEN;
397fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
398fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
399fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
400fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    sub2Limit = pos;
401fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    isPartDone = TRUE; // Go to next part
402fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += fSeparator.length();
403fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
404fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, fPercent.length(), fPercent) == 0) {
405fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Next handle characters which are appended directly.
406fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (multiplier != 1) {
407fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Too many percent/perMill characters
408fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Too many percent characters")
409fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_MULTIPLE_PERCENT_SYMBOLS;
410fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
411fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
412fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
413fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kQuote); // Encode percent/perMill
414fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kPatternPercent); // Use unlocalized pattern char
415fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    multiplier = 100;
416fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += fPercent.length();
417fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
418fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, fPerMill.length(), fPerMill) == 0) {
419fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    // Next handle characters which are appended directly.
420fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (multiplier != 1) {
421fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Too many percent/perMill characters
422fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Too many perMill characters")
423fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_MULTIPLE_PERMILL_SYMBOLS;
424fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
425fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
426fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
427fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kQuote); // Encode percent/perMill
428fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kPatternPerMill); // Use unlocalized pattern char
429fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    multiplier = 1000;
430fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += fPerMill.length();
431fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
432fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, fPadEscape.length(), fPadEscape) == 0) {
433fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (padPos >= 0 ||               // Multiple pad specifiers
434fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        (pos+1) == pattern.length()) { // Nothing after padEscape
435fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        debug("Multiple pad specifiers")
436fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        status = U_MULTIPLE_PAD_SPECIFIERS;
437fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        syntaxError(pattern,pos,parseError);
438fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        return;
439fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
440fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    padPos = pos;
441fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += fPadEscape.length();
442fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    padChar = pattern.char32At(pos);
443fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += U16_LENGTH(padChar);
444fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
445fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, fMinus.length(), fMinus) == 0) {
446fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kQuote); // Encode minus
447fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kPatternMinus);
448fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += fMinus.length();
449fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
450fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                } else if (pattern.compare(pos, fPlus.length(), fPlus) == 0) {
451fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kQuote); // Encode plus
452fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    affix->append(kPatternPlus);
453fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    pos += fPlus.length();
454fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    break;
455fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
456fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // Unquoted, non-special characters fall through to here, as
457fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // well as other code which needs to append something to the
458fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // affix.
459fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                affix->append(ch);
460fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                pos += U16_LENGTH(ch);
461fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                break;
462fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case 3: // Prefix subpart, in quote
463fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            case 4: // Suffix subpart, in quote
464fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // A quote within quotes indicates either the closing
465fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // quote or two quotes, which is a quote literal.  That is,
466fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // we have the second quote in 'do' or 'don''t'.
467fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                if (ch == kQuote) {
468fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    ++pos;
469fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    if (pos < pattern.length() && pattern[pos] == kQuote) {
470fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        affix->append(kQuote); // Encode quote
471fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        // Fall through to append(ch)
472fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    } else {
473fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        subpart -= 2; // close quote
474fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                        continue;
475fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    }
476fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                }
477fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                affix->append(ch);
478fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                pos += U16_LENGTH(ch);
479fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                break;
480fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
481fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
482fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
483fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (sub0Limit == 0) {
484fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            sub0Limit = pattern.length();
485fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
486fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
487fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (sub2Limit == 0) {
488fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            sub2Limit = pattern.length();
489fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
490fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
491fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        /* Handle patterns with no '0' pattern character.  These patterns
492fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * are legal, but must be recodified to make sense.  "##.###" ->
493fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * "#0.###".  ".###" -> ".0##".
494fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         *
495fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * We allow patterns of the form "####" to produce a zeroDigitCount
496fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * of zero (got that?); although this seems like it might make it
497fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * possible for format() to produce empty strings, format() checks
498fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * for this condition and outputs a zero digit in this situation.
499fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * Having a zeroDigitCount of zero yields a minimum integer digits
500fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * of zero, which allows proper round-trip patterns.  We don't want
501fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * "#" to become "#0" when toPattern() is called (even though that's
502fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         * what it really is, semantically).
503fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         */
504fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (zeroDigitCount == 0 && sigDigitCount == 0 &&
505fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            digitLeftCount > 0 && decimalPos >= 0) {
506fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // Handle "###.###" and "###." and ".###"
507fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            int n = decimalPos;
508fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (n == 0)
509fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                ++n; // Handle ".###"
510fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            digitRightCount = digitLeftCount - n;
511fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            digitLeftCount = n - 1;
512fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            zeroDigitCount = 1;
513fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
514fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
515fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Do syntax checking on the digits, decimal points, and quotes.
516fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
517fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            (decimalPos >= 0 &&
518fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius             (sigDigitCount > 0 ||
519fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius              decimalPos < digitLeftCount ||
520fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius              decimalPos > (digitLeftCount + zeroDigitCount))) ||
521fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            groupingCount == 0 || groupingCount2 == 0 ||
522fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            (sigDigitCount > 0 && zeroDigitCount > 0) ||
523fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            subpart > 2)
524fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        { // subpart > 2 == unmatched quote
525fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            debug("Syntax error")
526fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            status = U_PATTERN_SYNTAX_ERROR;
527fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            syntaxError(pattern,pos,parseError);
528fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            return;
529fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
530fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
531fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // Make sure pad is at legal position before or after affix.
532fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (padPos >= 0) {
533fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (padPos == start) {
534fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                padPos = DecimalFormatPattern::kPadBeforePrefix;
535fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else if (padPos+2 == sub0Start) {
536fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                padPos = DecimalFormatPattern::kPadAfterPrefix;
537fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else if (padPos == sub0Limit) {
538fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                padPos = DecimalFormatPattern::kPadBeforeSuffix;
539fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else if (padPos+2 == sub2Limit) {
540fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                padPos = DecimalFormatPattern::kPadAfterSuffix;
541fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else {
542fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // Illegal pad position
543fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                debug("Illegal pad position")
544fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                status = U_ILLEGAL_PAD_POSITION;
545fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                syntaxError(pattern,pos,parseError);
546fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                return;
547fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
548fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
549fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
550fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (part == 0) {
551fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fPosPatternsBogus = FALSE;
552fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fPosPrefixPattern = prefix;
553fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fPosSuffixPattern = suffix;
554fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fNegPatternsBogus = TRUE;
555fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fNegPrefixPattern.remove();
556fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fNegSuffixPattern.remove();
557fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
558fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fUseExponentialNotation = (expDigits >= 0);
559fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (out.fUseExponentialNotation) {
560fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius              out.fMinExponentDigits = expDigits;
561fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
562fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fExponentSignAlwaysShown = expSignAlways;
563fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
564fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // The effectiveDecimalPos is the position the decimal is at or
565fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // would be at if there is no decimal.  Note that if
566fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // decimalPos<0, then digitTotalCount == digitLeftCount +
567fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // zeroDigitCount.
568fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
569fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            UBool isSigDig = (sigDigitCount > 0);
570fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fUseSignificantDigits = isSigDig;
571fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (isSigDig) {
572fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fMinimumSignificantDigits = sigDigitCount;
573fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fMaximumSignificantDigits = sigDigitCount + digitRightCount;
574fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else {
575fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                int32_t minInt = effectiveDecimalPos - digitLeftCount;
576fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fMinimumIntegerDigits = minInt;
577fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fMaximumIntegerDigits = out.fUseExponentialNotation
578fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    ? digitLeftCount + out.fMinimumIntegerDigits
579fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    : gDefaultMaxIntegerDigits;
580fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fMaximumFractionDigits = decimalPos >= 0
581fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    ? (digitTotalCount - decimalPos) : 0;
582fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fMinimumFractionDigits = decimalPos >= 0
583fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    ? (digitLeftCount + zeroDigitCount - decimalPos) : 0;
584fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
585fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fGroupingUsed = groupingCount > 0;
586fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fGroupingSize = (groupingCount > 0) ? groupingCount : 0;
587fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
588fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                ? groupingCount2 : 0;
589fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fMultiplier = multiplier;
590fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fDecimalSeparatorAlwaysShown = decimalPos == 0
591fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    || decimalPos == digitTotalCount;
592fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (padPos >= 0) {
593fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fPadPosition = (DecimalFormatPattern::EPadPosition) padPos;
594fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // To compute the format width, first set up sub0Limit -
595fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // sub0Start.  Add in prefix/suffix length later.
596fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
597fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                // fFormatWidth = prefix.length() + suffix.length() +
598fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                //    sub0Limit - sub0Start;
599fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fFormatWidth = sub0Limit - sub0Start;
600fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fPad = padChar;
601fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else {
602fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fFormatWidth = 0;
603fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
604fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (roundingPos >= 0) {
605fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fRoundingIncrementUsed = TRUE;
606fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos);
607fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fRoundingIncrement = roundingInc;
608fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            } else {
609fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                out.fRoundingIncrementUsed = FALSE;
610fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
611fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        } else {
612fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fNegPatternsBogus = FALSE;
613fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fNegPrefixPattern = prefix;
614fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            out.fNegSuffixPattern = suffix;
615fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
616fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
617fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
618fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (pattern.length() == 0) {
619fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fNegPatternsBogus = TRUE;
620fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fNegPrefixPattern.remove();
621fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fNegSuffixPattern.remove();
622fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fPosPatternsBogus = FALSE;
623fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fPosPrefixPattern.remove();
624fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fPosSuffixPattern.remove();
625fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
626fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fMinimumIntegerDigits = 0;
627fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fMaximumIntegerDigits = kDoubleIntegerDigits;
628fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fMinimumFractionDigits = 0;
629fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fMaximumFractionDigits = kDoubleFractionDigits;
630fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
631fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fUseExponentialNotation = FALSE;
632fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fCurrencySignCount = fgCurrencySignCountZero;
633fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fGroupingUsed = FALSE;
634fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fGroupingSize = 0;
635fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fGroupingSize2 = 0;
636fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fMultiplier = 1;
637fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fDecimalSeparatorAlwaysShown = FALSE;
638fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fFormatWidth = 0;
639fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fRoundingIncrementUsed = FALSE;
640fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
641fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
642fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // If there was no negative pattern, or if the negative pattern is
643fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // identical to the positive pattern, then prepend the minus sign to the
644fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // positive pattern to form the negative pattern.
645fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (out.fNegPatternsBogus ||
646fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        (out.fNegPrefixPattern == out.fPosPrefixPattern
647fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius         && out.fNegSuffixPattern == out.fPosSuffixPattern)) {
648fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fNegPatternsBogus = FALSE;
649fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fNegSuffixPattern = out.fPosSuffixPattern;
650fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        out.fNegPrefixPattern.append(kQuote).append(kPatternMinus)
651fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            .append(out.fPosPrefixPattern);
652fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
653fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
654fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
655fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END
656fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
657fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif /* !UCONFIG_NO_FORMATTING */
658