1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/*
5 *******************************************************************************
6 * Copyright (C) 1996-2016, International Business Machines Corporation and
7 * others. All Rights Reserved.
8 *******************************************************************************
9 */
10package android.icu.text;
11
12import java.io.IOException;
13import java.io.ObjectInputStream;
14import java.io.ObjectOutputStream;
15import java.math.BigInteger;
16import java.text.AttributedCharacterIterator;
17import java.text.AttributedString;
18import java.text.ChoiceFormat;
19import java.text.FieldPosition;
20import java.text.Format;
21import java.text.ParsePosition;
22import java.util.ArrayList;
23import java.util.HashSet;
24import java.util.Iterator;
25import java.util.Set;
26
27import android.icu.impl.ICUConfig;
28import android.icu.impl.PatternProps;
29import android.icu.impl.Utility;
30import android.icu.lang.UCharacter;
31import android.icu.math.BigDecimal;
32import android.icu.math.MathContext;
33import android.icu.text.PluralRules.FixedDecimal;
34import android.icu.util.Currency;
35import android.icu.util.Currency.CurrencyUsage;
36import android.icu.util.CurrencyAmount;
37import android.icu.util.ULocale;
38import android.icu.util.ULocale.Category;
39
40/**
41 * <strong>[icu enhancement]</strong> ICU's replacement for {@link java.text.DecimalFormat}.&nbsp;Methods, fields, and other functionality specific to ICU are labeled '<strong>[icu]</strong>'.
42 *
43 * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
44 * decimal numbers. It has a variety of features designed to make it possible to parse and
45 * format numbers in any locale, including support for Western, Arabic, or Indic digits.
46 * It also supports different flavors of numbers, including integers ("123"), fixed-point
47 * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
48 * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be
49 * easily localized.
50 *
51 * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
52 * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
53 * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
54 * directly, unless you know what you are doing, since the {@link NumberFormat} factory
55 * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
56 * customize the format object, do something like this:
57 *
58 * <blockquote><pre>
59 * NumberFormat f = NumberFormat.getInstance(loc);
60 * if (f instanceof DecimalFormat) {
61 *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
62 * }</pre></blockquote>
63 *
64 * <p><strong>Example Usage</strong>
65 *
66 * Print out a number using the localized number, currency, and percent
67 * format for each locale.
68 *
69 * <blockquote><pre>
70 * Locale[] locales = NumberFormat.getAvailableLocales();
71 * double myNumber = -1234.56;
72 * NumberFormat format;
73 * for (int j=0; j&lt;3; ++j) {
74 *     System.out.println("FORMAT");
75 *     for (int i = 0; i &lt; locales.length; ++i) {
76 *         if (locales[i].getCountry().length() == 0) {
77 *            // Skip language-only locales
78 *            continue;
79 *         }
80 *         System.out.print(locales[i].getDisplayName());
81 *         switch (j) {
82 *         case 0:
83 *             format = NumberFormat.getInstance(locales[i]); break;
84 *         case 1:
85 *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
86 *         default:
87 *             format = NumberFormat.getPercentInstance(locales[i]); break;
88 *         }
89 *         try {
90 *             // Assume format is a DecimalFormat
91 *             System.out.print(": " + ((DecimalFormat) format).toPattern()
92 *                              + " -&gt; " + form.format(myNumber));
93 *         } catch (Exception e) {}
94 *         try {
95 *             System.out.println(" -&gt; " + format.parse(form.format(myNumber)));
96 *         } catch (ParseException e) {}
97 *     }
98 * }</pre></blockquote>
99 *
100 * <p>Another example use getInstance(style).<br>
101 * Print out a number using the localized number, currency, percent,
102 * scientific, integer, iso currency, and plural currency format for each locale.
103 *
104 * <blockquote><pre>
105 * ULocale locale = new ULocale("en_US");
106 * double myNumber = 1234.56;
107 * for (int j=NumberFormat.NUMBERSTYLE; j&lt;=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
108 *     NumberFormat format = NumberFormat.getInstance(locale, j);
109 *     try {
110 *         // Assume format is a DecimalFormat
111 *         System.out.print(": " + ((DecimalFormat) format).toPattern()
112 *                          + " -&gt; " + form.format(myNumber));
113 *     } catch (Exception e) {}
114 *     try {
115 *         System.out.println(" -&gt; " + format.parse(form.format(myNumber)));
116 *     } catch (ParseException e) {}
117 * }</pre></blockquote>
118 *
119 * <h3>Patterns</h3>
120 *
121 * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
122 * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or
123 * indirectly using other API methods which manipulate aspects of the pattern, such as the
124 * minimum number of integer digits.  The symbols are stored in a {@link
125 * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the
126 * pattern and symbols are read from ICU's locale data.
127 *
128 * <h4>Special Pattern Characters</h4>
129 *
130 * <p>Many characters in a pattern are taken literally; they are matched during parsing
131 * and output unchanged during formatting.  Special characters, on the other hand, stand
132 * for other characters, strings, or classes of characters.  For example, the '#'
133 * character is replaced by a localized digit.  Often the replacement character is the
134 * same as the pattern character; in the U.S. locale, the ',' grouping character is
135 * replaced by ','.  However, the replacement is still happening, and if the symbols are
136 * modified, the grouping character changes.  Some special characters affect the behavior
137 * of the formatter by their presence; for example, if the percent character is seen, then
138 * the value is multiplied by 100 before being displayed.
139 *
140 * <p>To insert a special character in a pattern as a literal, that is, without any
141 * special meaning, the character must be quoted.  There are some exceptions to this which
142 * are noted below.
143 *
144 * <p>The characters listed here are used in non-localized patterns.  Localized patterns
145 * use the corresponding characters taken from this formatter's {@link
146 * DecimalFormatSymbols} object instead, and these characters lose their special status.
147 * Two exceptions are the currency sign and quote, which are not localized.
148 *
149 * <blockquote>
150 * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
151 *  location, localized, and meaning.">
152 *   <tr style="background-color: #ccccff">
153 *     <th align=left>Symbol
154 *     <th align=left>Location
155 *     <th align=left>Localized?
156 *     <th align=left>Meaning
157 *   <tr style="vertical-align: top;">
158 *     <td><code>0</code>
159 *     <td>Number
160 *     <td>Yes
161 *     <td>Digit
162 *   <tr style="vertical-align: top; background-color: #eeeeff;">
163 *     <td><code>1-9</code>
164 *     <td>Number
165 *     <td>Yes
166 *     <td>'1' through '9' indicate rounding.
167 *   <tr style="vertical-align: top;">
168 *     <td><code>@</code>
169 *     <td>Number
170 *     <td>No
171 *     <td>Significant digit
172 *   <tr style="vertical-align: top; background-color: #eeeeff;">
173 *     <td><code>#</code>
174 *     <td>Number
175 *     <td>Yes
176 *     <td>Digit, zero shows as absent
177 *   <tr style="vertical-align: top;">
178 *     <td><code>.</code>
179 *     <td>Number
180 *     <td>Yes
181 *     <td>Decimal separator or monetary decimal separator
182 *   <tr style="vertical-align: top; background-color: #eeeeff;">
183 *     <td><code>-</code>
184 *     <td>Number
185 *     <td>Yes
186 *     <td>Minus sign
187 *   <tr style="vertical-align: top;">
188 *     <td><code>,</code>
189 *     <td>Number
190 *     <td>Yes
191 *     <td>Grouping separator
192 *   <tr style="vertical-align: top; background-color: #eeeeff;">
193 *     <td><code>E</code>
194 *     <td>Number
195 *     <td>Yes
196 *     <td>Separates mantissa and exponent in scientific notation.
197 *         <em>Need not be quoted in prefix or suffix.</em>
198 *   <tr style="vertical-align: top;">
199 *     <td><code>+</code>
200 *     <td>Exponent
201 *     <td>Yes
202 *     <td>Prefix positive exponents with localized plus sign.
203 *         <em>Need not be quoted in prefix or suffix.</em>
204 *   <tr style="vertical-align: top; background-color: #eeeeff;">
205 *     <td><code>;</code>
206 *     <td>Subpattern boundary
207 *     <td>Yes
208 *     <td>Separates positive and negative subpatterns
209 *   <tr style="vertical-align: top;">
210 *     <td><code>%</code>
211 *     <td>Prefix or suffix
212 *     <td>Yes
213 *     <td>Multiply by 100 and show as percentage
214 *   <tr style="vertical-align: top; background-color: #eeeeff;">
215 *     <td><code>&#92;u2030</code>
216 *     <td>Prefix or suffix
217 *     <td>Yes
218 *     <td>Multiply by 1000 and show as per mille
219 *   <tr style="vertical-align: top;">
220 *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
221 *     <td>Prefix or suffix
222 *     <td>No
223 *     <td>Currency sign, replaced by currency symbol.  If
224 *         doubled, replaced by international currency symbol.
225 *         If tripled, replaced by currency plural names, for example,
226 *         "US dollar" or "US dollars" for America.
227 *         If present in a pattern, the monetary decimal separator
228 *         is used instead of the decimal separator.
229 *   <tr style="vertical-align: top; background-color: #eeeeff;">
230 *     <td><code>'</code>
231 *     <td>Prefix or suffix
232 *     <td>No
233 *     <td>Used to quote special characters in a prefix or suffix,
234 *         for example, <code>"'#'#"</code> formats 123 to
235 *         <code>"#123"</code>.  To create a single quote
236 *         itself, use two in a row: <code>"# o''clock"</code>.
237 *   <tr style="vertical-align: top;">
238 *     <td><code>*</code>
239 *     <td>Prefix or suffix boundary
240 *     <td>Yes
241 *     <td>Pad escape, precedes pad character
242 * </table>
243 * </blockquote>
244 *
245 * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
246 * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a
247 * suffix.  If there is no explicit negative subpattern, the negative subpattern is the
248 * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
249 * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves
250 * only to specify the negative prefix and suffix; the number of digits, minimal digits,
251 * and other characteristics are ignored in the negative subpattern. That means that
252 * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
253 *
254 * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
255 * separators, decimal separators, etc. may be set to arbitrary values, and they will
256 * appear properly during formatting.  However, care must be taken that the symbols and
257 * strings do not conflict, or parsing will be unreliable.  For example, either the
258 * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
259 * be able to distinguish positive from negative values.  Another example is that the
260 * decimal separator and thousands separator should be distinct characters, or parsing
261 * will be impossible.
262 *
263 * <p>The <em>grouping separator</em> is a character that separates clusters of integer
264 * digits to make large numbers more legible.  It commonly used for thousands, but in some
265 * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits
266 * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
267 * 0000". There are actually two different grouping sizes: One used for the least
268 * significant integer digits, the <em>primary grouping size</em>, and one used for all
269 * others, the <em>secondary grouping size</em>.  In most locales these are the same, but
270 * sometimes they are different. For example, if the primary grouping interval is 3, and
271 * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
272 * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping
273 * separators, the interval between the last one and the end of the integer defines the
274 * primary grouping size, and the interval between the last two defines the secondary
275 * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
276 * "##,#,###,####".
277 *
278 * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
279 * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
280 * that describes the problem.
281 *
282 * <h4>Pattern BNF</h4>
283 *
284 * <pre>
285 * pattern    := subpattern (';' subpattern)?
286 * subpattern := prefix? number exponent? suffix?
287 * number     := (integer ('.' fraction)?) | sigDigits
288 * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
289 * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
290 * integer    := '#'* '0'* '0'
291 * fraction   := '0'* '#'*
292 * sigDigits  := '#'* '@' '@'* '#'*
293 * exponent   := 'E' '+'? '0'* '0'
294 * padSpec    := '*' padChar
295 * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
296 * &#32;
297 * Notation:
298 *   X*       0 or more instances of X
299 *   X?       0 or 1 instances of X
300 *   X|Y      either X or Y
301 *   C..D     any character from C up to D, inclusive
302 *   S-T      characters in S, except those in T
303 * </pre>
304 * The first subpattern is for positive numbers. The second (optional)
305 * subpattern is for negative numbers.
306 *
307 * <p>Not indicated in the BNF syntax above:
308 *
309 * <ul>
310 *
311 * <li>The grouping separator ',' can occur inside the integer and sigDigits
312 * elements, between any two pattern characters of that element, as long as the integer or
313 * sigDigits element is not followed by the exponent element.
314 *
315 * <li>Two grouping intervals are recognized: That between the decimal point and the first
316 * grouping symbol, and that between the first and second grouping symbols. These
317 * intervals are identical in most locales, but in some locales they differ. For example,
318 * the pattern &quot;#,##,###&quot; formats the number 123456789 as
319 * &quot;12,34,56,789&quot;.
320 *
321 * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
322 * prefix, before the suffix, after the suffix, or not at all.
323 *
324 * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
325 * increment.
326 *
327 * </ul>
328 *
329 * <h4>Parsing</h4>
330 *
331 * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
332 * digits, as defined by {@link UCharacter#digit}.  In addition,
333 * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
334 * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
335 * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.
336 *
337 * <p>During parsing, grouping separators are ignored.
338 *
339 * <p>For currency parsing, the formatter is able to parse every currency style formats no
340 * matter which style the formatter is constructed with.  For example, a formatter
341 * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
342 * parse formats such as "USD1.00" and "3.00 US dollars".
343 *
344 * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
345 * <code>null</code> and leaves the parse position unchanged.  The convenience method
346 * {@link #parse(String)} indicates parse failure by throwing a {@link
347 * java.text.ParseException}.
348 *
349 * <p>Parsing an extremely large or small absolute value (such as 1.0E10000 or 1.0E-10000)
350 * requires huge memory allocation for representing the parsed number. Such input may expose
351 * a risk of DoS attacks. To prevent huge memory allocation triggered by such inputs,
352 * <code>DecimalFormat</code> internally limits of maximum decimal digits to be 1000. Thus,
353 * an input string resulting more than 1000 digits in plain decimal representation (non-exponent)
354 * will be treated as either overflow (positive/negative infinite) or underflow (+0.0/-0.0).
355 *
356 * <h4>Formatting</h4>
357 *
358 * <p>Formatting is guided by several parameters, all of which can be specified either
359 * using a pattern or using the API.  The following description applies to formats that do
360 * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
361 * digits</a>.
362 *
363 * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
364 * digits</em>, then only the least significant digits are shown.  For example, 1997 is
365 * formatted as "97" if the maximum integer digits is set to 2.
366 *
367 * <li>If the number of actual integer digits is less than the <em>minimum integer
368 * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"
369 * if the minimum integer digits is set to 5.
370 *
371 * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
372 * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For
373 * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This
374 * behavior can be changed by specifying a rounding increment and a rounding mode.
375 *
376 * <li>If the number of actual fraction digits is less than the <em>minimum fraction
377 * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as
378 * "0.1250" if the mimimum fraction digits is set to 4.
379 *
380 * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
381 * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
382 * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
383 * </ul>
384 *
385 * <p><strong>Special Values</strong>
386 *
387 * <p><code>NaN</code> is represented as a single character, typically
388 * <code>&#92;uFFFD</code>.  This character is determined by the {@link
389 * DecimalFormatSymbols} object.  This is the only value for which the prefixes and
390 * suffixes are not used.
391 *
392 * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,
393 * with the positive or negative prefixes and suffixes applied.  The infinity character is
394 * determined by the {@link DecimalFormatSymbols} object.
395 *
396 * <h4><a name="sci">Scientific Notation</a></h4>
397 *
398 * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
399 * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
400 * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
401 * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
402 * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
403 * or through the pattern.  In a pattern, the exponent character immediately followed by
404 * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats
405 * the number 1234 as "1.234E3".
406 *
407 * <ul>
408 *
409 * <li>The number of digit characters after the exponent character gives the minimum
410 * exponent digit count.  There is no maximum.  Negative exponents are formatted using the
411 * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows
412 * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus
413 * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
414 * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign
415 * rather than '+'.)
416 *
417 * <li>The minimum number of integer digits is achieved by adjusting the exponent.
418 * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if
419 * there is no maximum number of integer digits.  If there is a maximum, then the minimum
420 * number of integer digits is fixed at one.
421 *
422 * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
423 * The most common use of this is to generate <em>engineering notation</em>, in which the
424 * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted
425 * using "##0.####E0" as "12.345E3".
426 *
427 * <li>When using scientific notation, the formatter controls the digit counts using
428 * significant digits logic.  The maximum number of significant digits limits the total
429 * number of integer and fraction digits that will be shown in the mantissa; it does not
430 * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the
431 * section on significant digits for more details.
432 *
433 * <li>The number of significant digits shown is determined as follows: If
434 * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
435 * shown is one, and the maximum number of significant digits shown is the sum of the
436 * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
437 * maximum integer digits.  If this sum is zero, then all significant digits are shown.
438 * If areSignificantDigitsUsed() returns true, then the significant digit counts are
439 * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this
440 * case, the number of integer digits is fixed at one, and there is no exponent grouping.
441 *
442 * <li>Exponential patterns may not contain grouping separators.
443 *
444 * </ul>
445 *
446 * <h4><a name="sigdig">Significant Digits</a></h4>
447 *
448 * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
449 * significant digits counts, or (b) integer and fraction digit counts.  Integer and
450 * fraction digit counts are described above.  When a formatter is using significant
451 * digits counts, the number of integer and fraction digits is not specified directly, and
452 * the formatter settings for these counts are ignored.  Instead, the formatter uses
453 * however many integer and fraction digits are required to display the specified number
454 * of significant digits.  Examples:
455 *
456 * <blockquote>
457 * <table border=0 cellspacing=3 cellpadding=0>
458 *   <tr style="background-color: #ccccff">
459 *     <th align=left>Pattern
460 *     <th align=left>Minimum significant digits
461 *     <th align=left>Maximum significant digits
462 *     <th align=left>Number
463 *     <th align=left>Output of format()
464 *   <tr style="vertical-align: top;">
465 *     <td><code>@@@</code>
466 *     <td>3
467 *     <td>3
468 *     <td>12345
469 *     <td><code>12300</code>
470 *   <tr style="vertical-align: top; background-color: #eeeeff;">
471 *     <td><code>@@@</code>
472 *     <td>3
473 *     <td>3
474 *     <td>0.12345
475 *     <td><code>0.123</code>
476 *   <tr style="vertical-align: top;">
477 *     <td><code>@@##</code>
478 *     <td>2
479 *     <td>4
480 *     <td>3.14159
481 *     <td><code>3.142</code>
482 *   <tr style="vertical-align: top; background-color: #eeeeff;">
483 *     <td><code>@@##</code>
484 *     <td>2
485 *     <td>4
486 *     <td>1.23004
487 *     <td><code>1.23</code>
488 * </table>
489 * </blockquote>
490 *
491 * <ul>
492 *
493 * <li>Significant digit counts may be expressed using patterns that specify a minimum and
494 * maximum number of significant digits.  These are indicated by the <code>'@'</code> and
495 * <code>'#'</code> characters.  The minimum number of significant digits is the number of
496 * <code>'@'</code> characters.  The maximum number of significant digits is the number of
497 * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
498 * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
499 * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
500 * Trailing zero digits to the right of the decimal separator are suppressed after the
501 * minimum number of significant digits have been shown.  For example, the pattern
502 * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
503 *
504 * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
505 * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or
506 * <code>"@.###"</code> are disallowed.
507 *
508 * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
509 * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum
510 * significant digits counts, but may be used to position grouping separators.  For
511 * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
512 * of two significant digits, and a grouping size of three.
513 *
514 * <li>In order to enable significant digits formatting, use a pattern containing the
515 * <code>'@'</code> pattern character.  Alternatively, call {@link
516 * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
517 *
518 * <li>In order to disable significant digits formatting, use a pattern that does not
519 * contain the <code>'@'</code> pattern character. Alternatively, call {@link
520 * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
521 *
522 * <li>The number of significant digits has no effect on parsing.
523 *
524 * <li>Significant digits may be used together with exponential notation. Such patterns
525 * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
526 * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
527 * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
528 * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
529 * <code>"0.0###E0"</code>.
530 *
531 * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
532 * via the API, are ignored.  If significant digits are not in use, then the signficant
533 * digit counts, as set via the API, are ignored.
534 *
535 * </ul>
536 *
537 * <h4>Padding</h4>
538 *
539 * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
540 * specific width.  Padding may be specified either through the API or through the pattern
541 * syntax.  In a pattern the pad escape character, followed by a single pad character,
542 * causes padding to be parsed and formatted.  The pad escape character is '*' in
543 * unlocalized patterns, and can be localized using {@link
544 * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats
545 * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
546 *
547 * <ul>
548 *
549 * <li>When padding is in effect, the width of the positive subpattern, including prefix
550 * and suffix, determines the format width.  For example, in the pattern <code>"* #0
551 * o''clock"</code>, the format width is 10.
552 *
553 * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
554 *
555 * <li>Some parameters which usually do not matter have meaning when padding is used,
556 * because the pattern width is significant with padding.  In the pattern "*
557 * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect
558 * the grouping size or maximum integer digits, but they do affect the format width.
559 *
560 * <li>Padding may be inserted at one of four locations: before the prefix, after the
561 * prefix, before the suffix, or after the suffix.  If padding is specified in any other
562 * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there
563 * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
564 * suffix.
565 *
566 * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
567 * pad escape is the pad character. This may be any character, including a special pattern
568 * character. That is, the pad escape <em>escapes</em> the following character. If there
569 * is no character after the pad escape, then the pattern is illegal.
570 *
571 * </ul>
572 *
573 * <p>
574 * <strong>Rounding</strong>
575 *
576 * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,
577 * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The
578 * rounding increment may be specified through the API or in a pattern.  To specify a
579 * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"
580 * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of
581 * 0.05.
582 *
583 * <ul>
584 *
585 * <li>Rounding only affects the string produced by formatting.  It does not affect
586 * parsing or change any numerical values.
587 *
588 * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
589 * android.icu.math.BigDecimal} documentation for a description of the modes.  Rounding
590 * increments specified in patterns use the default mode, {@link
591 * android.icu.math.BigDecimal#ROUND_HALF_EVEN}.
592 *
593 * <li>Some locales use rounding in their currency formats to reflect the smallest
594 * currency denomination.
595 *
596 * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
597 * identically to digit '0'.
598 *
599 * </ul>
600 *
601 * <h4>Synchronization</h4>
602 *
603 * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should
604 * not access one formatter concurrently.
605 *
606 * @see          java.text.Format
607 * @see          NumberFormat
608 * @author       Mark Davis
609 * @author       Alan Liu
610 */
611public class DecimalFormat extends NumberFormat {
612
613    /**
614     * Creates a DecimalFormat using the default pattern and symbols for the default
615     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
616     * internationalization is not the main concern.
617     *
618     * <p>To obtain standard formats for a given locale, use the factory methods on
619     * NumberFormat such as getNumberInstance.  These factories will return the most
620     * appropriate sub-class of NumberFormat for a given locale.
621     *
622     * @see NumberFormat#getInstance
623     * @see NumberFormat#getNumberInstance
624     * @see NumberFormat#getCurrencyInstance
625     * @see NumberFormat#getPercentInstance
626     * @see Category#FORMAT
627     */
628    public DecimalFormat() {
629        ULocale def = ULocale.getDefault(Category.FORMAT);
630        String pattern = getPattern(def, 0);
631        // Always applyPattern after the symbols are set
632        this.symbols = new DecimalFormatSymbols(def);
633        setCurrency(Currency.getInstance(def));
634        applyPatternWithoutExpandAffix(pattern, false);
635        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
636            currencyPluralInfo = new CurrencyPluralInfo(def);
637            // the exact pattern is not known until the plural count is known.
638            // so, no need to expand affix now.
639        } else {
640            expandAffixAdjustWidth(null);
641        }
642    }
643
644    /**
645     * Creates a DecimalFormat from the given pattern and the symbols for the default
646     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
647     * internationalization is not the main concern.
648     *
649     * <p>To obtain standard formats for a given locale, use the factory methods on
650     * NumberFormat such as getNumberInstance.  These factories will return the most
651     * appropriate sub-class of NumberFormat for a given locale.
652     *
653     * @param pattern A non-localized pattern string.
654     * @throws IllegalArgumentException if the given pattern is invalid.
655     * @see NumberFormat#getInstance
656     * @see NumberFormat#getNumberInstance
657     * @see NumberFormat#getCurrencyInstance
658     * @see NumberFormat#getPercentInstance
659     * @see Category#FORMAT
660     */
661    public DecimalFormat(String pattern) {
662        // Always applyPattern after the symbols are set
663        ULocale def = ULocale.getDefault(Category.FORMAT);
664        this.symbols = new DecimalFormatSymbols(def);
665        setCurrency(Currency.getInstance(def));
666        applyPatternWithoutExpandAffix(pattern, false);
667        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
668            currencyPluralInfo = new CurrencyPluralInfo(def);
669        } else {
670            expandAffixAdjustWidth(null);
671        }
672    }
673
674    /**
675     * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
676     * when you need to completely customize the behavior of the format.
677     *
678     * <p>To obtain standard formats for a given locale, use the factory methods on
679     * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
680     * adjustments to a standard format, you can modify the format returned by a
681     * NumberFormat factory method.
682     *
683     * @param pattern a non-localized pattern string
684     * @param symbols the set of symbols to be used
685     * @exception IllegalArgumentException if the given pattern is invalid
686     * @see NumberFormat#getInstance
687     * @see NumberFormat#getNumberInstance
688     * @see NumberFormat#getCurrencyInstance
689     * @see NumberFormat#getPercentInstance
690     * @see DecimalFormatSymbols
691     */
692    public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
693        createFromPatternAndSymbols(pattern, symbols);
694    }
695
696    private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
697        // Always applyPattern after the symbols are set
698        symbols = (DecimalFormatSymbols) inputSymbols.clone();
699        if (pattern.indexOf(CURRENCY_SIGN) >= 0) {
700            // Only spend time with currency symbols when we're going to display it.
701            // Also set some defaults before the apply pattern.
702            setCurrencyForSymbols();
703        }
704        applyPatternWithoutExpandAffix(pattern, false);
705        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
706            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
707        } else {
708            expandAffixAdjustWidth(null);
709        }
710    }
711
712    /**
713     * Creates a DecimalFormat from the given pattern, symbols, information used for
714     * currency plural format, and format style. Use this constructor when you need to
715     * completely customize the behavior of the format.
716     *
717     * <p>To obtain standard formats for a given locale, use the factory methods on
718     * NumberFormat such as getInstance or getCurrencyInstance.
719     *
720     * <p>If you need only minor adjustments to a standard format, you can modify the
721     * format returned by a NumberFormat factory method using the setters.
722     *
723     * <p>If you want to completely customize a decimal format, using your own
724     * DecimalFormatSymbols (such as group separators) and your own information for
725     * currency plural formatting (such as plural rule and currency plural patterns), you
726     * can use this constructor.
727     *
728     * @param pattern a non-localized pattern string
729     * @param symbols the set of symbols to be used
730     * @param infoInput the information used for currency plural format, including
731     * currency plural patterns and plural rules.
732     * @param style the decimal formatting style, it is one of the following values:
733     * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
734     * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
735     * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
736     */
737    public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
738                         int style) {
739        CurrencyPluralInfo info = infoInput;
740        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
741            info = (CurrencyPluralInfo) infoInput.clone();
742        }
743        create(pattern, symbols, info, style);
744    }
745
746    private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info,
747                        int inputStyle) {
748        if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
749            createFromPatternAndSymbols(pattern, inputSymbols);
750        } else {
751            // Always applyPattern after the symbols are set
752            symbols = (DecimalFormatSymbols) inputSymbols.clone();
753            currencyPluralInfo = info;
754            // the pattern used in format is not fixed until formatting, in which, the
755            // number is known and will be used to pick the right pattern based on plural
756            // count.  Here, set the pattern as the pattern of plural count == "other".
757            // For most locale, the patterns are probably the same for all plural
758            // count. If not, the right pattern need to be re-applied during format.
759            String currencyPluralPatternForOther =
760                currencyPluralInfo.getCurrencyPluralPattern("other");
761            applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false);
762            setCurrencyForSymbols();
763        }
764        style = inputStyle;
765    }
766
767    /**
768     * Creates a DecimalFormat for currency plural format from the given pattern, symbols,
769     * and style.
770     */
771    DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
772        CurrencyPluralInfo info = null;
773        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
774            info = new CurrencyPluralInfo(inputSymbols.getULocale());
775        }
776        create(pattern, inputSymbols, info, style);
777    }
778
779    /**
780     * {@inheritDoc}
781     */
782    @Override
783    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
784        return format(number, result, fieldPosition, false);
785    }
786
787    // See if number is negative.
788    // usage: isNegative(multiply(numberToBeFormatted));
789    private boolean isNegative(double number) {
790        // Detecting whether a double is negative is easy with the exception of the value
791        // -0.0. This is a double which has a zero mantissa (and exponent), but a negative
792        // sign bit. It is semantically distinct from a zero with a positive sign bit, and
793        // this distinction is important to certain kinds of computations. However, it's a
794        // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you
795        // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
796        // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by
797        // bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
798        return (number < 0.0) || (number == 0.0 && 1 / number < 0.0);
799    }
800
801    // Rounds the number and strips of the negative sign.
802    // usage: round(multiply(numberToBeFormatted))
803    private double round(double number) {
804        boolean isNegative = isNegative(number);
805        if (isNegative)
806            number = -number;
807
808        // Apply rounding after multiplier
809        if (roundingDouble > 0.0) {
810            // number = roundingDouble
811            //    * round(number / roundingDouble, roundingMode, isNegative);
812            return round(
813                number, roundingDouble, roundingDoubleReciprocal, roundingMode,
814                isNegative);
815        }
816        return number;
817    }
818
819    // Multiplies given number by multipler (if there is one) returning the new
820    // number. If there is no multiplier, returns the number passed in unchanged.
821    private double multiply(double number) {
822        if (multiplier != 1) {
823            return number * multiplier;
824        }
825        return number;
826    }
827
828    // [Spark/CDL] The actual method to format number. If boolean value
829    // parseAttr == true, then attribute information will be recorded.
830    private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition,
831                                boolean parseAttr) {
832        fieldPosition.setBeginIndex(0);
833        fieldPosition.setEndIndex(0);
834
835        if (Double.isNaN(number)) {
836            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
837                fieldPosition.setBeginIndex(result.length());
838            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
839                fieldPosition.setBeginIndex(result.length());
840            }
841
842            result.append(symbols.getNaN());
843            // TODO: Combine setting a single FieldPosition or adding to an AttributedCharacterIterator
844            // into a function like recordAttribute(FieldAttribute, begin, end).
845
846            // [Spark/CDL] Add attribute for NaN here.
847            // result.append(symbols.getNaN());
848            if (parseAttr) {
849                addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(),
850                             result.length());
851            }
852            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
853                fieldPosition.setEndIndex(result.length());
854            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
855                fieldPosition.setEndIndex(result.length());
856            }
857
858            addPadding(result, fieldPosition, 0, 0);
859            return result;
860        }
861
862        // Do this BEFORE checking to see if value is negative or infinite and
863        // before rounding.
864        number = multiply(number);
865        boolean isNegative = isNegative(number);
866        number = round(number);
867
868        if (Double.isInfinite(number)) {
869            int prefixLen = appendAffix(result, isNegative, true, fieldPosition, parseAttr);
870
871            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
872                fieldPosition.setBeginIndex(result.length());
873            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
874                fieldPosition.setBeginIndex(result.length());
875            }
876
877            // [Spark/CDL] Add attribute for infinity here.
878            result.append(symbols.getInfinity());
879            if (parseAttr) {
880                addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(),
881                             result.length());
882            }
883            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
884                fieldPosition.setEndIndex(result.length());
885            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
886                fieldPosition.setEndIndex(result.length());
887            }
888
889            int suffixLen = appendAffix(result, isNegative, false, fieldPosition, parseAttr);
890
891            addPadding(result, fieldPosition, prefixLen, suffixLen);
892            return result;
893        }
894
895        int precision = precision(false);
896
897        // This is to fix rounding for scientific notation. See ticket:10542.
898        // This code should go away when a permanent fix is done for ticket:9931.
899        //
900        // This block of code only executes for scientific notation so it will not interfere with the
901        // previous fix in {@link #resetActualRounding} for fixed decimal numbers.
902        // Moreover this code only runs when there is rounding to be done (precision > 0) and when the
903        // rounding mode is something other than ROUND_HALF_EVEN.
904        // This block of code does the correct rounding of number in advance so that it will fit into
905        // the number of digits indicated by precision. In this way, we avoid using the default
906        // ROUND_HALF_EVEN behavior of DigitList. For example, if number = 0.003016 and roundingMode =
907        // ROUND_DOWN and precision = 3 then after this code executes, number = 0.00301 (3 significant digits)
908        if (useExponentialNotation && precision > 0 && number != 0.0 && roundingMode != BigDecimal.ROUND_HALF_EVEN) {
909           int log10RoundingIncr = 1 - precision + (int) Math.floor(Math.log10(Math.abs(number)));
910           double roundingIncReciprocal = 0.0;
911           double roundingInc = 0.0;
912           if (log10RoundingIncr < 0) {
913               roundingIncReciprocal =
914                       BigDecimal.ONE.movePointRight(-log10RoundingIncr).doubleValue();
915           } else {
916               roundingInc =
917                       BigDecimal.ONE.movePointRight(log10RoundingIncr).doubleValue();
918           }
919           number = DecimalFormat.round(number, roundingInc, roundingIncReciprocal, roundingMode, isNegative);
920        }
921        // End fix for ticket:10542
922
923        // At this point we are guaranteed a nonnegative finite
924        // number.
925        synchronized (digitList) {
926            digitList.set(number, precision, !useExponentialNotation &&
927                          !areSignificantDigitsUsed());
928            return subformat(number, result, fieldPosition, isNegative, false, parseAttr);
929        }
930    }
931
932    /**
933     * This is a special function used by the CompactDecimalFormat subclass.
934     * It completes only the rounding portion of the formatting and returns
935     * the resulting double. CompactDecimalFormat uses the result to compute
936     * the plural form to use.
937     *
938     * @param number The number to format.
939     * @return The number rounded to the correct number of significant digits
940     * with negative sign stripped off.
941     * @deprecated This API is ICU internal only.
942     * @hide draft / provisional / internal are hidden on Android
943     */
944    @Deprecated
945    double adjustNumberAsInFormatting(double number) {
946        if (Double.isNaN(number)) {
947            return number;
948        }
949        number = round(multiply(number));
950        if (Double.isInfinite(number)) {
951            return number;
952        }
953        return toDigitList(number).getDouble();
954    }
955
956    @Deprecated
957    DigitList toDigitList(double number) {
958        DigitList result = new DigitList();
959        result.set(number, precision(false), false);
960        return result;
961    }
962
963    /**
964      * This is a special function used by the CompactDecimalFormat subclass
965      * to determine if the number to be formatted is negative.
966      *
967      * @param number The number to format.
968      * @return True if number is negative.
969      * @deprecated This API is ICU internal only.
970     * @hide draft / provisional / internal are hidden on Android
971      */
972     @Deprecated
973     boolean isNumberNegative(double number) {
974         if (Double.isNaN(number)) {
975             return false;
976         }
977         return isNegative(multiply(number));
978     }
979
980    /**
981     * Round a double value to the nearest multiple of the given rounding increment,
982     * according to the given mode. This is equivalent to rounding value/roundingInc to
983     * the nearest integer, according to the given mode, and returning that integer *
984     * roundingInc. Note this is changed from the version in 2.4, since division of
985     * doubles have inaccuracies. jitterbug 1871.
986     *
987     * @param number
988     *            the absolute value of the number to be rounded
989     * @param roundingInc
990     *            the rounding increment
991     * @param roundingIncReciprocal
992     *            if non-zero, is the reciprocal of rounding inc.
993     * @param mode
994     *            a BigDecimal rounding mode
995     * @param isNegative
996     *            true if the number to be rounded is negative
997     * @return the absolute value of the rounded result
998     */
999    private static double round(double number, double roundingInc, double roundingIncReciprocal,
1000                                int mode, boolean isNegative) {
1001
1002        double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number *
1003            roundingIncReciprocal;
1004
1005        // do the absolute cases first
1006
1007        switch (mode) {
1008        case BigDecimal.ROUND_CEILING:
1009            div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
1010            break;
1011        case BigDecimal.ROUND_FLOOR:
1012            div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
1013            break;
1014        case BigDecimal.ROUND_DOWN:
1015            div = (Math.floor(div + epsilon));
1016            break;
1017        case BigDecimal.ROUND_UP:
1018            div = (Math.ceil(div - epsilon));
1019            break;
1020        case BigDecimal.ROUND_UNNECESSARY:
1021            if (div != Math.floor(div)) {
1022                throw new ArithmeticException("Rounding necessary");
1023            }
1024            return number;
1025        default:
1026
1027            // Handle complex cases, where the choice depends on the closer value.
1028
1029            // We figure out the distances to the two possible values, ceiling and floor.
1030            // We then go for the diff that is smaller.  Only if they are equal does the
1031            // mode matter.
1032
1033            double ceil = Math.ceil(div);
1034            double ceildiff = ceil - div; // (ceil * roundingInc) - number;
1035            double floor = Math.floor(div);
1036            double floordiff = div - floor; // number - (floor * roundingInc);
1037
1038            // Note that the diff values were those mapped back to the "normal" space by
1039            // using the roundingInc. I don't have access to the original author of the
1040            // code but suspect that that was to produce better result in edge cases
1041            // because of machine precision, rather than simply using the difference
1042            // between, say, ceil and div.  However, it didn't work in all cases. Am
1043            // trying instead using an epsilon value.
1044
1045            switch (mode) {
1046            case BigDecimal.ROUND_HALF_EVEN:
1047                // We should be able to just return Math.rint(a), but this
1048                // doesn't work in some VMs.
1049                // if one is smaller than the other, take the corresponding side
1050                if (floordiff + epsilon < ceildiff) {
1051                    div = floor;
1052                } else if (ceildiff + epsilon < floordiff) {
1053                    div = ceil;
1054                } else { // they are equal, so we want to round to whichever is even
1055                    double testFloor = floor / 2;
1056                    div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
1057                }
1058                break;
1059            case BigDecimal.ROUND_HALF_DOWN:
1060                div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
1061                break;
1062            case BigDecimal.ROUND_HALF_UP:
1063                div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
1064                break;
1065            default:
1066                throw new IllegalArgumentException("Invalid rounding mode: " + mode);
1067            }
1068        }
1069        number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal;
1070        return number;
1071    }
1072
1073    private static double epsilon = 0.00000000001;
1074
1075    /**
1076     */
1077    // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
1078    @Override
1079    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
1080        return format(number, result, fieldPosition, false);
1081    }
1082
1083    private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition,
1084                                boolean parseAttr) {
1085        fieldPosition.setBeginIndex(0);
1086        fieldPosition.setEndIndex(0);
1087
1088        // If we are to do rounding, we need to move into the BigDecimal
1089        // domain in order to do divide/multiply correctly.
1090        if (actualRoundingIncrementICU != null) {
1091            return format(BigDecimal.valueOf(number), result, fieldPosition);
1092        }
1093
1094        boolean isNegative = (number < 0);
1095        if (isNegative)
1096            number = -number;
1097
1098        // In general, long values always represent real finite numbers, so we don't have
1099        // to check for +/- Infinity or NaN. However, there is one case we have to be
1100        // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE
1101        // outside the legal range. We check for this before multiplying, and if it
1102        // happens we use BigInteger instead.
1103        if (multiplier != 1) {
1104            boolean tooBig = false;
1105            if (number < 0) { // This can only happen if number == Long.MIN_VALUE
1106                long cutoff = Long.MIN_VALUE / multiplier;
1107                tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
1108            } else {
1109                long cutoff = Long.MAX_VALUE / multiplier;
1110                tooBig = (number > cutoff);
1111            }
1112            if (tooBig) {
1113                // [Spark/CDL] Use
1114                // format_BigInteger_StringBuffer_FieldPosition_boolean instead
1115                // parseAttr is used to judge whether to synthesize attributes.
1116                return format(BigInteger.valueOf(isNegative ? -number : number), result,
1117                              fieldPosition, parseAttr);
1118            }
1119        }
1120
1121        number *= multiplier;
1122        synchronized (digitList) {
1123            digitList.set(number, precision(true));
1124            // Issue 11808
1125            if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
1126                throw new ArithmeticException("Rounding necessary");
1127            }
1128            return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
1129        }
1130    }
1131
1132    /**
1133     * Formats a BigInteger number.
1134     */
1135    @Override
1136    public StringBuffer format(BigInteger number, StringBuffer result,
1137                               FieldPosition fieldPosition) {
1138        return format(number, result, fieldPosition, false);
1139    }
1140
1141    private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition,
1142                                boolean parseAttr) {
1143        // If we are to do rounding, we need to move into the BigDecimal
1144        // domain in order to do divide/multiply correctly.
1145        if (actualRoundingIncrementICU != null) {
1146            return format(new BigDecimal(number), result, fieldPosition);
1147        }
1148
1149        if (multiplier != 1) {
1150            number = number.multiply(BigInteger.valueOf(multiplier));
1151        }
1152
1153        // At this point we are guaranteed a nonnegative finite
1154        // number.
1155        synchronized (digitList) {
1156            digitList.set(number, precision(true));
1157            // For issue 11808.
1158            if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
1159                throw new ArithmeticException("Rounding necessary");
1160            }
1161            return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
1162                             parseAttr);
1163        }
1164    }
1165
1166    /**
1167     * Formats a BigDecimal number.
1168     */
1169    @Override
1170    public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
1171                               FieldPosition fieldPosition) {
1172        return format(number, result, fieldPosition, false);
1173    }
1174
1175    private StringBuffer format(java.math.BigDecimal number, StringBuffer result,
1176                                FieldPosition fieldPosition,
1177            boolean parseAttr) {
1178        if (multiplier != 1) {
1179            number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
1180        }
1181
1182        if (actualRoundingIncrement != null) {
1183            number = number.divide(actualRoundingIncrement, 0, roundingMode).multiply(actualRoundingIncrement);
1184        }
1185
1186        synchronized (digitList) {
1187            digitList.set(number, precision(false), !useExponentialNotation &&
1188                          !areSignificantDigitsUsed());
1189            // For issue 11808.
1190            if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
1191                throw new ArithmeticException("Rounding necessary");
1192            }
1193            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
1194                             false, parseAttr);
1195        }
1196    }
1197
1198    /**
1199     * Formats a BigDecimal number.
1200     */
1201    @Override
1202    public StringBuffer format(BigDecimal number, StringBuffer result,
1203                               FieldPosition fieldPosition) {
1204         // This method is just a copy of the corresponding java.math.BigDecimal method
1205         // for now. It isn't very efficient since it must create a conversion object to
1206         // do math on the rounding increment. In the future we may try to clean this up,
1207         // or even better, limit our support to just one flavor of BigDecimal.
1208        if (multiplier != 1) {
1209            number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
1210        }
1211
1212        if (actualRoundingIncrementICU != null) {
1213            number = number.divide(actualRoundingIncrementICU, 0, roundingMode)
1214                .multiply(actualRoundingIncrementICU, mathContext);
1215        }
1216
1217        synchronized (digitList) {
1218            digitList.set(number, precision(false), !useExponentialNotation &&
1219                          !areSignificantDigitsUsed());
1220            // For issue 11808.
1221            if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
1222                throw new ArithmeticException("Rounding necessary");
1223            }
1224            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
1225                             false, false);
1226        }
1227    }
1228
1229    /**
1230     * Returns true if a grouping separator belongs at the given position, based on whether
1231     * grouping is in use and the values of the primary and secondary grouping interval.
1232     *
1233     * @param pos the number of integer digits to the right of the current position. Zero
1234     * indicates the position after the rightmost integer digit.
1235     * @return true if a grouping character belongs at the current position.
1236     */
1237    private boolean isGroupingPosition(int pos) {
1238        boolean result = false;
1239        if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
1240            if ((groupingSize2 > 0) && (pos > groupingSize)) {
1241                result = ((pos - groupingSize) % groupingSize2) == 0;
1242            } else {
1243                result = pos % groupingSize == 0;
1244            }
1245        }
1246        return result;
1247    }
1248
1249    /**
1250     * Return the number of fraction digits to display, or the total
1251     * number of digits for significant digit formats and exponential
1252     * formats.
1253     */
1254    private int precision(boolean isIntegral) {
1255        if (areSignificantDigitsUsed()) {
1256            return getMaximumSignificantDigits();
1257        } else if (useExponentialNotation) {
1258            return getMinimumIntegerDigits() + getMaximumFractionDigits();
1259        } else {
1260            return isIntegral ? 0 : getMaximumFractionDigits();
1261        }
1262    }
1263
1264    private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition,
1265                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
1266        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
1267            // compute the plural category from the digitList plus other settings
1268            return subformat(currencyPluralInfo.select(getFixedDecimal(number)),
1269                             result, fieldPosition, isNegative,
1270                             isInteger, parseAttr);
1271        } else {
1272            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
1273        }
1274    }
1275
1276    /**
1277     * This is ugly, but don't see a better way to do it without major restructuring of the code.
1278     */
1279    /*package*/ FixedDecimal getFixedDecimal(double number) {
1280        // get the visible fractions and the number of fraction digits.
1281       return getFixedDecimal(number, digitList);
1282    }
1283
1284    FixedDecimal getFixedDecimal(double number, DigitList dl) {
1285        int fractionalDigitsInDigitList = dl.count - dl.decimalAt;
1286        int v;
1287        long f;
1288        int maxFractionalDigits;
1289        int minFractionalDigits;
1290        if (useSignificantDigits) {
1291            maxFractionalDigits = maxSignificantDigits - dl.decimalAt;
1292            minFractionalDigits = minSignificantDigits - dl.decimalAt;
1293            if (minFractionalDigits < 0) {
1294                minFractionalDigits = 0;
1295            }
1296            if (maxFractionalDigits < 0) {
1297                maxFractionalDigits = 0;
1298            }
1299        } else {
1300            maxFractionalDigits = getMaximumFractionDigits();
1301            minFractionalDigits = getMinimumFractionDigits();
1302        }
1303        v = fractionalDigitsInDigitList;
1304        if (v < minFractionalDigits) {
1305            v = minFractionalDigits;
1306        } else if (v > maxFractionalDigits) {
1307            v = maxFractionalDigits;
1308        }
1309        f = 0;
1310        if (v > 0) {
1311            for (int i = Math.max(0, dl.decimalAt); i < dl.count; ++i) {
1312                f *= 10;
1313                f += (dl.digits[i] - '0');
1314            }
1315            for (int i = v; i < fractionalDigitsInDigitList; ++i) {
1316                f *= 10;
1317            }
1318        }
1319        return new FixedDecimal(number, v, f);
1320    }
1321
1322    private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition,
1323                                   boolean isNegative,
1324            boolean isInteger, boolean parseAttr) {
1325        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
1326            // compute the plural category from the digitList plus other settings
1327            return subformat(currencyPluralInfo.select(getFixedDecimal(number)),
1328                             result, fieldPosition, isNegative,
1329                             isInteger, parseAttr);
1330        } else {
1331            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
1332        }
1333    }
1334
1335    private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition,
1336            boolean isNegative, boolean isInteger, boolean parseAttr) {
1337        // There are 2 ways to activate currency plural format: by applying a pattern with
1338        // 3 currency sign directly, or by instantiate a decimal formatter using
1339        // PLURALCURRENCYSTYLE.  For both cases, the number of currency sign in the
1340        // pattern is 3.  Even if the number of currency sign in the pattern is 3, it does
1341        // not mean we need to reset the pattern.  For 1st case, we do not need to reset
1342        // pattern.  For 2nd case, we might need to reset pattern, if the default pattern
1343        // (corresponding to plural count 'other') we use is different from the pattern
1344        // based on 'pluralCount'.
1345        //
1346        // style is only valid when decimal formatter is constructed through
1347        // DecimalFormat(pattern, symbol, style)
1348        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
1349            // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
1350            String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
1351            if (formatPattern.equals(currencyPluralPattern) == false) {
1352                applyPatternWithoutExpandAffix(currencyPluralPattern, false);
1353            }
1354        }
1355        // Expand the affix to the right name according to the plural rule.  This is only
1356        // used for currency plural formatting.  Currency plural name is not a fixed
1357        // static one, it is a dynamic name based on the currency plural count.  So, the
1358        // affixes need to be expanded here.  For other cases, the affix is a static one
1359        // based on pattern alone, and it is already expanded during applying pattern, or
1360        // setDecimalFormatSymbols, or setCurrency.
1361        expandAffixAdjustWidth(pluralCount);
1362        return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
1363    }
1364
1365    /**
1366     * Complete the formatting of a finite number. On entry, the
1367     * digitList must be filled in with the correct digits.
1368     */
1369    private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,
1370                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
1371        // NOTE: This isn't required anymore because DigitList takes care of this.
1372        //
1373        // // The negative of the exponent represents the number of leading // zeros
1374        // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g.,
1375        // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction
1376        // digits, then we have an underflow // for the printed representation. We
1377        // recognize this here and set // the DigitList representation to zero in this
1378        // situation.
1379        //
1380        // if (-digitList.decimalAt >= getMaximumFractionDigits())
1381        // {
1382        // digitList.count = 0;
1383        // }
1384
1385
1386
1387        // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as
1388        // zero. This allows sensible computations and preserves relations such as
1389        // signum(1/x) = signum(x), where x is +Infinity or -Infinity.  Prior to this fix,
1390        // we always formatted zero values as if they were positive. Liu 7/6/98.
1391        if (digitList.isZero()) {
1392            digitList.decimalAt = 0; // Normalize
1393        }
1394
1395        int prefixLen = appendAffix(result, isNegative, true, fieldPosition, parseAttr);
1396
1397        if (useExponentialNotation) {
1398            subformatExponential(result, fieldPosition, parseAttr);
1399        } else {
1400            subformatFixed(result, fieldPosition, isInteger, parseAttr);
1401        }
1402
1403        int suffixLen = appendAffix(result, isNegative, false, fieldPosition, parseAttr);
1404        addPadding(result, fieldPosition, prefixLen, suffixLen);
1405        return result;
1406    }
1407
1408    private void subformatFixed(StringBuffer result,
1409            FieldPosition fieldPosition,
1410            boolean isInteger,
1411            boolean parseAttr) {
1412        String[] digits = symbols.getDigitStrings();
1413
1414        String grouping = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
1415                symbols.getGroupingSeparatorString(): symbols.getMonetaryGroupingSeparatorString();
1416        String decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
1417                symbols.getDecimalSeparatorString() : symbols.getMonetaryDecimalSeparatorString();
1418        boolean useSigDig = areSignificantDigitsUsed();
1419        int maxIntDig = getMaximumIntegerDigits();
1420        int minIntDig = getMinimumIntegerDigits();
1421        int i;
1422        // [Spark/CDL] Record the integer start index.
1423        int intBegin = result.length();
1424        // Record field information for caller.
1425        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD ||
1426                fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1427            fieldPosition.setBeginIndex(intBegin);
1428        }
1429        long fractionalDigits = 0;
1430        int fractionalDigitsCount = 0;
1431        boolean recordFractionDigits = false;
1432
1433        int sigCount = 0;
1434        int minSigDig = getMinimumSignificantDigits();
1435        int maxSigDig = getMaximumSignificantDigits();
1436        if (!useSigDig) {
1437            minSigDig = 0;
1438            maxSigDig = Integer.MAX_VALUE;
1439        }
1440
1441        // Output the integer portion. Here 'count' is the total number of integer
1442        // digits we will display, including both leading zeros required to satisfy
1443        // getMinimumIntegerDigits, and actual digits present in the number.
1444        int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig;
1445        if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
1446            count = digitList.decimalAt;
1447        }
1448
1449        // Handle the case where getMaximumIntegerDigits() is smaller than the real
1450        // number of integer digits. If this is so, we output the least significant
1451        // max integer digits. For example, the value 1997 printed with 2 max integer
1452        // digits is just "97".
1453
1454        int digitIndex = 0; // Index into digitList.fDigits[]
1455        if (count > maxIntDig && maxIntDig >= 0) {
1456            count = maxIntDig;
1457            digitIndex = digitList.decimalAt - count;
1458        }
1459
1460        int sizeBeforeIntegerPart = result.length();
1461        for (i = count - 1; i >= 0; --i) {
1462            if (i < digitList.decimalAt && digitIndex < digitList.count
1463                && sigCount < maxSigDig) {
1464                // Output a real digit
1465                result.append(digits[digitList.getDigitValue(digitIndex++)]);
1466                ++sigCount;
1467            } else {
1468                // Output a zero (leading or trailing)
1469                result.append(digits[0]);
1470                if (sigCount > 0) {
1471                    ++sigCount;
1472                }
1473            }
1474
1475            // Output grouping separator if necessary.
1476            if (isGroupingPosition(i)) {
1477                result.append(grouping);
1478                // [Spark/CDL] Add grouping separator attribute here.
1479                // Set only for the first instance.
1480                // Length of grouping separator is 1.
1481                if (fieldPosition.getFieldAttribute() == Field.GROUPING_SEPARATOR &&
1482                        fieldPosition.getBeginIndex() == 0 && fieldPosition.getEndIndex() == 0) {
1483                    fieldPosition.setBeginIndex(result.length()-1);
1484                    fieldPosition.setEndIndex(result.length());
1485                }
1486                if (parseAttr) {
1487                    addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
1488                }
1489            }
1490        }
1491
1492        // Record field information for caller.
1493        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD ||
1494                fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1495            fieldPosition.setEndIndex(result.length());
1496        }
1497
1498        // This handles the special case of formatting 0. For zero only, we count the
1499        // zero to the left of the decimal point as one signficant digit. Ordinarily we
1500        // do not count any leading 0's as significant. If the number we are formatting
1501        // is not zero, then either sigCount or digits.getCount() will be non-zero.
1502        if (sigCount == 0 && digitList.count == 0) {
1503          sigCount = 1;
1504        }
1505
1506        // Determine whether or not there are any printable fractional digits. If
1507        // we've used up the digits we know there aren't.
1508        boolean fractionPresent = (!isInteger && digitIndex < digitList.count)
1509                || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
1510
1511        // If there is no fraction present, and we haven't printed any integer digits,
1512        // then print a zero. Otherwise we won't print _any_ digits, and we won't be
1513        // able to parse this string.
1514        if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
1515            result.append(digits[0]);
1516        // [Spark/CDL] Add attribute for integer part.
1517        if (parseAttr) {
1518            addAttribute(Field.INTEGER, intBegin, result.length());
1519        }
1520        // Output the decimal separator if we always do so.
1521        if (decimalSeparatorAlwaysShown || fractionPresent) {
1522            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
1523                fieldPosition.setBeginIndex(result.length());
1524            }
1525            result.append(decimal);
1526            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
1527                fieldPosition.setEndIndex(result.length());
1528            }
1529            // [Spark/CDL] Add attribute for decimal separator
1530            if (parseAttr) {
1531                addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length());
1532            }
1533        }
1534
1535        // Record field information for caller.
1536        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1537            fieldPosition.setBeginIndex(result.length());
1538        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1539            fieldPosition.setBeginIndex(result.length());
1540        }
1541
1542        // [Spark/CDL] Record the begin index of fraction part.
1543        int fracBegin = result.length();
1544        recordFractionDigits = fieldPosition instanceof UFieldPosition;
1545
1546        count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
1547        if (useSigDig && (sigCount == maxSigDig ||
1548                          (sigCount >= minSigDig && digitIndex == digitList.count))) {
1549            count = 0;
1550        }
1551        for (i = 0; i < count; ++i) {
1552            // Here is where we escape from the loop. We escape if we've output the
1553            // maximum fraction digits (specified in the for expression above). We
1554            // also stop when we've output the minimum digits and either: we have an
1555            // integer, so there is no fractional stuff to display, or we're out of
1556            // significant digits.
1557            if (!useSigDig && i >= getMinimumFractionDigits() &&
1558                (isInteger || digitIndex >= digitList.count)) {
1559                break;
1560            }
1561
1562            // Output leading fractional zeros. These are zeros that come after the
1563            // decimal but before any significant digits. These are only output if
1564            // abs(number being formatted) < 1.0.
1565            if (-1 - i > (digitList.decimalAt - 1)) {
1566                result.append(digits[0]);
1567                if (recordFractionDigits) {
1568                    ++fractionalDigitsCount;
1569                    fractionalDigits *= 10;
1570                }
1571                continue;
1572            }
1573
1574            // Output a digit, if we have any precision left, or a zero if we
1575            // don't. We don't want to output noise digits.
1576            if (!isInteger && digitIndex < digitList.count) {
1577                byte digit = digitList.getDigitValue(digitIndex++);
1578                result.append(digits[digit]);
1579                if (recordFractionDigits) {
1580                    ++fractionalDigitsCount;
1581                    fractionalDigits *= 10;
1582                    fractionalDigits += digit;
1583                }
1584            } else {
1585                result.append(digits[0]);
1586                if (recordFractionDigits) {
1587                    ++fractionalDigitsCount;
1588                    fractionalDigits *= 10;
1589                }
1590            }
1591
1592            // If we reach the maximum number of significant digits, or if we output
1593            // all the real digits and reach the minimum, then we are done.
1594            ++sigCount;
1595            if (useSigDig && (sigCount == maxSigDig ||
1596                              (digitIndex == digitList.count && sigCount >= minSigDig))) {
1597                break;
1598            }
1599        }
1600
1601        // Record field information for caller.
1602        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1603            fieldPosition.setEndIndex(result.length());
1604        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1605            fieldPosition.setEndIndex(result.length());
1606        }
1607        if (recordFractionDigits) {
1608            ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
1609        }
1610
1611        // [Spark/CDL] Add attribute information if necessary.
1612        if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
1613            addAttribute(Field.FRACTION, fracBegin, result.length());
1614        }
1615    }
1616
1617    private void subformatExponential(StringBuffer result,
1618            FieldPosition fieldPosition,
1619            boolean parseAttr) {
1620        String[] digits = symbols.getDigitStringsLocal();
1621        String decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
1622                symbols.getDecimalSeparatorString() : symbols.getMonetaryDecimalSeparatorString();
1623        boolean useSigDig = areSignificantDigitsUsed();
1624        int maxIntDig = getMaximumIntegerDigits();
1625        int minIntDig = getMinimumIntegerDigits();
1626        int i;
1627        // Record field information for caller.
1628        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1629            fieldPosition.setBeginIndex(result.length());
1630            fieldPosition.setEndIndex(-1);
1631        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1632            fieldPosition.setBeginIndex(-1);
1633        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1634            fieldPosition.setBeginIndex(result.length());
1635            fieldPosition.setEndIndex(-1);
1636        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1637            fieldPosition.setBeginIndex(-1);
1638        }
1639
1640        // [Spark/CDL]
1641        // the begin index of integer part
1642        // the end index of integer part
1643        // the begin index of fractional part
1644        int intBegin = result.length();
1645        int intEnd = -1;
1646        int fracBegin = -1;
1647        int minFracDig = 0;
1648        if (useSigDig) {
1649            maxIntDig = minIntDig = 1;
1650            minFracDig = getMinimumSignificantDigits() - 1;
1651        } else {
1652            minFracDig = getMinimumFractionDigits();
1653            if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
1654                maxIntDig = 1;
1655                if (maxIntDig < minIntDig) {
1656                    maxIntDig = minIntDig;
1657                }
1658            }
1659            if (maxIntDig > minIntDig) {
1660                minIntDig = 1;
1661            }
1662        }
1663        long fractionalDigits = 0;
1664        int fractionalDigitsCount = 0;
1665        boolean recordFractionDigits = false;
1666
1667        // Minimum integer digits are handled in exponential format by adjusting the
1668        // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".
1669
1670        // Maximum integer digits are interpreted as indicating the repeating
1671        // range. This is useful for engineering notation, in which the exponent is
1672        // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer
1673        // digits is "12.34e-3".  If maximum integer digits are defined and are larger
1674        // than minimum integer digits, then minimum integer digits are ignored.
1675
1676        int exponent = digitList.decimalAt;
1677        if (maxIntDig > 1 && maxIntDig != minIntDig) {
1678            // A exponent increment is defined; adjust to it.
1679            exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1;
1680            exponent *= maxIntDig;
1681        } else {
1682            // No exponent increment is defined; use minimum integer digits.
1683            // If none is specified, as in "#E0", generate 1 integer digit.
1684            exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1;
1685        }
1686
1687        // We now output a minimum number of digits, and more if there are more
1688        // digits, up to the maximum number of digits. We place the decimal point
1689        // after the "integer" digits, which are the first (decimalAt - exponent)
1690        // digits.
1691        int minimumDigits = minIntDig + minFracDig;
1692        // The number of integer digits is handled specially if the number
1693        // is zero, since then there may be no digits.
1694        int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent;
1695        int totalDigits = digitList.count;
1696        if (minimumDigits > totalDigits)
1697            totalDigits = minimumDigits;
1698        if (integerDigits > totalDigits)
1699            totalDigits = integerDigits;
1700
1701        for (i = 0; i < totalDigits; ++i) {
1702            if (i == integerDigits) {
1703                // Record field information for caller.
1704                if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1705                    fieldPosition.setEndIndex(result.length());
1706                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1707                    fieldPosition.setEndIndex(result.length());
1708                }
1709
1710                // [Spark/CDL] Add attribute for integer part
1711                if (parseAttr) {
1712                    intEnd = result.length();
1713                    addAttribute(Field.INTEGER, intBegin, result.length());
1714                }
1715                if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
1716                    fieldPosition.setBeginIndex(result.length());
1717                }
1718                result.append(decimal);
1719                if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
1720                    fieldPosition.setEndIndex(result.length());
1721                }
1722                // [Spark/CDL] Add attribute for decimal separator
1723                fracBegin = result.length();
1724                if (parseAttr) {
1725                    // Length of decimal separator is 1.
1726                    int decimalSeparatorBegin = result.length() - 1;
1727                    addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin,
1728                                 result.length());
1729                }
1730                // Record field information for caller.
1731                if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1732                    fieldPosition.setBeginIndex(result.length());
1733                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1734                    fieldPosition.setBeginIndex(result.length());
1735                }
1736                recordFractionDigits = fieldPosition instanceof UFieldPosition;
1737
1738            }
1739            byte digit = (i < digitList.count) ? digitList.getDigitValue(i) : (byte)0;
1740            result.append(digits[digit]);
1741            if (recordFractionDigits) {
1742                ++fractionalDigitsCount;
1743                fractionalDigits *= 10;
1744                fractionalDigits += digit;
1745            }
1746        }
1747
1748        // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
1749        if (digitList.isZero() && (totalDigits == 0)) {
1750            result.append(digits[0]);
1751        }
1752
1753        // add the decimal separator if it is to be always shown AND there are no decimal digits
1754        if ((fracBegin == -1) && this.decimalSeparatorAlwaysShown) {
1755            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
1756                fieldPosition.setBeginIndex(result.length());
1757            }
1758            result.append(decimal);
1759            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
1760                fieldPosition.setEndIndex(result.length());
1761            }
1762            if (parseAttr) {
1763                // Length of decimal separator is 1.
1764                int decimalSeparatorBegin = result.length() - 1;
1765                addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin, result.length());
1766            }
1767        }
1768
1769        // Record field information
1770        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
1771            if (fieldPosition.getEndIndex() < 0) {
1772                fieldPosition.setEndIndex(result.length());
1773            }
1774        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
1775            if (fieldPosition.getBeginIndex() < 0) {
1776                fieldPosition.setBeginIndex(result.length());
1777            }
1778            fieldPosition.setEndIndex(result.length());
1779        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
1780            if (fieldPosition.getEndIndex() < 0) {
1781                fieldPosition.setEndIndex(result.length());
1782            }
1783        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
1784            if (fieldPosition.getBeginIndex() < 0) {
1785                fieldPosition.setBeginIndex(result.length());
1786            }
1787            fieldPosition.setEndIndex(result.length());
1788        }
1789        if (recordFractionDigits) {
1790            ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
1791        }
1792
1793        // [Spark/CDL] Calculate the end index of integer part and fractional
1794        // part if they are not properly processed yet.
1795        if (parseAttr) {
1796            if (intEnd < 0) {
1797                addAttribute(Field.INTEGER, intBegin, result.length());
1798            }
1799            if (fracBegin > 0) {
1800                addAttribute(Field.FRACTION, fracBegin, result.length());
1801            }
1802        }
1803
1804        // The exponent is output using the pattern-specified minimum exponent
1805        // digits. There is no maximum limit to the exponent digits, since truncating
1806        // the exponent would result in an unacceptable inaccuracy.
1807        if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
1808            fieldPosition.setBeginIndex(result.length());
1809        }
1810
1811        result.append(symbols.getExponentSeparator());
1812        if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
1813            fieldPosition.setEndIndex(result.length());
1814        }
1815        // [Spark/CDL] For exponent symbol, add an attribute.
1816        if (parseAttr) {
1817            addAttribute(Field.EXPONENT_SYMBOL, result.length() -
1818                         symbols.getExponentSeparator().length(), result.length());
1819        }
1820        // For zero values, we force the exponent to zero. We must do this here, and
1821        // not earlier, because the value is used to determine integer digit count
1822        // above.
1823        if (digitList.isZero())
1824            exponent = 0;
1825
1826        boolean negativeExponent = exponent < 0;
1827        if (negativeExponent) {
1828            exponent = -exponent;
1829            if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
1830                fieldPosition.setBeginIndex(result.length());
1831            }
1832            result.append(symbols.getMinusSignString());
1833            if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
1834                fieldPosition.setEndIndex(result.length());
1835            }
1836            // [Spark/CDL] If exponent has sign, then add an exponent sign
1837            // attribute.
1838            if (parseAttr) {
1839                // Length of exponent sign is 1.
1840                addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
1841            }
1842        } else if (exponentSignAlwaysShown) {
1843            if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
1844                fieldPosition.setBeginIndex(result.length());
1845            }
1846            result.append(symbols.getPlusSignString());
1847            if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
1848                fieldPosition.setEndIndex(result.length());
1849            }
1850            // [Spark/CDL] Add an plus sign attribute.
1851            if (parseAttr) {
1852                // Length of exponent sign is 1.
1853                int expSignBegin = result.length() - 1;
1854                addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length());
1855            }
1856        }
1857        int expBegin = result.length();
1858        digitList.set(exponent);
1859        {
1860            int expDig = minExponentDigits;
1861            if (useExponentialNotation && expDig < 1) {
1862                expDig = 1;
1863            }
1864            for (i = digitList.decimalAt; i < expDig; ++i)
1865                result.append(digits[0]);
1866        }
1867        for (i = 0; i < digitList.decimalAt; ++i) {
1868            result.append((i < digitList.count) ? digits[digitList.getDigitValue(i)]
1869                          : digits[0]);
1870        }
1871        // [Spark/CDL] Add attribute for exponent part.
1872        if (fieldPosition.getFieldAttribute() == Field.EXPONENT) {
1873            fieldPosition.setBeginIndex(expBegin);
1874            fieldPosition.setEndIndex(result.length());
1875        }
1876        if (parseAttr) {
1877            addAttribute(Field.EXPONENT, expBegin, result.length());
1878        }
1879    }
1880
1881    private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen,
1882                                  int suffixLen) {
1883        if (formatWidth > 0) {
1884            int len = formatWidth - result.length();
1885            if (len > 0) {
1886                char[] padding = new char[len];
1887                for (int i = 0; i < len; ++i) {
1888                    padding[i] = pad;
1889                }
1890                switch (padPosition) {
1891                case PAD_AFTER_PREFIX:
1892                    result.insert(prefixLen, padding);
1893                    break;
1894                case PAD_BEFORE_PREFIX:
1895                    result.insert(0, padding);
1896                    break;
1897                case PAD_BEFORE_SUFFIX:
1898                    result.insert(result.length() - suffixLen, padding);
1899                    break;
1900                case PAD_AFTER_SUFFIX:
1901                    result.append(padding);
1902                    break;
1903                }
1904                if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) {
1905                    fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
1906                    fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
1907                }
1908            }
1909        }
1910    }
1911
1912    /**
1913     * Parses the given string, returning a <code>Number</code> object to represent the
1914     * parsed value. <code>Double</code> objects are returned to represent non-integral
1915     * values which cannot be stored in a <code>BigDecimal</code>. These are
1916     * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
1917     * false (the default), all other values are returned as <code>Long</code>,
1918     * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
1919     * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
1920     * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
1921     *
1922     * @param text the string to be parsed
1923     * @param parsePosition defines the position where parsing is to begin, and upon
1924     * return, the position where parsing left off. If the position has not changed upon
1925     * return, then parsing failed.
1926     * @return a <code>Number</code> object with the parsed value or
1927     * <code>null</code> if the parse failed
1928     */
1929    @Override
1930    public Number parse(String text, ParsePosition parsePosition) {
1931        return (Number) parse(text, parsePosition, null);
1932    }
1933
1934    /**
1935     * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
1936     * this method will attempt to parse a generic currency name, searching for a match of
1937     * this object's locale's currency display names, or for a 3-letter ISO currency
1938     * code. This method will fail if this format is not a currency format, that is, if it
1939     * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
1940     *
1941     * @param text the text to parse
1942     * @param pos input-output position; on input, the position within text to match; must
1943     *  have 0 &lt;= pos.getIndex() &lt; text.length(); on output, the position after the last
1944     *  matched character. If the parse fails, the position in unchanged upon output.
1945     * @return a CurrencyAmount, or null upon failure
1946     */
1947    @Override
1948    public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) {
1949        Currency[] currency = new Currency[1];
1950        return (CurrencyAmount) parse(text.toString(), pos, currency);
1951    }
1952
1953    /**
1954     * Parses the given text as either a Number or a CurrencyAmount.
1955     *
1956     * @param text the string to parse
1957     * @param parsePosition input-output position; on input, the position within text to
1958     * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after
1959     * the last matched character. If the parse fails, the position in unchanged upon
1960     * output.
1961     * @param currency if non-null, a CurrencyAmount is parsed and returned; otherwise a
1962     * Number is parsed and returned
1963     * @return a Number or CurrencyAmount or null
1964     */
1965    private Object parse(String text, ParsePosition parsePosition, Currency[] currency) {
1966        int backup;
1967        int i = backup = parsePosition.getIndex();
1968
1969        // Handle NaN as a special case:
1970
1971        // Skip padding characters, if around prefix
1972        if (formatWidth > 0 &&
1973            (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {
1974            i = skipPadding(text, i);
1975        }
1976        if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) {
1977            i += symbols.getNaN().length();
1978            // Skip padding characters, if around suffix
1979            if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
1980                                    padPosition == PAD_AFTER_SUFFIX)) {
1981                i = skipPadding(text, i);
1982            }
1983            parsePosition.setIndex(i);
1984            return new Double(Double.NaN);
1985        }
1986
1987        // NaN parse failed; start over
1988        i = backup;
1989
1990        boolean[] status = new boolean[STATUS_LENGTH];
1991        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
1992            if (!parseForCurrency(text, parsePosition, currency, status)) {
1993                return null;
1994            }
1995        } else if (currency != null) {
1996            return null;
1997        } else {
1998            if (!subparse(text, parsePosition, digitList, status, currency, negPrefixPattern,
1999                          negSuffixPattern, posPrefixPattern, posSuffixPattern,
2000                          false, Currency.SYMBOL_NAME)) {
2001                parsePosition.setIndex(backup);
2002                return null;
2003            }
2004        }
2005
2006        Number n = null;
2007
2008        // Handle infinity
2009        if (status[STATUS_INFINITE]) {
2010            n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY :
2011                           Double.NEGATIVE_INFINITY);
2012        }
2013
2014        // Handle underflow
2015        else if (status[STATUS_UNDERFLOW]) {
2016            n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
2017        }
2018
2019        // Handle -0.0
2020        else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
2021            n = new Double("-0.0");
2022        }
2023
2024        else {
2025            // Do as much of the multiplier conversion as possible without
2026            // losing accuracy.
2027            int mult = multiplier; // Don't modify this.multiplier
2028            while (mult % 10 == 0) {
2029                --digitList.decimalAt;
2030                mult /= 10;
2031            }
2032
2033            // Handle integral values
2034            if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
2035                // hack quick long
2036                if (digitList.decimalAt < 12) { // quick check for long
2037                    long l = 0;
2038                    if (digitList.count > 0) {
2039                        int nx = 0;
2040                        while (nx < digitList.count) {
2041                            l = l * 10 + (char) digitList.digits[nx++] - '0';
2042                        }
2043                        while (nx++ < digitList.decimalAt) {
2044                            l *= 10;
2045                        }
2046                        if (!status[STATUS_POSITIVE]) {
2047                            l = -l;
2048                        }
2049                    }
2050                    n = Long.valueOf(l);
2051                } else {
2052                    BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
2053                    n = (big.bitLength() < 64) ? (Number) Long.valueOf(big.longValue()) : (Number) big;
2054                }
2055            }
2056            // Handle non-integral values or the case where parseBigDecimal is set
2057            else {
2058                BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
2059                n = big;
2060                if (mult != 1) {
2061                    n = big.divide(BigDecimal.valueOf(mult), mathContext);
2062                }
2063            }
2064        }
2065
2066        // Assemble into CurrencyAmount if necessary
2067        return (currency != null) ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n;
2068    }
2069
2070    private boolean parseForCurrency(String text, ParsePosition parsePosition,
2071            Currency[] currency, boolean[] status) {
2072        int origPos = parsePosition.getIndex();
2073        if (!isReadyForParsing) {
2074            int savedCurrencySignCount = currencySignCount;
2075            setupCurrencyAffixForAllPatterns();
2076            // reset pattern back
2077            if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
2078                applyPatternWithoutExpandAffix(formatPattern, false);
2079            } else {
2080                applyPattern(formatPattern, false);
2081            }
2082            isReadyForParsing = true;
2083        }
2084        int maxPosIndex = origPos;
2085        int maxErrorPos = -1;
2086        boolean[] savedStatus = null;
2087        // First, parse against current pattern.
2088        // Since current pattern could be set by applyPattern(),
2089        // it could be an arbitrary pattern, and it may not be the one
2090        // defined in current locale.
2091        boolean[] tmpStatus = new boolean[STATUS_LENGTH];
2092        ParsePosition tmpPos = new ParsePosition(origPos);
2093        DigitList tmpDigitList = new DigitList();
2094        boolean found;
2095        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
2096            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
2097                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
2098                             true, Currency.LONG_NAME);
2099        } else {
2100            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
2101                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
2102                             true, Currency.SYMBOL_NAME);
2103        }
2104        if (found) {
2105            if (tmpPos.getIndex() > maxPosIndex) {
2106                maxPosIndex = tmpPos.getIndex();
2107                savedStatus = tmpStatus;
2108                digitList = tmpDigitList;
2109            }
2110        } else {
2111            maxErrorPos = tmpPos.getErrorIndex();
2112        }
2113        // Then, parse against affix patterns.  Those are currency patterns and currency
2114        // plural patterns defined in the locale.
2115        for (AffixForCurrency affix : affixPatternsForCurrency) {
2116            tmpStatus = new boolean[STATUS_LENGTH];
2117            tmpPos = new ParsePosition(origPos);
2118            tmpDigitList = new DigitList();
2119            boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
2120                                      affix.getNegPrefix(), affix.getNegSuffix(),
2121                                      affix.getPosPrefix(), affix.getPosSuffix(),
2122                                      true, affix.getPatternType());
2123            if (result) {
2124                found = true;
2125                if (tmpPos.getIndex() > maxPosIndex) {
2126                    maxPosIndex = tmpPos.getIndex();
2127                    savedStatus = tmpStatus;
2128                    digitList = tmpDigitList;
2129                }
2130            } else {
2131                maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex()
2132                    : maxErrorPos;
2133            }
2134        }
2135        // Finally, parse against simple affix to find the match.  For example, in
2136        // TestMonster suite, if the to-be-parsed text is "-\u00A40,00".
2137        // complexAffixCompare will not find match, since there is no ISO code matches
2138        // "\u00A4", and the parse stops at "\u00A4".  We will just use simple affix
2139        // comparison (look for exact match) to pass it.
2140        //
2141        // TODO: We should parse against simple affix first when
2142        // output currency is not requested. After the complex currency
2143        // parsing implementation was introduced, the default currency
2144        // instance parsing slowed down because of the new code flow.
2145        // I filed #10312 - Yoshito
2146        tmpStatus = new boolean[STATUS_LENGTH];
2147        tmpPos = new ParsePosition(origPos);
2148        tmpDigitList = new DigitList();
2149
2150        // Disable complex currency parsing and try it again.
2151        boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
2152                                  negativePrefix, negativeSuffix, positivePrefix, positiveSuffix,
2153                                  false /* disable complex currency parsing */, Currency.SYMBOL_NAME);
2154        if (result) {
2155            if (tmpPos.getIndex() > maxPosIndex) {
2156                maxPosIndex = tmpPos.getIndex();
2157                savedStatus = tmpStatus;
2158                digitList = tmpDigitList;
2159            }
2160            found = true;
2161        } else {
2162            maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() :
2163                maxErrorPos;
2164        }
2165
2166        if (!found) {
2167            // parsePosition.setIndex(origPos);
2168            parsePosition.setErrorIndex(maxErrorPos);
2169        } else {
2170            parsePosition.setIndex(maxPosIndex);
2171            parsePosition.setErrorIndex(-1);
2172            for (int index = 0; index < STATUS_LENGTH; ++index) {
2173                status[index] = savedStatus[index];
2174            }
2175        }
2176        return found;
2177    }
2178
2179    // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and
2180    // currency plural pattern (CurrencyUnitPatterns).
2181    private void setupCurrencyAffixForAllPatterns() {
2182        if (currencyPluralInfo == null) {
2183            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
2184        }
2185        affixPatternsForCurrency = new HashSet<AffixForCurrency>();
2186
2187        // save the current pattern, since it will be changed by
2188        // applyPatternWithoutExpandAffix
2189        String savedFormatPattern = formatPattern;
2190
2191        // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so,
2192        // only need to save one of them.  Here, chose onlyApplyPatternWithoutExpandAffix
2193        // without saving the actualy pattern in 'pattern' data member.  TODO: is it uloc?
2194        applyPatternWithoutExpandAffix(getPattern(symbols.getULocale(), NumberFormat.CURRENCYSTYLE),
2195                                       false);
2196        AffixForCurrency affixes = new AffixForCurrency(
2197            negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
2198            Currency.SYMBOL_NAME);
2199        affixPatternsForCurrency.add(affixes);
2200
2201        // add plural pattern
2202        Iterator<String> iter = currencyPluralInfo.pluralPatternIterator();
2203        Set<String> currencyUnitPatternSet = new HashSet<String>();
2204        while (iter.hasNext()) {
2205            String pluralCount = iter.next();
2206            String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
2207            if (currencyPattern != null &&
2208                currencyUnitPatternSet.contains(currencyPattern) == false) {
2209                currencyUnitPatternSet.add(currencyPattern);
2210                applyPatternWithoutExpandAffix(currencyPattern, false);
2211                affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern,
2212                                               posSuffixPattern, Currency.LONG_NAME);
2213                affixPatternsForCurrency.add(affixes);
2214            }
2215        }
2216        // reset pattern back
2217        formatPattern = savedFormatPattern;
2218    }
2219
2220    // currency formatting style options
2221    private static final int CURRENCY_SIGN_COUNT_ZERO = 0;
2222    private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
2223    private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
2224    private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;
2225
2226    private static final int STATUS_INFINITE = 0;
2227    private static final int STATUS_POSITIVE = 1;
2228    private static final int STATUS_UNDERFLOW = 2;
2229    private static final int STATUS_LENGTH = 3;
2230
2231    private static final UnicodeSet dotEquivalents = new UnicodeSet(
2232            //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]"
2233            0x002E, 0x002E,
2234            0x2024, 0x2024,
2235            0x3002, 0x3002,
2236            0xFE12, 0xFE12,
2237            0xFE52, 0xFE52,
2238            0xFF0E, 0xFF0E,
2239            0xFF61, 0xFF61).freeze();
2240
2241    private static final UnicodeSet commaEquivalents = new UnicodeSet(
2242            //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]"
2243            0x002C, 0x002C,
2244            0x060C, 0x060C,
2245            0x066B, 0x066B,
2246            0x3001, 0x3001,
2247            0xFE10, 0xFE11,
2248            0xFE50, 0xFE51,
2249            0xFF0C, 0xFF0C,
2250            0xFF64, 0xFF64).freeze();
2251
2252//    private static final UnicodeSet otherGroupingSeparators = new UnicodeSet(
2253//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
2254//            0x0020, 0x0020,
2255//            0x0027, 0x0027,
2256//            0x00A0, 0x00A0,
2257//            0x066C, 0x066C,
2258//            0x2000, 0x200A,
2259//            0x2018, 0x2019,
2260//            0x202F, 0x202F,
2261//            0x205F, 0x205F,
2262//            0x3000, 0x3000,
2263//            0xFF07, 0xFF07).freeze();
2264
2265    private static final UnicodeSet strictDotEquivalents = new UnicodeSet(
2266            //"[.\u2024\uFE52\uFF0E\uFF61]"
2267            0x002E, 0x002E,
2268            0x2024, 0x2024,
2269            0xFE52, 0xFE52,
2270            0xFF0E, 0xFF0E,
2271            0xFF61, 0xFF61).freeze();
2272
2273    private static final UnicodeSet strictCommaEquivalents = new UnicodeSet(
2274            //"[,\u066B\uFE10\uFE50\uFF0C]"
2275            0x002C, 0x002C,
2276            0x066B, 0x066B,
2277            0xFE10, 0xFE10,
2278            0xFE50, 0xFE50,
2279            0xFF0C, 0xFF0C).freeze();
2280
2281//    private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet(
2282//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
2283//            0x0020, 0x0020,
2284//            0x0027, 0x0027,
2285//            0x00A0, 0x00A0,
2286//            0x066C, 0x066C,
2287//            0x2000, 0x200A,
2288//            0x2018, 0x2019,
2289//            0x202F, 0x202F,
2290//            0x205F, 0x205F,
2291//            0x3000, 0x3000,
2292//            0xFF07, 0xFF07).freeze();
2293
2294    private static final UnicodeSet defaultGroupingSeparators =
2295        // new UnicodeSet(dotEquivalents).addAll(commaEquivalents)
2296        //     .addAll(otherGroupingSeparators).freeze();
2297        new UnicodeSet(
2298                0x0020, 0x0020,
2299                0x0027, 0x0027,
2300                0x002C, 0x002C,
2301                0x002E, 0x002E,
2302                0x00A0, 0x00A0,
2303                0x060C, 0x060C,
2304                0x066B, 0x066C,
2305                0x2000, 0x200A,
2306                0x2018, 0x2019,
2307                0x2024, 0x2024,
2308                0x202F, 0x202F,
2309                0x205F, 0x205F,
2310                0x3000, 0x3002,
2311                0xFE10, 0xFE12,
2312                0xFE50, 0xFE52,
2313                0xFF07, 0xFF07,
2314                0xFF0C, 0xFF0C,
2315                0xFF0E, 0xFF0E,
2316                0xFF61, 0xFF61,
2317                0xFF64, 0xFF64).freeze();
2318
2319    private static final UnicodeSet strictDefaultGroupingSeparators =
2320        // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents)
2321        //     .addAll(strictOtherGroupingSeparators).freeze();
2322        new UnicodeSet(
2323                0x0020, 0x0020,
2324                0x0027, 0x0027,
2325                0x002C, 0x002C,
2326                0x002E, 0x002E,
2327                0x00A0, 0x00A0,
2328                0x066B, 0x066C,
2329                0x2000, 0x200A,
2330                0x2018, 0x2019,
2331                0x2024, 0x2024,
2332                0x202F, 0x202F,
2333                0x205F, 0x205F,
2334                0x3000, 0x3000,
2335                0xFE10, 0xFE10,
2336                0xFE50, 0xFE50,
2337                0xFE52, 0xFE52,
2338                0xFF07, 0xFF07,
2339                0xFF0C, 0xFF0C,
2340                0xFF0E, 0xFF0E,
2341                0xFF61, 0xFF61).freeze();
2342
2343    static final UnicodeSet minusSigns =
2344        new UnicodeSet(
2345                0x002D, 0x002D,
2346                0x207B, 0x207B,
2347                0x208B, 0x208B,
2348                0x2212, 0x2212,
2349                0x2796, 0x2796,
2350                0xFE63, 0xFE63,
2351                0xFF0D, 0xFF0D).freeze();
2352
2353    static final UnicodeSet plusSigns =
2354            new UnicodeSet(
2355                0x002B, 0x002B,
2356                0x207A, 0x207A,
2357                0x208A, 0x208A,
2358                0x2795, 0x2795,
2359                0xFB29, 0xFB29,
2360                0xFE62, 0xFE62,
2361                0xFF0B, 0xFF0B).freeze();
2362
2363    // equivalent grouping and decimal support
2364    static final boolean skipExtendedSeparatorParsing = ICUConfig.get(
2365        "android.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
2366        .equals("true");
2367
2368    // allow control of requiring a matching decimal point when parsing
2369    boolean parseRequireDecimalPoint = false;
2370
2371    // When parsing a number with big exponential value, it requires to transform the
2372    // value into a string representation to construct BigInteger instance.  We want to
2373    // set the maximum size because it can easily trigger OutOfMemoryException.
2374    // PARSE_MAX_EXPONENT is currently set to 1000 (See getParseMaxDigits()),
2375    // which is much bigger than MAX_VALUE of Double ( See the problem reported by ticket#5698
2376    private int PARSE_MAX_EXPONENT = 1000;
2377
2378    /**
2379     * Parses the given text into a number. The text is parsed beginning at parsePosition,
2380     * until an unparseable character is seen.
2381     *
2382     * @param text the string to parse.
2383     * @param parsePosition the position at which to being parsing. Upon return, the first
2384     * unparseable character.
2385     * @param digits the DigitList to set to the parsed value.
2386     * @param status Upon return contains boolean status flags indicating whether the
2387     * value was infinite and whether it was positive.
2388     * @param currency return value for parsed currency, for generic currency parsing
2389     * mode, or null for normal parsing. In generic currency parsing mode, any currency is
2390     * parsed, not just the currency that this formatter is set to.
2391     * @param negPrefix negative prefix pattern
2392     * @param negSuffix negative suffix pattern
2393     * @param posPrefix positive prefix pattern
2394     * @param negSuffix negative suffix pattern
2395     * @param parseComplexCurrency whether it is complex currency parsing or not.
2396     * @param type type of currency to parse against, LONG_NAME only or not.
2397     */
2398    private final boolean subparse(
2399        String text, ParsePosition parsePosition, DigitList digits,
2400        boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix,
2401        String posSuffix, boolean parseComplexCurrency, int type) {
2402
2403        int position = parsePosition.getIndex();
2404        int oldStart = parsePosition.getIndex();
2405
2406        // Match padding before prefix
2407        if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
2408            position = skipPadding(text, position);
2409        }
2410
2411        // Match positive and negative prefixes; prefer longest match.
2412        int posMatch = compareAffix(text, position, false, true, posPrefix, parseComplexCurrency, type, currency);
2413        int negMatch = compareAffix(text, position, true, true, negPrefix, parseComplexCurrency, type, currency);
2414        if (posMatch >= 0 && negMatch >= 0) {
2415            if (posMatch > negMatch) {
2416                negMatch = -1;
2417            } else if (negMatch > posMatch) {
2418                posMatch = -1;
2419            }
2420        }
2421        if (posMatch >= 0) {
2422            position += posMatch;
2423        } else if (negMatch >= 0) {
2424            position += negMatch;
2425        } else {
2426            parsePosition.setErrorIndex(position);
2427            return false;
2428        }
2429
2430        // Match padding after prefix
2431        if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
2432            position = skipPadding(text, position);
2433        }
2434
2435        // process digits or Inf, find decimal position
2436        status[STATUS_INFINITE] = false;
2437        if (text.regionMatches(position, symbols.getInfinity(), 0,
2438                                              symbols.getInfinity().length())) {
2439            position += symbols.getInfinity().length();
2440            status[STATUS_INFINITE] = true;
2441        } else {
2442            // We now have a string of digits, possibly with grouping symbols, and decimal
2443            // points. We want to process these into a DigitList.  We don't want to put a
2444            // bunch of leading zeros into the DigitList though, so we keep track of the
2445            // location of the decimal point, put only significant digits into the
2446            // DigitList, and adjust the exponent as needed.
2447
2448            digits.decimalAt = digits.count = 0;
2449            String decimal = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
2450                    symbols.getDecimalSeparatorString() : symbols.getMonetaryDecimalSeparatorString();
2451            String grouping = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
2452                    symbols.getGroupingSeparatorString() : symbols.getMonetaryGroupingSeparatorString();
2453
2454            String exponentSep = symbols.getExponentSeparator();
2455            boolean sawDecimal = false;
2456            boolean sawGrouping = false;
2457            boolean sawDigit = false;
2458            long exponent = 0; // Set to the exponent value, if any
2459
2460            // strict parsing
2461            boolean strictParse = isParseStrict();
2462            boolean strictFail = false; // did we exit with a strict parse failure?
2463            int lastGroup = -1; // where did we last see a grouping separator?
2464            int groupedDigitCount = 0;  // tracking count of digits delimited by grouping separator
2465            int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
2466
2467            UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
2468                getEquivalentDecimals(decimal, strictParse);
2469            UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
2470                (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators);
2471
2472            // We have to track digitCount ourselves, because digits.count will pin when
2473            // the maximum allowable digits is reached.
2474            int digitCount = 0;
2475
2476            int backup = -1;    // used for preserving the last confirmed position
2477            int[] parsedDigit = {-1};   // allocates int[1] for parsing a single digit
2478
2479            while (position < text.length()) {
2480                // Check if the sequence at the current position matches a decimal digit
2481                int matchLen = matchesDigit(text, position, parsedDigit);
2482                if (matchLen > 0) {
2483                    // matched a digit
2484                    // Cancel out backup setting (see grouping handler below)
2485                    if (backup != -1) {
2486                        if (strictParse) {
2487                            // comma followed by digit, so group before comma is a secondary
2488                            // group. If there was a group separator before that, the group
2489                            // must == the secondary group length, else it can be <= the the
2490                            // secondary group length.
2491                            if ((lastGroup != -1 && groupedDigitCount != gs2)
2492                                    || (lastGroup == -1 && groupedDigitCount > gs2)) {
2493                                strictFail = true;
2494                                break;
2495                            }
2496                        }
2497                        lastGroup = backup;
2498                        groupedDigitCount = 0;
2499                    }
2500
2501                    groupedDigitCount++;
2502                    position += matchLen;
2503                    backup = -1;
2504                    sawDigit = true;
2505                    if (parsedDigit[0] == 0 && digits.count == 0) {
2506                        // Handle leading zeros
2507                        if (!sawDecimal) {
2508                            // Ignore leading zeros in integer part of number.
2509                            continue;
2510                        }
2511                        // If we have seen the decimal, but no significant digits yet,
2512                        // then we account for leading zeros by decrementing the
2513                        // digits.decimalAt into negative values.
2514                        --digits.decimalAt;
2515                    } else {
2516                        ++digitCount;
2517                        digits.append((char) (parsedDigit[0] + '0'));
2518                    }
2519                    continue;
2520                }
2521
2522                // Check if the sequence at the current position matches locale's decimal separator
2523                int decimalStrLen = decimal.length();
2524                if (text.regionMatches(position, decimal, 0, decimalStrLen)) {
2525                    // matched a decimal separator
2526                    if (strictParse) {
2527                        if (backup != -1 ||
2528                            (lastGroup != -1 && groupedDigitCount != groupingSize)) {
2529                            strictFail = true;
2530                            break;
2531                        }
2532                    }
2533
2534                    // If we're only parsing integers, or if we ALREADY saw the decimal,
2535                    // then don't parse this one.
2536                    if (isParseIntegerOnly() || sawDecimal) {
2537                        break;
2538                    }
2539
2540                    digits.decimalAt = digitCount; // Not digits.count!
2541                    sawDecimal = true;
2542                    position += decimalStrLen;
2543                    continue;
2544                }
2545
2546                if (isGroupingUsed()) {
2547                    // Check if the sequence at the current position matches locale's grouping separator
2548                    int groupingStrLen = grouping.length();
2549                    if (text.regionMatches(position, grouping, 0, groupingStrLen)) {
2550                        if (sawDecimal) {
2551                            break;
2552                        }
2553
2554                        if (strictParse) {
2555                            if ((!sawDigit || backup != -1)) {
2556                                // leading group, or two group separators in a row
2557                                strictFail = true;
2558                                break;
2559                            }
2560                        }
2561
2562                        // Ignore grouping characters, if we are using them, but require that
2563                        // they be followed by a digit. Otherwise we backup and reprocess
2564                        // them.
2565                        backup = position;
2566                        position += groupingStrLen;
2567                        sawGrouping = true;
2568                        continue;
2569                    }
2570                }
2571
2572                // Check if the code point at the current position matches one of decimal/grouping equivalent group chars
2573                int cp = text.codePointAt(position);
2574                if (!sawDecimal && decimalEquiv.contains(cp)) {
2575                    // matched a decimal separator
2576                    if (strictParse) {
2577                        if (backup != -1 ||
2578                            (lastGroup != -1 && groupedDigitCount != groupingSize)) {
2579                            strictFail = true;
2580                            break;
2581                        }
2582                    }
2583
2584                    // If we're only parsing integers, or if we ALREADY saw the decimal,
2585                    // then don't parse this one.
2586                    if (isParseIntegerOnly()) {
2587                        break;
2588                    }
2589
2590                    digits.decimalAt = digitCount; // Not digits.count!
2591
2592                    // Once we see a decimal separator character, we only accept that
2593                    // decimal separator character from then on.
2594                    decimal = String.valueOf(Character.toChars(cp));
2595
2596                    sawDecimal = true;
2597                    position += Character.charCount(cp);
2598                    continue;
2599                }
2600
2601                if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(cp)) {
2602                    // matched a grouping separator
2603                    if (sawDecimal) {
2604                        break;
2605                    }
2606
2607                    if (strictParse) {
2608                        if ((!sawDigit || backup != -1)) {
2609                            // leading group, or two group separators in a row
2610                            strictFail = true;
2611                            break;
2612                        }
2613                    }
2614
2615                    // Once we see a grouping character, we only accept that grouping
2616                    // character from then on.
2617                    grouping = String.valueOf(Character.toChars(cp));
2618
2619                    // Ignore grouping characters, if we are using them, but require that
2620                    // they be followed by a digit. Otherwise we backup and reprocess
2621                    // them.
2622                    backup = position;
2623                    position += Character.charCount(cp);
2624                    sawGrouping = true;
2625                    continue;
2626                }
2627
2628                // Check if the sequence at the current position matches locale's exponent separator
2629                int exponentSepStrLen = exponentSep.length();
2630                if (text.regionMatches(true, position, exponentSep, 0, exponentSepStrLen)) {
2631                    // parse sign, if present
2632                    boolean negExp = false;
2633                    int pos = position + exponentSep.length();
2634                    if (pos < text.length()) {
2635                        String plusSign = symbols.getPlusSignString();
2636                        String minusSign = symbols.getMinusSignString();
2637                        if (text.regionMatches(pos, plusSign, 0, plusSign.length())) {
2638                            pos += plusSign.length();
2639                        } else if (text.regionMatches(pos, minusSign, 0, minusSign.length())) {
2640                            pos += minusSign.length();
2641                            negExp = true;
2642                        }
2643                    }
2644
2645                    DigitList exponentDigits = new DigitList();
2646                    exponentDigits.count = 0;
2647                    while (pos < text.length()) {
2648                        int digitMatchLen = matchesDigit(text, pos, parsedDigit);
2649                        if (digitMatchLen > 0) {
2650                            exponentDigits.append((char) (parsedDigit[0] + '0'));
2651                            pos += digitMatchLen;
2652                        } else {
2653                            break;
2654                        }
2655                    }
2656
2657                    if (exponentDigits.count > 0) {
2658                        // defer strict parse until we know we have a bona-fide exponent
2659                        if (strictParse && sawGrouping) {
2660                            strictFail = true;
2661                            break;
2662                        }
2663
2664                        // Quick overflow check for exponential part.  Actual limit check
2665                        // will be done later in this code.
2666                        if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
2667                            if (negExp) {
2668                                // set underflow flag
2669                                status[STATUS_UNDERFLOW] = true;
2670                            } else {
2671                                // set infinite flag
2672                                status[STATUS_INFINITE] = true;
2673                            }
2674                        } else {
2675                            exponentDigits.decimalAt = exponentDigits.count;
2676                            exponent = exponentDigits.getLong();
2677                            if (negExp) {
2678                                exponent = -exponent;
2679                            }
2680                        }
2681                        position = pos; // Advance past the exponent
2682                    }
2683
2684                    break; // Whether we fail or succeed, we exit this loop
2685                }
2686
2687                // All other cases, stop parsing
2688                break;
2689            }
2690
2691            if (digits.decimalAt == 0 && isDecimalPatternMatchRequired()) {
2692                if (this.formatPattern.indexOf(decimal) != -1) {
2693                    parsePosition.setIndex(oldStart);
2694                    parsePosition.setErrorIndex(position);
2695                    return false;
2696                }
2697            }
2698
2699            if (backup != -1)
2700                position = backup;
2701
2702            // If there was no decimal point we have an integer
2703            if (!sawDecimal) {
2704                digits.decimalAt = digitCount; // Not digits.count!
2705            }
2706
2707            // check for strict parse errors
2708            if (strictParse && !sawDecimal) {
2709                if (lastGroup != -1 && groupedDigitCount != groupingSize) {
2710                    strictFail = true;
2711                }
2712            }
2713            if (strictFail) {
2714                // only set with strictParse and a leading zero error leading zeros are an
2715                // error with strict parsing except immediately before nondigit (except
2716                // group separator followed by digit), or end of text.
2717
2718                parsePosition.setIndex(oldStart);
2719                parsePosition.setErrorIndex(position);
2720                return false;
2721            }
2722
2723            // Adjust for exponent, if any
2724            exponent += digits.decimalAt;
2725            if (exponent < -getParseMaxDigits()) {
2726                status[STATUS_UNDERFLOW] = true;
2727            } else if (exponent > getParseMaxDigits()) {
2728                status[STATUS_INFINITE] = true;
2729            } else {
2730                digits.decimalAt = (int) exponent;
2731            }
2732
2733            // If none of the text string was recognized. For example, parse "x" with
2734            // pattern "#0.00" (return index and error index both 0) parse "$" with
2735            // pattern "$#0.00". (return index 0 and error index 1).
2736            if (!sawDigit && digitCount == 0) {
2737                parsePosition.setIndex(oldStart);
2738                parsePosition.setErrorIndex(oldStart);
2739                return false;
2740            }
2741        }
2742
2743        // Match padding before suffix
2744        if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
2745            position = skipPadding(text, position);
2746        }
2747
2748        // Match positive and negative suffixes; prefer longest match.
2749        if (posMatch >= 0) {
2750            posMatch = compareAffix(text, position, false, false, posSuffix, parseComplexCurrency, type, currency);
2751        }
2752        if (negMatch >= 0) {
2753            negMatch = compareAffix(text, position, true, false, negSuffix, parseComplexCurrency, type, currency);
2754        }
2755        if (posMatch >= 0 && negMatch >= 0) {
2756            if (posMatch > negMatch) {
2757                negMatch = -1;
2758            } else if (negMatch > posMatch) {
2759                posMatch = -1;
2760            }
2761        }
2762
2763        // Fail if neither or both
2764        if ((posMatch >= 0) == (negMatch >= 0)) {
2765            parsePosition.setErrorIndex(position);
2766            return false;
2767        }
2768
2769        position += (posMatch >= 0 ? posMatch : negMatch);
2770
2771        // Match padding after suffix
2772        if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
2773            position = skipPadding(text, position);
2774        }
2775
2776        parsePosition.setIndex(position);
2777
2778        status[STATUS_POSITIVE] = (posMatch >= 0);
2779
2780        if (parsePosition.getIndex() == oldStart) {
2781            parsePosition.setErrorIndex(position);
2782            return false;
2783        }
2784        return true;
2785    }
2786
2787    /**
2788     * Check if the substring at the specified position matches a decimal digit.
2789     * If matched, this method sets the decimal value to <code>decVal</code> and
2790     * returns matched length.
2791     *
2792     * @param str       The input string
2793     * @param start     The start index
2794     * @param decVal    Receives decimal value
2795     * @return          Length of match, or 0 if the sequence at the position is not
2796     *                  a decimal digit.
2797     */
2798    private int matchesDigit(String str, int start, int[] decVal) {
2799        String[] localeDigits = symbols.getDigitStringsLocal();
2800
2801        // Check if the sequence at the current position matches locale digits.
2802        for (int i = 0; i < 10; i++) {
2803            int digitStrLen = localeDigits[i].length();
2804            if (str.regionMatches(start, localeDigits[i], 0, digitStrLen)) {
2805                decVal[0] = i;
2806                return digitStrLen;
2807            }
2808        }
2809
2810        // If no locale digit match, then check if this is a Unicode digit
2811        int cp = str.codePointAt(start);
2812        decVal[0] = UCharacter.digit(cp, 10);
2813        if (decVal[0] >= 0) {
2814            return Character.charCount(cp);
2815        }
2816
2817        return 0;
2818    }
2819
2820    /**
2821     * Returns a set of characters equivalent to the given desimal separator used for
2822     * parsing number.  This method may return an empty set.
2823     */
2824    private UnicodeSet getEquivalentDecimals(String decimal, boolean strictParse) {
2825        UnicodeSet equivSet = UnicodeSet.EMPTY;
2826        if (strictParse) {
2827            if (strictDotEquivalents.contains(decimal)) {
2828                equivSet = strictDotEquivalents;
2829            } else if (strictCommaEquivalents.contains(decimal)) {
2830                equivSet = strictCommaEquivalents;
2831            }
2832        } else {
2833            if (dotEquivalents.contains(decimal)) {
2834                equivSet = dotEquivalents;
2835            } else if (commaEquivalents.contains(decimal)) {
2836                equivSet = commaEquivalents;
2837            }
2838        }
2839        return equivSet;
2840    }
2841
2842    /**
2843     * Starting at position, advance past a run of pad characters, if any. Return the
2844     * index of the first character after position that is not a pad character. Result is
2845     * >= position.
2846     */
2847    private final int skipPadding(String text, int position) {
2848        while (position < text.length() && text.charAt(position) == pad) {
2849            ++position;
2850        }
2851        return position;
2852    }
2853
2854    /**
2855     * Returns the length matched by the given affix, or -1 if none. Runs of white space
2856     * in the affix, match runs of white space in the input. Pattern white space and input
2857     * white space are determined differently; see code.
2858     *
2859     * @param text input text
2860     * @param pos offset into input at which to begin matching
2861     * @param isNegative
2862     * @param isPrefix
2863     * @param affixPat affix pattern used for currency affix comparison
2864     * @param complexCurrencyParsing whether it is currency parsing or not
2865     * @param type compare against currency type, LONG_NAME only or not.
2866     * @param currency return value for parsed currency, for generic currency parsing
2867     * mode, or null for normal parsing.  In generic currency parsing mode, any currency
2868     * is parsed, not just the currency that this formatter is set to.
2869     * @return length of input that matches, or -1 if match failure
2870     */
2871    private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix,
2872                             String affixPat, boolean complexCurrencyParsing, int type, Currency[] currency) {
2873        if (currency != null || currencyChoice != null || (currencySignCount != CURRENCY_SIGN_COUNT_ZERO && complexCurrencyParsing)) {
2874            return compareComplexAffix(affixPat, text, pos, type, currency);
2875        }
2876        if (isPrefix) {
2877            return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos);
2878        } else {
2879            return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos);
2880        }
2881
2882    }
2883
2884    /**
2885     * Check for bidi marks: LRM, RLM, ALM
2886     */
2887    private static boolean isBidiMark(int c) {
2888        return (c==0x200E || c==0x200F || c==0x061C);
2889    }
2890
2891    /**
2892     * Remove bidi marks from affix
2893     */
2894    private static String trimMarksFromAffix(String affix) {
2895        boolean hasBidiMark = false;
2896        int idx = 0;
2897        for (; idx < affix.length(); idx++) {
2898            if (isBidiMark(affix.charAt(idx))) {
2899                hasBidiMark = true;
2900                break;
2901            }
2902        }
2903        if (!hasBidiMark) {
2904            return affix;
2905        }
2906
2907        StringBuilder buf = new StringBuilder();
2908        buf.append(affix, 0, idx);
2909        idx++;  // skip the first Bidi mark
2910        for (; idx < affix.length(); idx++) {
2911            char c = affix.charAt(idx);
2912            if (!isBidiMark(c)) {
2913                buf.append(c);
2914            }
2915        }
2916
2917        return buf.toString();
2918    }
2919
2920    /**
2921     * Return the length matched by the given affix, or -1 if none. Runs of white space in
2922     * the affix, match runs of white space in the input. Pattern white space and input
2923     * white space are determined differently; see code.
2924     *
2925     * @param affix pattern string, taken as a literal
2926     * @param input input text
2927     * @param pos offset into input at which to begin matching
2928     * @return length of input that matches, or -1 if match failure
2929     */
2930    private static int compareSimpleAffix(String affix, String input, int pos) {
2931        int start = pos;
2932        // Affixes here might consist of sign, currency symbol and related spacing, etc.
2933        // For more efficiency we should keep lazily-created trimmed affixes around in
2934        // instance variables instead of trimming each time they are used (the next step).
2935        String trimmedAffix = (affix.length() > 1)? trimMarksFromAffix(affix): affix;
2936        for (int i = 0; i < trimmedAffix.length();) {
2937            int c = UTF16.charAt(trimmedAffix, i);
2938            int len = UTF16.getCharCount(c);
2939            if (PatternProps.isWhiteSpace(c)) {
2940                // We may have a pattern like: \u200F and input text like: \u200F Note
2941                // that U+200F and U+0020 are Pattern_White_Space but only U+0020 is
2942                // UWhiteSpace. So we have to first do a direct match of the run of RULE
2943                // whitespace in the pattern, then match any extra characters.
2944                boolean literalMatch = false;
2945                while (pos < input.length()) {
2946                    int ic = UTF16.charAt(input, pos);
2947                    if (ic == c) {
2948                        literalMatch = true;
2949                        i += len;
2950                        pos += len;
2951                        if (i == trimmedAffix.length()) {
2952                            break;
2953                        }
2954                        c = UTF16.charAt(trimmedAffix, i);
2955                        len = UTF16.getCharCount(c);
2956                        if (!PatternProps.isWhiteSpace(c)) {
2957                            break;
2958                        }
2959                    } else if (isBidiMark(ic)) {
2960                        pos++; // just skip over this input text
2961                    } else {
2962                        break;
2963                    }
2964                }
2965
2966                // Advance over run in trimmedAffix
2967                i = skipPatternWhiteSpace(trimmedAffix, i);
2968
2969                // Advance over run in input text. Must see at least one white space char
2970                // in input, unless we've already matched some characters literally.
2971                int s = pos;
2972                pos = skipUWhiteSpace(input, pos);
2973                if (pos == s && !literalMatch) {
2974                    return -1;
2975                }
2976                // If we skip UWhiteSpace in the input text, we need to skip it in the
2977                // pattern.  Otherwise, the previous lines may have skipped over text
2978                // (such as U+00A0) that is also in the trimmedAffix.
2979                i = skipUWhiteSpace(trimmedAffix, i);
2980            } else {
2981                boolean match = false;
2982                while (pos < input.length()) {
2983                    int ic = UTF16.charAt(input, pos);
2984                    if (!match && equalWithSignCompatibility(ic, c)) {
2985                        i += len;
2986                        pos += len;
2987                        match = true;
2988                    } else if (isBidiMark(ic)) {
2989                        pos++; // just skip over this input text
2990                    } else {
2991                        break;
2992                    }
2993                }
2994                if (!match) {
2995                    return -1;
2996                }
2997            }
2998        }
2999        return pos - start;
3000    }
3001
3002    private static boolean equalWithSignCompatibility(int lhs, int rhs) {
3003        return lhs == rhs
3004                || (minusSigns.contains(lhs) && minusSigns.contains(rhs))
3005                || (plusSigns.contains(lhs) && plusSigns.contains(rhs));
3006    }
3007
3008    /**
3009     * Skips over a run of zero or more Pattern_White_Space characters at pos in text.
3010     */
3011    private static int skipPatternWhiteSpace(String text, int pos) {
3012        while (pos < text.length()) {
3013            int c = UTF16.charAt(text, pos);
3014            if (!PatternProps.isWhiteSpace(c)) {
3015                break;
3016            }
3017            pos += UTF16.getCharCount(c);
3018        }
3019        return pos;
3020    }
3021
3022    /**
3023     * Skips over a run of zero or more isUWhiteSpace() characters at pos in text.
3024     */
3025    private static int skipUWhiteSpace(String text, int pos) {
3026        while (pos < text.length()) {
3027            int c = UTF16.charAt(text, pos);
3028            if (!UCharacter.isUWhiteSpace(c)) {
3029                break;
3030            }
3031            pos += UTF16.getCharCount(c);
3032        }
3033        return pos;
3034    }
3035
3036     /**
3037     * Skips over a run of zero or more bidi marks at pos in text.
3038     */
3039    private static int skipBidiMarks(String text, int pos) {
3040        while (pos < text.length()) {
3041            int c = UTF16.charAt(text, pos);
3042            if (!isBidiMark(c)) {
3043                break;
3044            }
3045            pos += UTF16.getCharCount(c);
3046        }
3047        return pos;
3048    }
3049
3050   /**
3051     * Returns the length matched by the given affix, or -1 if none.
3052     *
3053     * @param affixPat pattern string
3054     * @param text input text
3055     * @param pos offset into input at which to begin matching
3056     * @param type parse against currency type, LONG_NAME only or not.
3057     * @param currency return value for parsed currency, for generic
3058     * currency parsing mode, or null for normal parsing.  In generic
3059     * currency parsing mode, any currency is parsed, not just the
3060     * currency that this formatter is set to.
3061     * @return position after the matched text, or -1 if match failure
3062     */
3063    private int compareComplexAffix(String affixPat, String text, int pos, int type,
3064                                    Currency[] currency) {
3065        int start = pos;
3066        for (int i = 0; i < affixPat.length() && pos >= 0;) {
3067            char c = affixPat.charAt(i++);
3068            if (c == QUOTE) {
3069                for (;;) {
3070                    int j = affixPat.indexOf(QUOTE, i);
3071                    if (j == i) {
3072                        pos = match(text, pos, QUOTE);
3073                        i = j + 1;
3074                        break;
3075                    } else if (j > i) {
3076                        pos = match(text, pos, affixPat.substring(i, j));
3077                        i = j + 1;
3078                        if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) {
3079                            pos = match(text, pos, QUOTE);
3080                            ++i;
3081                            // loop again
3082                        } else {
3083                            break;
3084                        }
3085                    } else {
3086                        // Unterminated quote; should be caught by apply
3087                        // pattern.
3088                        throw new RuntimeException();
3089                    }
3090                }
3091                continue;
3092            }
3093
3094            String affix = null;
3095
3096            switch (c) {
3097            case CURRENCY_SIGN:
3098                // since the currency names in choice format is saved the same way as
3099                // other currency names, do not need to do currency choice parsing here.
3100                // the general currency parsing parse against all names, including names
3101                // in choice format.  assert(currency != null || (getCurrency() != null &&
3102                // currencyChoice != null));
3103                boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
3104                if (intl) {
3105                    ++i;
3106                }
3107                boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
3108                if (plural) {
3109                    ++i;
3110                    intl = false;
3111                }
3112                // Parse generic currency -- anything for which we have a display name, or
3113                // any 3-letter ISO code.  Try to parse display name for our locale; first
3114                // determine our locale.  TODO: use locale in CurrencyPluralInfo
3115                ULocale uloc = getLocale(ULocale.VALID_LOCALE);
3116                if (uloc == null) {
3117                    // applyPattern has been called; use the symbols
3118                    uloc = symbols.getLocale(ULocale.VALID_LOCALE);
3119                }
3120                // Delegate parse of display name => ISO code to Currency
3121                ParsePosition ppos = new ParsePosition(pos);
3122                // using Currency.parse to handle mixed style parsing.
3123                String iso = Currency.parse(uloc, text, type, ppos);
3124
3125                // If parse succeeds, populate currency[0]
3126                if (iso != null) {
3127                    if (currency != null) {
3128                        currency[0] = Currency.getInstance(iso);
3129                    } else {
3130                        // The formatter is currency-style but the client has not requested
3131                        // the value of the parsed currency. In this case, if that value does
3132                        // not match the formatter's current value, then the parse fails.
3133                        Currency effectiveCurr = getEffectiveCurrency();
3134                        if (iso.compareTo(effectiveCurr.getCurrencyCode()) != 0) {
3135                            pos = -1;
3136                            continue;
3137                        }
3138                    }
3139                    pos = ppos.getIndex();
3140                } else {
3141                    pos = -1;
3142                }
3143                continue;
3144            case PATTERN_PERCENT:
3145                affix = symbols.getPercentString();
3146                break;
3147            case PATTERN_PER_MILLE:
3148                affix = symbols.getPerMillString();
3149                break;
3150            case PATTERN_PLUS_SIGN:
3151                affix = symbols.getPlusSignString();
3152                break;
3153            case PATTERN_MINUS_SIGN:
3154                affix = symbols.getMinusSignString();
3155                break;
3156            default:
3157                // fall through to affix != null test, which will fail
3158                break;
3159            }
3160
3161            if (affix != null) {
3162                pos = match(text, pos, affix);
3163                continue;
3164            }
3165
3166            pos = match(text, pos, c);
3167            if (PatternProps.isWhiteSpace(c)) {
3168                i = skipPatternWhiteSpace(affixPat, i);
3169            }
3170        }
3171
3172        return pos - start;
3173    }
3174
3175    /**
3176     * Matches a single character at text[pos] and return the index of the next character
3177     * upon success. Return -1 on failure. If ch is a Pattern_White_Space then match a run of
3178     * white space in text.
3179     */
3180    static final int match(String text, int pos, int ch) {
3181        if (pos < 0 || pos >= text.length()) {
3182            return -1;
3183        }
3184        pos = skipBidiMarks(text, pos);
3185        if (PatternProps.isWhiteSpace(ch)) {
3186            // Advance over run of white space in input text
3187            // Must see at least one white space char in input
3188            int s = pos;
3189            pos = skipPatternWhiteSpace(text, pos);
3190            if (pos == s) {
3191                return -1;
3192            }
3193            return pos;
3194        }
3195        if (pos >= text.length() || UTF16.charAt(text, pos) != ch) {
3196            return -1;
3197        }
3198        pos = skipBidiMarks(text, pos + UTF16.getCharCount(ch));
3199        return pos;
3200    }
3201
3202    /**
3203     * Matches a string at text[pos] and return the index of the next character upon
3204     * success. Return -1 on failure. Match a run of white space in str with a run of
3205     * white space in text.
3206     */
3207    static final int match(String text, int pos, String str) {
3208        for (int i = 0; i < str.length() && pos >= 0;) {
3209            int ch = UTF16.charAt(str, i);
3210            i += UTF16.getCharCount(ch);
3211            if (isBidiMark(ch)) {
3212                continue;
3213            }
3214            pos = match(text, pos, ch);
3215            if (PatternProps.isWhiteSpace(ch)) {
3216                i = skipPatternWhiteSpace(str, i);
3217            }
3218        }
3219        return pos;
3220    }
3221
3222    /**
3223     * Returns a copy of the decimal format symbols used by this format.
3224     *
3225     * @return desired DecimalFormatSymbols
3226     * @see DecimalFormatSymbols
3227     */
3228    public DecimalFormatSymbols getDecimalFormatSymbols() {
3229        try {
3230            // don't allow multiple references
3231            return (DecimalFormatSymbols) symbols.clone();
3232        } catch (Exception foo) {
3233            return null; // should never happen
3234        }
3235    }
3236
3237    /**
3238     * Sets the decimal format symbols used by this format. The format uses a copy of the
3239     * provided symbols.
3240     *
3241     * @param newSymbols desired DecimalFormatSymbols
3242     * @see DecimalFormatSymbols
3243     */
3244    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
3245        symbols = (DecimalFormatSymbols) newSymbols.clone();
3246        setCurrencyForSymbols();
3247        expandAffixes(null);
3248    }
3249
3250    /**
3251     * Update the currency object to match the symbols. This method is used only when the
3252     * caller has passed in a symbols object that may not be the default object for its
3253     * locale.
3254     */
3255    private void setCurrencyForSymbols() {
3256
3257        // Bug 4212072 Update the affix strings according to symbols in order to keep the
3258        // affix strings up to date.  [Richard/GCL]
3259
3260        // With the introduction of the Currency object, the currency symbols in the DFS
3261        // object are ignored. For backward compatibility, we check any explicitly set DFS
3262        // object. If it is a default symbols object for its locale, we change the
3263        // currency object to one for that locale. If it is custom, we set the currency to
3264        // null.
3265        DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getULocale());
3266
3267        if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())
3268                && symbols.getInternationalCurrencySymbol()
3269                       .equals(def.getInternationalCurrencySymbol())) {
3270            setCurrency(Currency.getInstance(symbols.getULocale()));
3271        } else {
3272            setCurrency(null);
3273        }
3274    }
3275
3276    /**
3277     * Returns the positive prefix.
3278     *
3279     * <p>Examples: +123, $123, sFr123
3280     * @return the prefix
3281     */
3282    public String getPositivePrefix() {
3283        return positivePrefix;
3284    }
3285
3286    /**
3287     * Sets the positive prefix.
3288     *
3289     * <p>Examples: +123, $123, sFr123
3290     * @param newValue the prefix
3291     */
3292    public void setPositivePrefix(String newValue) {
3293        positivePrefix = newValue;
3294        posPrefixPattern = null;
3295    }
3296
3297    /**
3298     * Returns the negative prefix.
3299     *
3300     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
3301     *
3302     * @return the prefix
3303     */
3304    public String getNegativePrefix() {
3305        return negativePrefix;
3306    }
3307
3308    /**
3309     * Sets the negative prefix.
3310     *
3311     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
3312     * @param newValue the prefix
3313     */
3314    public void setNegativePrefix(String newValue) {
3315        negativePrefix = newValue;
3316        negPrefixPattern = null;
3317    }
3318
3319    /**
3320     * Returns the positive suffix.
3321     *
3322     * <p>Example: 123%
3323     *
3324     * @return the suffix
3325     */
3326    public String getPositiveSuffix() {
3327        return positiveSuffix;
3328    }
3329
3330    /**
3331     * Sets the positive suffix.
3332     *
3333     * <p>Example: 123%
3334     * @param newValue the suffix
3335     */
3336    public void setPositiveSuffix(String newValue) {
3337        positiveSuffix = newValue;
3338        posSuffixPattern = null;
3339    }
3340
3341    /**
3342     * Returns the negative suffix.
3343     *
3344     * <p>Examples: -123%, ($123) (with positive suffixes)
3345     *
3346     * @return the suffix
3347     */
3348    public String getNegativeSuffix() {
3349        return negativeSuffix;
3350    }
3351
3352    /**
3353     * Sets the positive suffix.
3354     *
3355     * <p>Examples: 123%
3356     * @param newValue the suffix
3357     */
3358    public void setNegativeSuffix(String newValue) {
3359        negativeSuffix = newValue;
3360        negSuffixPattern = null;
3361    }
3362
3363    /**
3364     * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
3365     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
3366     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
3367     * 1000.
3368     *
3369     * <p>Examples: with 100, 1.23 -&gt; "123", and "123" -&gt; 1.23
3370     *
3371     * @return the multiplier
3372     */
3373    public int getMultiplier() {
3374        return multiplier;
3375    }
3376
3377    /**
3378     * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
3379     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
3380     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
3381     * 1000.
3382     *
3383     * <p>Examples: with 100, 1.23 -&gt; "123", and "123" -&gt; 1.23
3384     *
3385     * @param newValue the multiplier
3386     */
3387    public void setMultiplier(int newValue) {
3388        if (newValue == 0) {
3389            throw new IllegalArgumentException("Bad multiplier: " + newValue);
3390        }
3391        multiplier = newValue;
3392    }
3393
3394    /**
3395     * <strong>[icu]</strong> Returns the rounding increment.
3396     *
3397     * @return A positive rounding increment, or <code>null</code> if a custom rounding
3398     * increment is not in effect.
3399     * @see #setRoundingIncrement
3400     * @see #getRoundingMode
3401     * @see #setRoundingMode
3402     */
3403    public java.math.BigDecimal getRoundingIncrement() {
3404        if (roundingIncrementICU == null)
3405            return null;
3406        return roundingIncrementICU.toBigDecimal();
3407    }
3408
3409    /**
3410     * <strong>[icu]</strong> Sets the rounding increment. In the absence of a rounding increment, numbers
3411     * will be rounded to the number of digits displayed.
3412     *
3413     * @param newValue A positive rounding increment, or <code>null</code> or
3414     * <code>BigDecimal(0.0)</code> to use the default rounding increment.
3415     * @throws IllegalArgumentException if <code>newValue</code> is &lt; 0.0
3416     * @see #getRoundingIncrement
3417     * @see #getRoundingMode
3418     * @see #setRoundingMode
3419     */
3420    public void setRoundingIncrement(java.math.BigDecimal newValue) {
3421        if (newValue == null) {
3422            setRoundingIncrement((BigDecimal) null);
3423        } else {
3424            setRoundingIncrement(new BigDecimal(newValue));
3425        }
3426    }
3427
3428    /**
3429     * <strong>[icu]</strong> Sets the rounding increment. In the absence of a rounding increment, numbers
3430     * will be rounded to the number of digits displayed.
3431     *
3432     * @param newValue A positive rounding increment, or <code>null</code> or
3433     * <code>BigDecimal(0.0)</code> to use the default rounding increment.
3434     * @throws IllegalArgumentException if <code>newValue</code> is &lt; 0.0
3435     * @see #getRoundingIncrement
3436     * @see #getRoundingMode
3437     * @see #setRoundingMode
3438     */
3439    public void setRoundingIncrement(BigDecimal newValue) {
3440        int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO);
3441        if (i < 0) {
3442            throw new IllegalArgumentException("Illegal rounding increment");
3443        }
3444        if (i == 0) {
3445            setInternalRoundingIncrement(null);
3446        } else {
3447            setInternalRoundingIncrement(newValue);
3448        }
3449        resetActualRounding();
3450    }
3451
3452    /**
3453     * <strong>[icu]</strong> Sets the rounding increment. In the absence of a rounding increment, numbers
3454     * will be rounded to the number of digits displayed.
3455     *
3456     * @param newValue A positive rounding increment, or 0.0 to use the default
3457     * rounding increment.
3458     * @throws IllegalArgumentException if <code>newValue</code> is &lt; 0.0
3459     * @see #getRoundingIncrement
3460     * @see #getRoundingMode
3461     * @see #setRoundingMode
3462     */
3463    public void setRoundingIncrement(double newValue) {
3464        if (newValue < 0.0) {
3465            throw new IllegalArgumentException("Illegal rounding increment");
3466        }
3467        if (newValue == 0.0d) {
3468            setInternalRoundingIncrement((BigDecimal) null);
3469        } else {
3470            // Should use BigDecimal#valueOf(double) instead of constructor
3471            // to avoid the double precision problem.
3472            setInternalRoundingIncrement(BigDecimal.valueOf(newValue));
3473        }
3474        resetActualRounding();
3475    }
3476
3477    /**
3478     * Returns the rounding mode.
3479     *
3480     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
3481     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
3482     * @see #setRoundingIncrement
3483     * @see #getRoundingIncrement
3484     * @see #setRoundingMode
3485     * @see java.math.BigDecimal
3486     */
3487    @Override
3488    public int getRoundingMode() {
3489        return roundingMode;
3490    }
3491
3492    /**
3493     * Sets the rounding mode. This has no effect unless the rounding increment is greater
3494     * than zero.
3495     *
3496     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
3497     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
3498     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
3499     * @see #setRoundingIncrement
3500     * @see #getRoundingIncrement
3501     * @see #getRoundingMode
3502     * @see java.math.BigDecimal
3503     */
3504    @Override
3505    public void setRoundingMode(int roundingMode) {
3506        if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
3507            throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);
3508        }
3509
3510        this.roundingMode = roundingMode;
3511        resetActualRounding();
3512    }
3513
3514    /**
3515     * Returns the width to which the output of <code>format()</code> is padded. The width is
3516     * counted in 16-bit code units.
3517     *
3518     * @return the format width, or zero if no padding is in effect
3519     * @see #setFormatWidth
3520     * @see #getPadCharacter
3521     * @see #setPadCharacter
3522     * @see #getPadPosition
3523     * @see #setPadPosition
3524     */
3525    public int getFormatWidth() {
3526        return formatWidth;
3527    }
3528
3529    /**
3530     * Sets the width to which the output of <code>format()</code> is
3531     * padded. The width is counted in 16-bit code units.  This method
3532     * also controls whether padding is enabled.
3533     *
3534     * @param width the width to which to pad the result of
3535     * <code>format()</code>, or zero to disable padding
3536     * @exception IllegalArgumentException if <code>width</code> is &lt; 0
3537     * @see #getFormatWidth
3538     * @see #getPadCharacter
3539     * @see #setPadCharacter
3540     * @see #getPadPosition
3541     * @see #setPadPosition
3542     */
3543    public void setFormatWidth(int width) {
3544        if (width < 0) {
3545            throw new IllegalArgumentException("Illegal format width");
3546        }
3547        formatWidth = width;
3548    }
3549
3550    /**
3551     * <strong>[icu]</strong> Returns the character used to pad to the format width. The default is ' '.
3552     *
3553     * @return the pad character
3554     * @see #setFormatWidth
3555     * @see #getFormatWidth
3556     * @see #setPadCharacter
3557     * @see #getPadPosition
3558     * @see #setPadPosition
3559     */
3560    public char getPadCharacter() {
3561        return pad;
3562    }
3563
3564    /**
3565     * <strong>[icu]</strong> Sets the character used to pad to the format width. If padding is not
3566     * enabled, then this will take effect if padding is later enabled.
3567     *
3568     * @param padChar the pad character
3569     * @see #setFormatWidth
3570     * @see #getFormatWidth
3571     * @see #getPadCharacter
3572     * @see #getPadPosition
3573     * @see #setPadPosition
3574     */
3575    public void setPadCharacter(char padChar) {
3576        pad = padChar;
3577    }
3578
3579    /**
3580     * <strong>[icu]</strong> Returns the position at which padding will take place. This is the location at
3581     * which padding will be inserted if the result of <code>format()</code> is shorter
3582     * than the format width.
3583     *
3584     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
3585     *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
3586     *         <code>PAD_AFTER_SUFFIX</code>.
3587     * @see #setFormatWidth
3588     * @see #getFormatWidth
3589     * @see #setPadCharacter
3590     * @see #getPadCharacter
3591     * @see #setPadPosition
3592     * @see #PAD_BEFORE_PREFIX
3593     * @see #PAD_AFTER_PREFIX
3594     * @see #PAD_BEFORE_SUFFIX
3595     * @see #PAD_AFTER_SUFFIX
3596     */
3597    public int getPadPosition() {
3598        return padPosition;
3599    }
3600
3601    /**
3602     * <strong>[icu]</strong> Sets the position at which padding will take place. This is the location at
3603     * which padding will be inserted if the result of <code>format()</code> is shorter
3604     * than the format width. This has no effect unless padding is enabled.
3605     *
3606     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
3607     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
3608     * <code>PAD_AFTER_SUFFIX</code>.
3609     * @exception IllegalArgumentException if the pad position in unrecognized
3610     * @see #setFormatWidth
3611     * @see #getFormatWidth
3612     * @see #setPadCharacter
3613     * @see #getPadCharacter
3614     * @see #getPadPosition
3615     * @see #PAD_BEFORE_PREFIX
3616     * @see #PAD_AFTER_PREFIX
3617     * @see #PAD_BEFORE_SUFFIX
3618     * @see #PAD_AFTER_SUFFIX
3619     */
3620    public void setPadPosition(int padPos) {
3621        if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
3622            throw new IllegalArgumentException("Illegal pad position");
3623        }
3624        padPosition = padPos;
3625    }
3626
3627    /**
3628     * <strong>[icu]</strong> Returns whether or not scientific notation is used.
3629     *
3630     * @return true if this object formats and parses scientific notation
3631     * @see #setScientificNotation
3632     * @see #getMinimumExponentDigits
3633     * @see #setMinimumExponentDigits
3634     * @see #isExponentSignAlwaysShown
3635     * @see #setExponentSignAlwaysShown
3636     */
3637    public boolean isScientificNotation() {
3638        return useExponentialNotation;
3639    }
3640
3641    /**
3642     * <strong>[icu]</strong> Sets whether or not scientific notation is used. When scientific notation is
3643     * used, the effective maximum number of integer digits is &lt;= 8. If the maximum number
3644     * of integer digits is set to more than 8, the effective maximum will be 1. This
3645     * allows this call to generate a 'default' scientific number format without
3646     * additional changes.
3647     *
3648     * @param useScientific true if this object formats and parses scientific notation
3649     * @see #isScientificNotation
3650     * @see #getMinimumExponentDigits
3651     * @see #setMinimumExponentDigits
3652     * @see #isExponentSignAlwaysShown
3653     * @see #setExponentSignAlwaysShown
3654     */
3655    public void setScientificNotation(boolean useScientific) {
3656        useExponentialNotation = useScientific;
3657    }
3658
3659    /**
3660     * <strong>[icu]</strong> Returns the minimum exponent digits that will be shown.
3661     *
3662     * @return the minimum exponent digits that will be shown
3663     * @see #setScientificNotation
3664     * @see #isScientificNotation
3665     * @see #setMinimumExponentDigits
3666     * @see #isExponentSignAlwaysShown
3667     * @see #setExponentSignAlwaysShown
3668     */
3669    public byte getMinimumExponentDigits() {
3670        return minExponentDigits;
3671    }
3672
3673    /**
3674     * <strong>[icu]</strong> Sets the minimum exponent digits that will be shown. This has no effect
3675     * unless scientific notation is in use.
3676     *
3677     * @param minExpDig a value &gt;= 1 indicating the fewest exponent
3678     * digits that will be shown
3679     * @exception IllegalArgumentException if <code>minExpDig</code> &lt; 1
3680     * @see #setScientificNotation
3681     * @see #isScientificNotation
3682     * @see #getMinimumExponentDigits
3683     * @see #isExponentSignAlwaysShown
3684     * @see #setExponentSignAlwaysShown
3685     */
3686    public void setMinimumExponentDigits(byte minExpDig) {
3687        if (minExpDig < 1) {
3688            throw new IllegalArgumentException("Exponent digits must be >= 1");
3689        }
3690        minExponentDigits = minExpDig;
3691    }
3692
3693    /**
3694     * <strong>[icu]</strong> Returns whether the exponent sign is always shown.
3695     *
3696     * @return true if the exponent is always prefixed with either the localized minus
3697     * sign or the localized plus sign, false if only negative exponents are prefixed with
3698     * the localized minus sign.
3699     * @see #setScientificNotation
3700     * @see #isScientificNotation
3701     * @see #setMinimumExponentDigits
3702     * @see #getMinimumExponentDigits
3703     * @see #setExponentSignAlwaysShown
3704     */
3705    public boolean isExponentSignAlwaysShown() {
3706        return exponentSignAlwaysShown;
3707    }
3708
3709    /**
3710     * <strong>[icu]</strong> Sets whether the exponent sign is always shown. This has no effect unless
3711     * scientific notation is in use.
3712     *
3713     * @param expSignAlways true if the exponent is always prefixed with either the
3714     * localized minus sign or the localized plus sign, false if only negative exponents
3715     * are prefixed with the localized minus sign.
3716     * @see #setScientificNotation
3717     * @see #isScientificNotation
3718     * @see #setMinimumExponentDigits
3719     * @see #getMinimumExponentDigits
3720     * @see #isExponentSignAlwaysShown
3721     */
3722    public void setExponentSignAlwaysShown(boolean expSignAlways) {
3723        exponentSignAlwaysShown = expSignAlways;
3724    }
3725
3726    /**
3727     * Returns the grouping size. Grouping size is the number of digits between grouping
3728     * separators in the integer portion of a number. For example, in the number
3729     * "123,456.78", the grouping size is 3.
3730     *
3731     * @see #setGroupingSize
3732     * @see NumberFormat#isGroupingUsed
3733     * @see DecimalFormatSymbols#getGroupingSeparator
3734     */
3735    public int getGroupingSize() {
3736        return groupingSize;
3737    }
3738
3739    /**
3740     * Sets the grouping size. Grouping size is the number of digits between grouping
3741     * separators in the integer portion of a number. For example, in the number
3742     * "123,456.78", the grouping size is 3.
3743     *
3744     * @see #getGroupingSize
3745     * @see NumberFormat#setGroupingUsed
3746     * @see DecimalFormatSymbols#setGroupingSeparator
3747     */
3748    public void setGroupingSize(int newValue) {
3749        groupingSize = (byte) newValue;
3750    }
3751
3752    /**
3753     * <strong>[icu]</strong> Returns the secondary grouping size. In some locales one grouping interval
3754     * is used for the least significant integer digits (the primary grouping size), and
3755     * another is used for all others (the secondary grouping size). A formatter
3756     * supporting a secondary grouping size will return a positive integer unequal to the
3757     * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
3758     * the primary grouping size is 4, and the secondary grouping size is 2, then the
3759     * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
3760     *
3761     * @return the secondary grouping size, or a value less than one if there is none
3762     * @see #setSecondaryGroupingSize
3763     * @see NumberFormat#isGroupingUsed
3764     * @see DecimalFormatSymbols#getGroupingSeparator
3765     */
3766    public int getSecondaryGroupingSize() {
3767        return groupingSize2;
3768    }
3769
3770    /**
3771     * <strong>[icu]</strong> Sets the secondary grouping size. If set to a value less than 1, then
3772     * secondary grouping is turned off, and the primary grouping size is used for all
3773     * intervals, not just the least significant.
3774     *
3775     * @see #getSecondaryGroupingSize
3776     * @see NumberFormat#setGroupingUsed
3777     * @see DecimalFormatSymbols#setGroupingSeparator
3778     */
3779    public void setSecondaryGroupingSize(int newValue) {
3780        groupingSize2 = (byte) newValue;
3781    }
3782
3783    /**
3784     * <strong>[icu]</strong> Returns the MathContext used by this format.
3785     *
3786     * @return desired MathContext
3787     * @see #getMathContext
3788     */
3789    public MathContext getMathContextICU() {
3790        return mathContext;
3791    }
3792
3793    /**
3794     * <strong>[icu]</strong> Returns the MathContext used by this format.
3795     *
3796     * @return desired MathContext
3797     * @see #getMathContext
3798     */
3799    public java.math.MathContext getMathContext() {
3800        try {
3801            // don't allow multiple references
3802            return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(),
3803                    java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
3804        } catch (Exception foo) {
3805            return null; // should never happen
3806        }
3807    }
3808
3809    /**
3810     * <strong>[icu]</strong> Sets the MathContext used by this format.
3811     *
3812     * @param newValue desired MathContext
3813     * @see #getMathContext
3814     */
3815    public void setMathContextICU(MathContext newValue) {
3816        mathContext = newValue;
3817    }
3818
3819    /**
3820     * <strong>[icu]</strong> Sets the MathContext used by this format.
3821     *
3822     * @param newValue desired MathContext
3823     * @see #getMathContext
3824     */
3825    public void setMathContext(java.math.MathContext newValue) {
3826        mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false,
3827                                      (newValue.getRoundingMode()).ordinal());
3828    }
3829
3830    /**
3831     * Returns the behavior of the decimal separator with integers. (The decimal
3832     * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 -&gt;
3833     * 12345.; OFF: 12345 -&gt; 12345
3834     */
3835    public boolean isDecimalSeparatorAlwaysShown() {
3836        return decimalSeparatorAlwaysShown;
3837    }
3838
3839    /**
3840     * When decimal match is not required, the input does not have to
3841     * contain a decimal mark when there is a decimal mark specified in the
3842     * pattern.
3843     * @param value true if input must contain a match to decimal mark in pattern
3844     * Default is false.
3845     */
3846     public void setDecimalPatternMatchRequired(boolean value) {
3847         parseRequireDecimalPoint = value;
3848     }
3849
3850    /**
3851     * <strong>[icu]</strong> Returns whether the input to parsing must contain a decimal mark if there
3852     * is a decimal mark in the pattern.
3853     * @return true if input must contain a match to decimal mark in pattern
3854     */
3855    public boolean isDecimalPatternMatchRequired() {
3856        return parseRequireDecimalPoint;
3857    }
3858
3859
3860    /**
3861     * Sets the behavior of the decimal separator with integers. (The decimal separator
3862     * will always appear with decimals.)
3863     *
3864     * <p>This only affects formatting, and only where there might be no digits after the
3865     * decimal point, e.g., if true, 3456.00 -&gt; "3,456." if false, 3456.00 -&gt; "3456" This
3866     * is independent of parsing. If you want parsing to stop at the decimal point, use
3867     * setParseIntegerOnly.
3868     *
3869     * <p>
3870     * Example: Decimal ON: 12345 -&gt; 12345.; OFF: 12345 -&gt; 12345
3871     */
3872    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
3873        decimalSeparatorAlwaysShown = newValue;
3874    }
3875
3876    /**
3877     * <strong>[icu]</strong> Returns a copy of the CurrencyPluralInfo used by this format. It might
3878     * return null if the decimal format is not a plural type currency decimal
3879     * format. Plural type currency decimal format means either the pattern in the decimal
3880     * format contains 3 currency signs, or the decimal format is initialized with
3881     * PLURALCURRENCYSTYLE.
3882     *
3883     * @return desired CurrencyPluralInfo
3884     * @see CurrencyPluralInfo
3885     */
3886    public CurrencyPluralInfo getCurrencyPluralInfo() {
3887        try {
3888            // don't allow multiple references
3889            return currencyPluralInfo == null ? null :
3890                (CurrencyPluralInfo) currencyPluralInfo.clone();
3891        } catch (Exception foo) {
3892            return null; // should never happen
3893        }
3894    }
3895
3896    /**
3897     * <strong>[icu]</strong> Sets the CurrencyPluralInfo used by this format. The format uses a copy of
3898     * the provided information.
3899     *
3900     * @param newInfo desired CurrencyPluralInfo
3901     * @see CurrencyPluralInfo
3902     */
3903    public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
3904        currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
3905        isReadyForParsing = false;
3906    }
3907
3908    /**
3909     * Overrides clone.
3910     */
3911    @Override
3912    public Object clone() {
3913        try {
3914            DecimalFormat other = (DecimalFormat) super.clone();
3915            other.symbols = (DecimalFormatSymbols) symbols.clone();
3916            other.digitList = new DigitList(); // fix for JB#5358
3917            if (currencyPluralInfo != null) {
3918                other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
3919            }
3920            other.attributes = new ArrayList<FieldPosition>(); // #9240
3921            other.currencyUsage = currencyUsage;
3922
3923            // TODO: We need to figure out whether we share a single copy of DigitList by
3924            // multiple cloned copies.  format/subformat are designed to use a single
3925            // instance, but parse/subparse implementation is not.
3926            return other;
3927        } catch (Exception e) {
3928            throw new IllegalStateException();
3929        }
3930    }
3931
3932    /**
3933     * Overrides equals.
3934     */
3935    @Override
3936    public boolean equals(Object obj) {
3937        if (obj == null)
3938            return false;
3939        if (!super.equals(obj))
3940            return false; // super does class check
3941
3942        DecimalFormat other = (DecimalFormat) obj;
3943        // Add the comparison of the four new added fields ,they are posPrefixPattern,
3944        // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL]
3945        // following are added to accomodate changes for currency plural format.
3946        return currencySignCount == other.currencySignCount
3947                && (style != NumberFormat.PLURALCURRENCYSTYLE ||
3948                    equals(posPrefixPattern, other.posPrefixPattern)
3949                && equals(posSuffixPattern, other.posSuffixPattern)
3950                && equals(negPrefixPattern, other.negPrefixPattern)
3951                && equals(negSuffixPattern, other.negSuffixPattern))
3952                && multiplier == other.multiplier
3953                && groupingSize == other.groupingSize
3954                && groupingSize2 == other.groupingSize2
3955                && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
3956                && useExponentialNotation == other.useExponentialNotation
3957                && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
3958                && useSignificantDigits == other.useSignificantDigits
3959                && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
3960                        && maxSignificantDigits == other.maxSignificantDigits)
3961                && symbols.equals(other.symbols)
3962                && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo)
3963                && currencyUsage.equals(other.currencyUsage);
3964    }
3965
3966    // method to unquote the strings and compare
3967    private boolean equals(String pat1, String pat2) {
3968        if (pat1 == null || pat2 == null) {
3969            return (pat1 == null && pat2 == null);
3970        }
3971        // fast path
3972        if (pat1.equals(pat2)) {
3973            return true;
3974        }
3975        return unquote(pat1).equals(unquote(pat2));
3976    }
3977
3978    private String unquote(String pat) {
3979        StringBuilder buf = new StringBuilder(pat.length());
3980        int i = 0;
3981        while (i < pat.length()) {
3982            char ch = pat.charAt(i++);
3983            if (ch != QUOTE) {
3984                buf.append(ch);
3985            }
3986        }
3987        return buf.toString();
3988    }
3989
3990    // protected void handleToString(StringBuffer buf) {
3991    // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
3992    // buf.append("positivePrefix: '" + positivePrefix + "'\n");
3993    // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
3994    // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
3995    // buf.append("negPrefixPattern: '" +
3996    //     android.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
3997    // buf.append("negativePrefix: '" +
3998    //     android.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
3999    // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
4000    // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
4001    // buf.append("multiplier: '" + multiplier + "'\n");
4002    // buf.append("groupingSize: '" + groupingSize + "'\n");
4003    // buf.append("groupingSize2: '" + groupingSize2 + "'\n");
4004    // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
4005    // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
4006    // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
4007    // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
4008    // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
4009    // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
4010    // buf.append("symbols: '" + symbols + "'");
4011    // }
4012
4013    /**
4014     * Overrides hashCode.
4015     */
4016    @Override
4017    public int hashCode() {
4018        return super.hashCode() * 37 + positivePrefix.hashCode();
4019        // just enough fields for a reasonable distribution
4020    }
4021
4022    /**
4023     * Synthesizes a pattern string that represents the current state of this Format
4024     * object.
4025     *
4026     * @see #applyPattern
4027     */
4028    public String toPattern() {
4029        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
4030            // the prefix or suffix pattern might not be defined yet, so they can not be
4031            // synthesized, instead, get them directly.  but it might not be the actual
4032            // pattern used in formatting.  the actual pattern used in formatting depends
4033            // on the formatted number's plural count.
4034            return formatPattern;
4035        }
4036        return toPattern(false);
4037    }
4038
4039    /**
4040     * Synthesizes a localized pattern string that represents the current state of this
4041     * Format object.
4042     *
4043     * @see #applyPattern
4044     */
4045    public String toLocalizedPattern() {
4046        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
4047            return formatPattern;
4048        }
4049        return toPattern(true);
4050    }
4051
4052    /**
4053     * Expands the affix pattern strings into the expanded affix strings. If any affix
4054     * pattern string is null, do not expand it. This method should be called any time the
4055     * symbols or the affix patterns change in order to keep the expanded affix strings up
4056     * to date. This method also will be called before formatting if format currency
4057     * plural names, since the plural name is not a static one, it is based on the
4058     * currency plural count, the affix will be known only after the currency plural count
4059     * is know. In which case, the parameter 'pluralCount' will be a non-null currency
4060     * plural count. In all other cases, the 'pluralCount' is null, which means it is not
4061     * needed.
4062     */
4063    // Bug 4212072 [Richard/GCL]
4064    private void expandAffixes(String pluralCount) {
4065        // expandAffix() will set currencyChoice to a non-null value if
4066        // appropriate AND if it is null.
4067        currencyChoice = null;
4068
4069        // Reuse one StringBuffer for better performance
4070        StringBuffer buffer = new StringBuffer();
4071        if (posPrefixPattern != null) {
4072            expandAffix(posPrefixPattern, pluralCount, buffer);
4073            positivePrefix = buffer.toString();
4074        }
4075        if (posSuffixPattern != null) {
4076            expandAffix(posSuffixPattern, pluralCount, buffer);
4077            positiveSuffix = buffer.toString();
4078        }
4079        if (negPrefixPattern != null) {
4080            expandAffix(negPrefixPattern, pluralCount, buffer);
4081            negativePrefix = buffer.toString();
4082        }
4083        if (negSuffixPattern != null) {
4084            expandAffix(negSuffixPattern, pluralCount, buffer);
4085            negativeSuffix = buffer.toString();
4086        }
4087    }
4088
4089    /**
4090     * Expands an affix pattern into an affix string. All characters in the pattern are
4091     * literal unless bracketed by QUOTEs. The following characters outside QUOTE are
4092     * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
4093     * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international
4094     * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural
4095     * long names, such as "US Dollars". Any other character outside QUOTE represents
4096     * itself. Quoted text must be well-formed.
4097     *
4098     * This method is used in two distinct ways. First, it is used to expand the stored
4099     * affix patterns into actual affixes. For this usage, doFormat must be false. Second,
4100     * it is used to expand the stored affix patterns given a specific number (doFormat ==
4101     * true), for those rare cases in which a currency format references a ChoiceFormat
4102     * (e.g., en_IN display name for INR). The number itself is taken from digitList.
4103     * TODO: There are no currency ChoiceFormat patterns, figure out what is still relevant here.
4104     *
4105     * When used in the first way, this method has a side effect: It sets currencyChoice
4106     * to a ChoiceFormat object, if the currency's display name in this locale is a
4107     * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to
4108     * start with.
4109     *
4110     * @param pattern the non-null, possibly empty pattern
4111     * @param pluralCount the plural count. It is only used for currency plural format. In
4112     * which case, it is the plural count of the currency amount. For example, in en_US,
4113     * it is the singular "one", or the plural "other". For all other cases, it is null,
4114     * and is not being used.
4115     * @param buffer a scratch StringBuffer; its contents will be lost
4116     */
4117    // Bug 4212072 [Richard/GCL]
4118    private void expandAffix(String pattern, String pluralCount, StringBuffer buffer) {
4119        buffer.setLength(0);
4120        for (int i = 0; i < pattern.length();) {
4121            char c = pattern.charAt(i++);
4122            if (c == QUOTE) {
4123                for (;;) {
4124                    int j = pattern.indexOf(QUOTE, i);
4125                    if (j == i) {
4126                        buffer.append(QUOTE);
4127                        i = j + 1;
4128                        break;
4129                    } else if (j > i) {
4130                        buffer.append(pattern.substring(i, j));
4131                        i = j + 1;
4132                        if (i < pattern.length() && pattern.charAt(i) == QUOTE) {
4133                            buffer.append(QUOTE);
4134                            ++i;
4135                            // loop again
4136                        } else {
4137                            break;
4138                        }
4139                    } else {
4140                        // Unterminated quote; should be caught by apply
4141                        // pattern.
4142                        throw new RuntimeException();
4143                    }
4144                }
4145                continue;
4146            }
4147
4148            switch (c) {
4149            case CURRENCY_SIGN:
4150                // As of ICU 2.2 we use the currency object, and ignore the currency
4151                // symbols in the DFS, unless we have a null currency object. This occurs
4152                // if resurrecting a pre-2.2 object or if the user sets a custom DFS.
4153                boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN;
4154                boolean plural = false;
4155                if (intl) {
4156                    ++i;
4157                    if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) {
4158                        plural = true;
4159                        intl = false;
4160                        ++i;
4161                    }
4162                }
4163                String s = null;
4164                Currency currency = getCurrency();
4165                if (currency != null) {
4166                    // plural name is only needed when pluralCount != null, which means
4167                    // when formatting currency plural names.  For other cases,
4168                    // pluralCount == null, and plural names are not needed.
4169                    if (plural && pluralCount != null) {
4170                        s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,
4171                                             pluralCount, null);
4172                    } else if (!intl) {
4173                        s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, null);
4174                    } else {
4175                        s = currency.getCurrencyCode();
4176                    }
4177                } else {
4178                    s = intl ? symbols.getInternationalCurrencySymbol() :
4179                        symbols.getCurrencySymbol();
4180                }
4181                // Here is where FieldPosition could be set for CURRENCY PLURAL.
4182                buffer.append(s);
4183                break;
4184            case PATTERN_PERCENT:
4185                buffer.append(symbols.getPercentString());
4186                break;
4187            case PATTERN_PER_MILLE:
4188                buffer.append(symbols.getPerMillString());
4189                break;
4190            case PATTERN_MINUS_SIGN:
4191                buffer.append(symbols.getMinusSignString());
4192                break;
4193            default:
4194                buffer.append(c);
4195                break;
4196            }
4197        }
4198    }
4199
4200    /**
4201     * Append an affix to the given StringBuffer.
4202     *
4203     * @param buf
4204     *            buffer to append to
4205     * @param isNegative
4206     * @param isPrefix
4207     * @param fieldPosition
4208     * @param parseAttr
4209     */
4210    private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,
4211                            FieldPosition fieldPosition,
4212                            boolean parseAttr) {
4213        if (currencyChoice != null) {
4214            String affixPat = null;
4215            if (isPrefix) {
4216                affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
4217            } else {
4218                affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
4219            }
4220            StringBuffer affixBuf = new StringBuffer();
4221            expandAffix(affixPat, null, affixBuf);
4222            buf.append(affixBuf);
4223            return affixBuf.length();
4224        }
4225
4226        String affix = null;
4227        String pattern;
4228        if (isPrefix) {
4229            affix = isNegative ? negativePrefix : positivePrefix;
4230            pattern = isNegative ? negPrefixPattern : posPrefixPattern;
4231        } else {
4232            affix = isNegative ? negativeSuffix : positiveSuffix;
4233            pattern = isNegative ? negSuffixPattern : posSuffixPattern;
4234        }
4235        // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
4236        if (parseAttr) {
4237            // Updates for Ticket 11805.
4238            int offset = affix.indexOf(symbols.getCurrencySymbol());
4239            if (offset > -1) {
4240                formatAffix2Attribute(isPrefix, Field.CURRENCY, buf, offset,
4241                        symbols.getCurrencySymbol().length());
4242            }
4243            offset = affix.indexOf(symbols.getMinusSignString());
4244            if (offset > -1) {
4245                formatAffix2Attribute(isPrefix, Field.SIGN, buf, offset,
4246                        symbols.getMinusSignString().length());
4247            }
4248            offset = affix.indexOf(symbols.getPercentString());
4249            if (offset > -1) {
4250                formatAffix2Attribute(isPrefix, Field.PERCENT, buf, offset,
4251                        symbols.getPercentString().length());
4252            }
4253            offset = affix.indexOf(symbols.getPerMillString());
4254            if (offset > -1) {
4255                formatAffix2Attribute(isPrefix, Field.PERMILLE, buf, offset,
4256                        symbols.getPerMillString().length());
4257            }
4258            offset = pattern.indexOf("¤¤¤");
4259            if (offset > -1) {
4260                formatAffix2Attribute(isPrefix, Field.CURRENCY, buf, offset,
4261                        affix.length() - offset);
4262            }
4263        }
4264
4265        // Look for SIGN, PERCENT, PERMILLE in the formatted affix.
4266        if (fieldPosition.getFieldAttribute() == NumberFormat.Field.SIGN) {
4267            String sign = isNegative ? symbols.getMinusSignString() : symbols.getPlusSignString();
4268            int firstPos = affix.indexOf(sign);
4269            if (firstPos > -1) {
4270                int startPos = buf.length() + firstPos;
4271                fieldPosition.setBeginIndex(startPos);
4272                fieldPosition.setEndIndex(startPos + sign.length());
4273            }
4274        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERCENT) {
4275            int firstPos = affix.indexOf(symbols.getPercentString());
4276            if (firstPos > -1) {
4277                int startPos = buf.length() + firstPos;
4278                fieldPosition.setBeginIndex(startPos);
4279                fieldPosition.setEndIndex(startPos + symbols.getPercentString().length());
4280            }
4281        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERMILLE) {
4282            int firstPos = affix.indexOf(symbols.getPerMillString());
4283            if (firstPos > -1) {
4284                int startPos = buf.length() + firstPos;
4285                fieldPosition.setBeginIndex(startPos);
4286                fieldPosition.setEndIndex(startPos + symbols.getPerMillString().length());
4287            }
4288        } else
4289        // If CurrencySymbol or InternationalCurrencySymbol is in the affix, check for currency symbol.
4290        // Get spelled out name if "¤¤¤" is in the pattern.
4291        if (fieldPosition.getFieldAttribute() == NumberFormat.Field.CURRENCY) {
4292            if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
4293                String aff = symbols.getCurrencySymbol();
4294                int firstPos = affix.indexOf(aff);
4295                int start = buf.length() + firstPos;
4296                int end = start + aff.length();
4297                fieldPosition.setBeginIndex(start);
4298                fieldPosition.setEndIndex(end);
4299            } else if (affix.indexOf(symbols.getInternationalCurrencySymbol()) > -1) {
4300                String aff = symbols.getInternationalCurrencySymbol();
4301                int firstPos = affix.indexOf(aff);
4302                int start = buf.length() + firstPos;
4303                int end = start + aff.length();
4304                fieldPosition.setBeginIndex(start);
4305                fieldPosition.setEndIndex(end);
4306            } else if (pattern.indexOf("¤¤¤") > -1) {
4307                // It's a plural, and we know where it is in the pattern.
4308                int firstPos = pattern.indexOf("¤¤¤");
4309                int start = buf.length() + firstPos;
4310                int end = buf.length() + affix.length(); // This seems clunky and wrong.
4311                fieldPosition.setBeginIndex(start);
4312                fieldPosition.setEndIndex(end);
4313            }
4314        }
4315
4316        buf.append(affix);
4317        return affix.length();
4318    }
4319
4320    // Fix for prefix and suffix in Ticket 11805.
4321    private void formatAffix2Attribute(boolean isPrefix, Field fieldType,
4322        StringBuffer buf, int offset, int symbolSize) {
4323        int begin;
4324        begin = offset;
4325        if (!isPrefix) {
4326            begin += buf.length();
4327        }
4328
4329        addAttribute(fieldType, begin, begin + symbolSize);
4330    }
4331
4332    /**
4333     * [Spark/CDL] Use this method to add attribute.
4334     */
4335    private void addAttribute(Field field, int begin, int end) {
4336        FieldPosition pos = new FieldPosition(field);
4337        pos.setBeginIndex(begin);
4338        pos.setEndIndex(end);
4339        attributes.add(pos);
4340    }
4341
4342    /**
4343     * Formats the object to an attributed string, and return the corresponding iterator.
4344     */
4345    @Override
4346    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
4347      return formatToCharacterIterator(obj, NULL_UNIT);
4348    }
4349
4350    AttributedCharacterIterator formatToCharacterIterator(Object obj, Unit unit) {
4351        if (!(obj instanceof Number))
4352            throw new IllegalArgumentException();
4353        Number number = (Number) obj;
4354        StringBuffer text = new StringBuffer();
4355        unit.writePrefix(text);
4356        attributes.clear();
4357        if (obj instanceof BigInteger) {
4358            format((BigInteger) number, text, new FieldPosition(0), true);
4359        } else if (obj instanceof java.math.BigDecimal) {
4360            format((java.math.BigDecimal) number, text, new FieldPosition(0)
4361                          , true);
4362        } else if (obj instanceof Double) {
4363            format(number.doubleValue(), text, new FieldPosition(0), true);
4364        } else if (obj instanceof Integer || obj instanceof Long) {
4365            format(number.longValue(), text, new FieldPosition(0), true);
4366        } else {
4367            throw new IllegalArgumentException();
4368        }
4369        unit.writeSuffix(text);
4370        AttributedString as = new AttributedString(text.toString());
4371
4372        // add NumberFormat field attributes to the AttributedString
4373        for (int i = 0; i < attributes.size(); i++) {
4374            FieldPosition pos = attributes.get(i);
4375            Format.Field attribute = pos.getFieldAttribute();
4376            as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());
4377        }
4378
4379        // return the CharacterIterator from AttributedString
4380        return as.getIterator();
4381    }
4382
4383    /**
4384     * Appends an affix pattern to the given StringBuffer. Localize unquoted specials.
4385     * <p>
4386     * <b>Note:</b> This implementation does not support new String localized symbols.
4387     */
4388    private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,
4389                                    boolean localized) {
4390        String affixPat = null;
4391        if (isPrefix) {
4392            affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
4393        } else {
4394            affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
4395        }
4396
4397        // When there is a null affix pattern, we use the affix itself.
4398        if (affixPat == null) {
4399            String affix = null;
4400            if (isPrefix) {
4401                affix = isNegative ? negativePrefix : positivePrefix;
4402            } else {
4403                affix = isNegative ? negativeSuffix : positiveSuffix;
4404            }
4405            // Do this crudely for now: Wrap everything in quotes.
4406            buffer.append(QUOTE);
4407            for (int i = 0; i < affix.length(); ++i) {
4408                char ch = affix.charAt(i);
4409                if (ch == QUOTE) {
4410                    buffer.append(ch);
4411                }
4412                buffer.append(ch);
4413            }
4414            buffer.append(QUOTE);
4415            return;
4416        }
4417
4418        if (!localized) {
4419            buffer.append(affixPat);
4420        } else {
4421            int i, j;
4422            for (i = 0; i < affixPat.length(); ++i) {
4423                char ch = affixPat.charAt(i);
4424                switch (ch) {
4425                case QUOTE:
4426                    j = affixPat.indexOf(QUOTE, i + 1);
4427                    if (j < 0) {
4428                        throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
4429                    }
4430                    buffer.append(affixPat.substring(i, j + 1));
4431                    i = j;
4432                    continue;
4433                case PATTERN_PER_MILLE:
4434                    ch = symbols.getPerMill();
4435                    break;
4436                case PATTERN_PERCENT:
4437                    ch = symbols.getPercent();
4438                    break;
4439                case PATTERN_MINUS_SIGN:
4440                    ch = symbols.getMinusSign();
4441                    break;
4442                }
4443                // check if char is same as any other symbol
4444                if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) {
4445                    buffer.append(QUOTE);
4446                    buffer.append(ch);
4447                    buffer.append(QUOTE);
4448                } else {
4449                    buffer.append(ch);
4450                }
4451            }
4452        }
4453    }
4454
4455    /**
4456     * Does the real work of generating a pattern.
4457     * <p>
4458     * <b>Note:</b> This implementation does not support new String localized symbols.
4459     */
4460    private String toPattern(boolean localized) {
4461        StringBuffer result = new StringBuffer();
4462        char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
4463        char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
4464        char sigDigit = 0;
4465        boolean useSigDig = areSignificantDigitsUsed();
4466        if (useSigDig) {
4467            sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
4468        }
4469        char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR;
4470        int i;
4471        int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
4472        String roundingDigits = null;
4473        int padPos = (formatWidth > 0) ? padPosition : -1;
4474        String padSpec = (formatWidth > 0)
4475            ? new StringBuffer(2).append(localized
4476                                         ? symbols.getPadEscape()
4477                                         : PATTERN_PAD_ESCAPE).append(pad).toString()
4478            : null;
4479        if (roundingIncrementICU != null) {
4480            i = roundingIncrementICU.scale();
4481            roundingDigits = roundingIncrementICU.movePointRight(i).toString();
4482            roundingDecimalPos = roundingDigits.length() - i;
4483        }
4484        for (int part = 0; part < 2; ++part) {
4485            // variable not used int partStart = result.length();
4486            if (padPos == PAD_BEFORE_PREFIX) {
4487                result.append(padSpec);
4488            }
4489
4490            // Use original symbols read from resources in pattern eg. use "\u00A4"
4491            // instead of "$" in Locale.US [Richard/GCL]
4492            appendAffixPattern(result, part != 0, true, localized);
4493            if (padPos == PAD_AFTER_PREFIX) {
4494                result.append(padSpec);
4495            }
4496            int sub0Start = result.length();
4497            int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
4498            if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
4499                g += groupingSize2;
4500            }
4501            int maxDig = 0, minDig = 0, maxSigDig = 0;
4502            if (useSigDig) {
4503                minDig = getMinimumSignificantDigits();
4504                maxDig = maxSigDig = getMaximumSignificantDigits();
4505            } else {
4506                minDig = getMinimumIntegerDigits();
4507                maxDig = getMaximumIntegerDigits();
4508            }
4509            if (useExponentialNotation) {
4510                if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
4511                    maxDig = 1;
4512                }
4513            } else if (useSigDig) {
4514                maxDig = Math.max(maxDig, g + 1);
4515            } else {
4516                maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1;
4517            }
4518            for (i = maxDig; i > 0; --i) {
4519                if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) {
4520                    result.append(group);
4521                }
4522                if (useSigDig) {
4523                    // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos,
4524                    // count from the right) Use # if pos > maxSigDig or 1 <= pos <=
4525                    // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <=
4526                    // maxSigDig
4527                    result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
4528                } else {
4529                    if (roundingDigits != null) {
4530                        int pos = roundingDecimalPos - i;
4531                        if (pos >= 0 && pos < roundingDigits.length()) {
4532                            result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
4533                            continue;
4534                        }
4535                    }
4536                    result.append(i <= minDig ? zero : digit);
4537                }
4538            }
4539            if (!useSigDig) {
4540                if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
4541                    result.append(localized ? symbols.getDecimalSeparator() :
4542                                  PATTERN_DECIMAL_SEPARATOR);
4543                }
4544                int pos = roundingDecimalPos;
4545                for (i = 0; i < getMaximumFractionDigits(); ++i) {
4546                    if (roundingDigits != null && pos < roundingDigits.length()) {
4547                        result.append(pos < 0 ? zero :
4548                                      (char) (roundingDigits.charAt(pos) - '0' + zero));
4549                        ++pos;
4550                        continue;
4551                    }
4552                    result.append(i < getMinimumFractionDigits() ? zero : digit);
4553                }
4554            }
4555            if (useExponentialNotation) {
4556                if (localized) {
4557                    result.append(symbols.getExponentSeparator());
4558                } else {
4559                    result.append(PATTERN_EXPONENT);
4560                }
4561                if (exponentSignAlwaysShown) {
4562                    result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN);
4563                }
4564                for (i = 0; i < minExponentDigits; ++i) {
4565                    result.append(zero);
4566                }
4567            }
4568            if (padSpec != null && !useExponentialNotation) {
4569                int add = formatWidth
4570                        - result.length()
4571                        + sub0Start
4572                        - ((part == 0)
4573                           ? positivePrefix.length() + positiveSuffix.length()
4574                           : negativePrefix.length() + negativeSuffix.length());
4575                while (add > 0) {
4576                    result.insert(sub0Start, digit);
4577                    ++maxDig;
4578                    --add;
4579                    // Only add a grouping separator if we have at least 2 additional
4580                    // characters to be added, so we don't end up with ",###".
4581                    if (add > 1 && isGroupingPosition(maxDig)) {
4582                        result.insert(sub0Start, group);
4583                        --add;
4584                    }
4585                }
4586            }
4587            if (padPos == PAD_BEFORE_SUFFIX) {
4588                result.append(padSpec);
4589            }
4590            // Use original symbols read from resources in pattern eg. use "\u00A4"
4591            // instead of "$" in Locale.US [Richard/GCL]
4592            appendAffixPattern(result, part != 0, false, localized);
4593            if (padPos == PAD_AFTER_SUFFIX) {
4594                result.append(padSpec);
4595            }
4596            if (part == 0) {
4597                if (negativeSuffix.equals(positiveSuffix) &&
4598                    negativePrefix.equals(PATTERN_MINUS_SIGN + positivePrefix)) {
4599                    break;
4600                } else {
4601                    result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);
4602                }
4603            }
4604        }
4605        return result.toString();
4606    }
4607
4608    /**
4609     * Applies the given pattern to this Format object. A pattern is a short-hand
4610     * specification for the various formatting properties. These properties can also be
4611     * changed individually through the various setter methods.
4612     *
4613     * <p>There is no limit to integer digits are set by this routine, since that is the
4614     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
4615     * negative numbers, use a second pattern, separated by a semicolon
4616     *
4617     * <p>Example "#,#00.0#" -&gt; 1,234.56
4618     *
4619     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
4620     * fraction digits.
4621     *
4622     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
4623     *
4624     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
4625     * presumed to be set in the positive pattern.
4626     */
4627    public void applyPattern(String pattern) {
4628        applyPattern(pattern, false);
4629    }
4630
4631    /**
4632     * Applies the given pattern to this Format object. The pattern is assumed to be in a
4633     * localized notation. A pattern is a short-hand specification for the various
4634     * formatting properties. These properties can also be changed individually through
4635     * the various setter methods.
4636     *
4637     * <p>There is no limit to integer digits are set by this routine, since that is the
4638     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
4639     * negative numbers, use a second pattern, separated by a semicolon
4640     *
4641     * <p>Example "#,#00.0#" -&gt; 1,234.56
4642     *
4643     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
4644     * fraction digits.
4645     *
4646     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
4647     *
4648     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
4649     * presumed to be set in the positive pattern.
4650     */
4651    public void applyLocalizedPattern(String pattern) {
4652        applyPattern(pattern, true);
4653    }
4654
4655    /**
4656     * Does the real work of applying a pattern.
4657     */
4658    private void applyPattern(String pattern, boolean localized) {
4659        applyPatternWithoutExpandAffix(pattern, localized);
4660        expandAffixAdjustWidth(null);
4661    }
4662
4663    private void expandAffixAdjustWidth(String pluralCount) {
4664        // Bug 4212072 Update the affix strings according to symbols in order to keep the
4665        // affix strings up to date.  [Richard/GCL]
4666        expandAffixes(pluralCount);
4667
4668        // Now that we have the actual prefix and suffix, fix up formatWidth
4669        if (formatWidth > 0) {
4670            formatWidth += positivePrefix.length() + positiveSuffix.length();
4671        }
4672    }
4673
4674    private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
4675        char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
4676        char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
4677        char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
4678        char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
4679        char percent = PATTERN_PERCENT;
4680        char perMill = PATTERN_PER_MILLE;
4681        char digit = PATTERN_DIGIT; // '#'
4682        char separator = PATTERN_SEPARATOR;
4683        String exponent = String.valueOf(PATTERN_EXPONENT);
4684        char plus = PATTERN_PLUS_SIGN;
4685        char padEscape = PATTERN_PAD_ESCAPE;
4686        char minus = PATTERN_MINUS_SIGN; // Bug 4212072 [Richard/GCL]
4687        if (localized) {
4688            zeroDigit = symbols.getZeroDigit();
4689            sigDigit = symbols.getSignificantDigit();
4690            groupingSeparator = symbols.getGroupingSeparator();
4691            decimalSeparator = symbols.getDecimalSeparator();
4692            percent = symbols.getPercent();
4693            perMill = symbols.getPerMill();
4694            digit = symbols.getDigit();
4695            separator = symbols.getPatternSeparator();
4696            exponent = symbols.getExponentSeparator();
4697            plus = symbols.getPlusSign();
4698            padEscape = symbols.getPadEscape();
4699            minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL]
4700        }
4701        char nineDigit = (char) (zeroDigit + 9);
4702
4703        boolean gotNegative = false;
4704
4705        int pos = 0;
4706        // Part 0 is the positive pattern. Part 1, if present, is the negative
4707        // pattern.
4708        for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
4709            // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,
4710            // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and
4711            // suffix, and consists of pattern characters. In the prefix and suffix,
4712            // percent, permille, and currency symbols are recognized and translated.
4713            int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
4714
4715            // It's important that we don't change any fields of this object
4716            // prematurely. We set the following variables for the multiplier, grouping,
4717            // etc., and then only change the actual object fields if everything parses
4718            // correctly. This also lets us register the data from part 0 and ignore the
4719            // part 1, except for the prefix and suffix.
4720            StringBuilder prefix = new StringBuilder();
4721            StringBuilder suffix = new StringBuilder();
4722            int decimalPos = -1;
4723            int multpl = 1;
4724            int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
4725            byte groupingCount = -1;
4726            byte groupingCount2 = -1;
4727            int padPos = -1;
4728            char padChar = 0;
4729            int incrementPos = -1;
4730            long incrementVal = 0;
4731            byte expDigits = -1;
4732            boolean expSignAlways = false;
4733            int currencySignCnt = 0;
4734
4735            // The affix is either the prefix or the suffix.
4736            StringBuilder affix = prefix;
4737
4738            int start = pos;
4739
4740            PARTLOOP: for (; pos < pattern.length(); ++pos) {
4741                char ch = pattern.charAt(pos);
4742                switch (subpart) {
4743                case 0: // Pattern proper subpart (between prefix & suffix)
4744                    // Process the digits, decimal, and grouping characters. We record
4745                    // five pieces of information. We expect the digits to occur in the
4746                    // pattern ####00.00####, and we record the number of left digits,
4747                    // zero (central) digits, and right digits. The position of the last
4748                    // grouping character is recorded (should be somewhere within the
4749                    // first two blocks of characters), as is the position of the decimal
4750                    // point, if any (should be in the zero digits). If there is no
4751                    // decimal point, then there should be no right digits.
4752                    if (ch == digit) {
4753                        if (zeroDigitCount > 0 || sigDigitCount > 0) {
4754                            ++digitRightCount;
4755                        } else {
4756                            ++digitLeftCount;
4757                        }
4758                        if (groupingCount >= 0 && decimalPos < 0) {
4759                            ++groupingCount;
4760                        }
4761                    } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
4762                        if (digitRightCount > 0) {
4763                            patternError("Unexpected '" + ch + '\'', pattern);
4764                        }
4765                        if (ch == sigDigit) {
4766                            ++sigDigitCount;
4767                        } else {
4768                            ++zeroDigitCount;
4769                            if (ch != zeroDigit) {
4770                                int p = digitLeftCount + zeroDigitCount + digitRightCount;
4771                                if (incrementPos >= 0) {
4772                                    while (incrementPos < p) {
4773                                        incrementVal *= 10;
4774                                        ++incrementPos;
4775                                    }
4776                                } else {
4777                                    incrementPos = p;
4778                                }
4779                                incrementVal += ch - zeroDigit;
4780                            }
4781                        }
4782                        if (groupingCount >= 0 && decimalPos < 0) {
4783                            ++groupingCount;
4784                        }
4785                    } else if (ch == groupingSeparator) {
4786                        // Bug 4212072 process the Localized pattern like
4787                        // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator
4788                        // == QUOTE) [Richard/GCL]
4789                        if (ch == QUOTE && (pos + 1) < pattern.length()) {
4790                            char after = pattern.charAt(pos + 1);
4791                            if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
4792                                // A quote outside quotes indicates either the opening
4793                                // quote or two quotes, which is a quote literal. That is,
4794                                // we have the first quote in 'do' or o''clock.
4795                                if (after == QUOTE) {
4796                                    ++pos;
4797                                    // Fall through to append(ch)
4798                                } else {
4799                                    if (groupingCount < 0) {
4800                                        subpart = 3; // quoted prefix subpart
4801                                    } else {
4802                                        // Transition to suffix subpart
4803                                        subpart = 2; // suffix subpart
4804                                        affix = suffix;
4805                                        sub0Limit = pos--;
4806                                    }
4807                                    continue;
4808                                }
4809                            }
4810                        }
4811
4812                        if (decimalPos >= 0) {
4813                            patternError("Grouping separator after decimal", pattern);
4814                        }
4815                        groupingCount2 = groupingCount;
4816                        groupingCount = 0;
4817                    } else if (ch == decimalSeparator) {
4818                        if (decimalPos >= 0) {
4819                            patternError("Multiple decimal separators", pattern);
4820                        }
4821                        // Intentionally incorporate the digitRightCount, even though it
4822                        // is illegal for this to be > 0 at this point. We check pattern
4823                        // syntax below.
4824                        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
4825                    } else {
4826                        if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
4827                            if (expDigits >= 0) {
4828                                patternError("Multiple exponential symbols", pattern);
4829                            }
4830                            if (groupingCount >= 0) {
4831                                patternError("Grouping separator in exponential", pattern);
4832                            }
4833                            pos += exponent.length();
4834                            // Check for positive prefix
4835                            if (pos < pattern.length() && pattern.charAt(pos) == plus) {
4836                                expSignAlways = true;
4837                                ++pos;
4838                            }
4839                            // Use lookahead to parse out the exponential part of the
4840                            // pattern, then jump into suffix subpart.
4841                            expDigits = 0;
4842                            while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {
4843                                ++expDigits;
4844                                ++pos;
4845                            }
4846
4847                            // 1. Require at least one mantissa pattern digit
4848                            // 2. Disallow "#+ @" in mantissa
4849                            // 3. Require at least one exponent pattern digit
4850                            if (((digitLeftCount + zeroDigitCount) < 1 &&
4851                                 (sigDigitCount + digitRightCount) < 1)
4852                                || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {
4853                                patternError("Malformed exponential", pattern);
4854                            }
4855                        }
4856                        // Transition to suffix subpart
4857                        subpart = 2; // suffix subpart
4858                        affix = suffix;
4859                        sub0Limit = pos--; // backup: for() will increment
4860                        continue;
4861                    }
4862                    break;
4863                case 1: // Prefix subpart
4864                case 2: // Suffix subpart
4865                    // Process the prefix / suffix characters Process unquoted characters
4866                    // seen in prefix or suffix subpart.
4867
4868                    // Several syntax characters implicitly begins the next subpart if we
4869                    // are in the prefix; otherwise they are illegal if unquoted.
4870                    if (ch == digit || ch == groupingSeparator || ch == decimalSeparator
4871                            || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
4872                        // Any of these characters implicitly begins the
4873                        // next subpart if we are in the prefix
4874                        if (subpart == 1) { // prefix subpart
4875                            subpart = 0; // pattern proper subpart
4876                            sub0Start = pos--; // Reprocess this character
4877                            continue;
4878                        } else if (ch == QUOTE) {
4879                            // Bug 4212072 process the Localized pattern like
4880                            // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH",
4881                            // groupingSeparator == QUOTE) [Richard/GCL]
4882
4883                            // A quote outside quotes indicates either the opening quote
4884                            // or two quotes, which is a quote literal. That is, we have
4885                            // the first quote in 'do' or o''clock.
4886                            if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
4887                                ++pos;
4888                                affix.append(ch);
4889                            } else {
4890                                subpart += 2; // open quote
4891                            }
4892                            continue;
4893                        }
4894                        patternError("Unquoted special character '" + ch + '\'', pattern);
4895                    } else if (ch == CURRENCY_SIGN) {
4896                        // Use lookahead to determine if the currency sign is
4897                        // doubled or not.
4898                        boolean doubled = (pos + 1) < pattern.length() &&
4899                            pattern.charAt(pos + 1) == CURRENCY_SIGN;
4900
4901                        // Bug 4212072 To meet the need of expandAffix(String,
4902                        // StirngBuffer) [Richard/GCL]
4903                        if (doubled) {
4904                            ++pos; // Skip over the doubled character
4905                            affix.append(ch); // append two: one here, one below
4906                            if ((pos + 1) < pattern.length() &&
4907                                pattern.charAt(pos + 1) == CURRENCY_SIGN) {
4908                                ++pos; // Skip over the tripled character
4909                                affix.append(ch); // append again
4910                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
4911                            } else {
4912                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
4913                            }
4914                        } else {
4915                            currencySignCnt = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
4916                        }
4917                        // Fall through to append(ch)
4918                    } else if (ch == QUOTE) {
4919                        // A quote outside quotes indicates either the opening quote or
4920                        // two quotes, which is a quote literal. That is, we have the
4921                        // first quote in 'do' or o''clock.
4922                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
4923                            ++pos;
4924                            affix.append(ch); // append two: one here, one below
4925                        } else {
4926                            subpart += 2; // open quote
4927                        }
4928                        // Fall through to append(ch)
4929                    } else if (ch == separator) {
4930                        // Don't allow separators in the prefix, and don't allow
4931                        // separators in the second pattern (part == 1).
4932                        if (subpart == 1 || part == 1) {
4933                            patternError("Unquoted special character '" + ch + '\'', pattern);
4934                        }
4935                        sub2Limit = pos++;
4936                        break PARTLOOP; // Go to next part
4937                    } else if (ch == percent || ch == perMill) {
4938                        // Next handle characters which are appended directly.
4939                        if (multpl != 1) {
4940                            patternError("Too many percent/permille characters", pattern);
4941                        }
4942                        multpl = (ch == percent) ? 100 : 1000;
4943                        // Convert to non-localized pattern
4944                        ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
4945                        // Fall through to append(ch)
4946                    } else if (ch == minus) {
4947                        // Convert to non-localized pattern
4948                        ch = PATTERN_MINUS_SIGN;
4949                        // Fall through to append(ch)
4950                    } else if (ch == padEscape) {
4951                        if (padPos >= 0) {
4952                            patternError("Multiple pad specifiers", pattern);
4953                        }
4954                        if ((pos + 1) == pattern.length()) {
4955                            patternError("Invalid pad specifier", pattern);
4956                        }
4957                        padPos = pos++; // Advance past pad char
4958                        padChar = pattern.charAt(pos);
4959                        continue;
4960                    }
4961                    affix.append(ch);
4962                    break;
4963                case 3: // Prefix subpart, in quote
4964                case 4: // Suffix subpart, in quote
4965                    // A quote within quotes indicates either the closing quote or two
4966                    // quotes, which is a quote literal. That is, we have the second quote
4967                    // in 'do' or 'don''t'.
4968                    if (ch == QUOTE) {
4969                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
4970                            ++pos;
4971                            affix.append(ch);
4972                        } else {
4973                            subpart -= 2; // close quote
4974                        }
4975                        // Fall through to append(ch)
4976                    }
4977                    // NOTE: In ICU 2.2 there was code here to parse quoted percent and
4978                    // permille characters _within quotes_ and give them special
4979                    // meaning. This is incorrect, since quoted characters are literals
4980                    // without special meaning.
4981                    affix.append(ch);
4982                    break;
4983                }
4984            }
4985
4986            if (subpart == 3 || subpart == 4) {
4987                patternError("Unterminated quote", pattern);
4988            }
4989
4990            if (sub0Limit == 0) {
4991                sub0Limit = pattern.length();
4992            }
4993
4994            if (sub2Limit == 0) {
4995                sub2Limit = pattern.length();
4996            }
4997
4998            // Handle patterns with no '0' pattern character. These patterns are legal,
4999            // but must be recodified to make sense. "##.###" -> "#0.###". ".###" ->
5000            // ".0##".
5001            //
5002            // We allow patterns of the form "####" to produce a zeroDigitCount of zero
5003            // (got that?); although this seems like it might make it possible for
5004            // format() to produce empty strings, format() checks for this condition and
5005            // outputs a zero digit in this situation. Having a zeroDigitCount of zero
5006            // yields a minimum integer digits of zero, which allows proper round-trip
5007            // patterns. We don't want "#" to become "#0" when toPattern() is called (even
5008            // though that's what it really is, semantically).
5009            if (zeroDigitCount == 0 && sigDigitCount == 0 &&
5010                digitLeftCount > 0 && decimalPos >= 0) {
5011                // Handle "###.###" and "###." and ".###"
5012                int n = decimalPos;
5013                if (n == 0)
5014                    ++n; // Handle ".###"
5015                digitRightCount = digitLeftCount - n;
5016                digitLeftCount = n - 1;
5017                zeroDigitCount = 1;
5018            }
5019
5020            // Do syntax checking on the digits, decimal points, and quotes.
5021            if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)
5022                || (decimalPos >= 0
5023                    && (sigDigitCount > 0
5024                        || decimalPos < digitLeftCount
5025                        || decimalPos > (digitLeftCount + zeroDigitCount)))
5026                || groupingCount == 0
5027                || groupingCount2 == 0
5028                || (sigDigitCount > 0 && zeroDigitCount > 0)
5029                || subpart > 2) { // subpart > 2 == unmatched quote
5030                patternError("Malformed pattern", pattern);
5031            }
5032
5033            // Make sure pad is at legal position before or after affix.
5034            if (padPos >= 0) {
5035                if (padPos == start) {
5036                    padPos = PAD_BEFORE_PREFIX;
5037                } else if (padPos + 2 == sub0Start) {
5038                    padPos = PAD_AFTER_PREFIX;
5039                } else if (padPos == sub0Limit) {
5040                    padPos = PAD_BEFORE_SUFFIX;
5041                } else if (padPos + 2 == sub2Limit) {
5042                    padPos = PAD_AFTER_SUFFIX;
5043                } else {
5044                    patternError("Illegal pad position", pattern);
5045                }
5046            }
5047
5048            if (part == 0) {
5049                // Set negative affixes temporarily to match the positive
5050                // affixes. Fix this up later after processing both parts.
5051
5052                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
5053                // [Richard/GCL]
5054                posPrefixPattern = negPrefixPattern = prefix.toString();
5055                posSuffixPattern = negSuffixPattern = suffix.toString();
5056
5057                useExponentialNotation = (expDigits >= 0);
5058                if (useExponentialNotation) {
5059                    minExponentDigits = expDigits;
5060                    exponentSignAlwaysShown = expSignAlways;
5061                }
5062                int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
5063                // The effectiveDecimalPos is the position the decimal is at or would be
5064                // at if there is no decimal. Note that if decimalPos<0, then
5065                // digitTotalCount == digitLeftCount + zeroDigitCount.
5066                int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
5067                boolean useSigDig = (sigDigitCount > 0);
5068                setSignificantDigitsUsed(useSigDig);
5069                if (useSigDig) {
5070                    setMinimumSignificantDigits(sigDigitCount);
5071                    setMaximumSignificantDigits(sigDigitCount + digitRightCount);
5072                } else {
5073                    int minInt = effectiveDecimalPos - digitLeftCount;
5074                    setMinimumIntegerDigits(minInt);
5075
5076                    // Upper limit on integer and fraction digits for a Java double
5077                    // [Richard/GCL]
5078                    setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt :
5079                                            DOUBLE_INTEGER_DIGITS);
5080                    _setMaximumFractionDigits(decimalPos >= 0 ?
5081                                             (digitTotalCount - decimalPos) : 0);
5082                    setMinimumFractionDigits(decimalPos >= 0 ?
5083                                             (digitLeftCount + zeroDigitCount - decimalPos) : 0);
5084                }
5085                setGroupingUsed(groupingCount > 0);
5086                this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
5087                this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
5088                    ? groupingCount2 : 0;
5089                this.multiplier = multpl;
5090                setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
5091                if (padPos >= 0) {
5092                    padPosition = padPos;
5093                    formatWidth = sub0Limit - sub0Start; // to be fixed up below
5094                    pad = padChar;
5095                } else {
5096                    formatWidth = 0;
5097                }
5098                if (incrementVal != 0) {
5099                    // BigDecimal scale cannot be negative (even though this makes perfect
5100                    // sense), so we need to handle this.
5101                    int scale = incrementPos - effectiveDecimalPos;
5102                    roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
5103                    if (scale < 0) {
5104                        roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);
5105                    }
5106                    roundingMode = BigDecimal.ROUND_HALF_EVEN;
5107                } else {
5108                    setRoundingIncrement((BigDecimal) null);
5109                }
5110
5111                // Update currency sign count for the new pattern
5112                currencySignCount = currencySignCnt;
5113            } else {
5114                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
5115                // [Richard/GCL]
5116                negPrefixPattern = prefix.toString();
5117                negSuffixPattern = suffix.toString();
5118                gotNegative = true;
5119            }
5120        }
5121
5122
5123        // Bug 4140009 Process the empty pattern [Richard/GCL]
5124        if (pattern.length() == 0) {
5125            posPrefixPattern = posSuffixPattern = "";
5126            setMinimumIntegerDigits(0);
5127            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
5128            setMinimumFractionDigits(0);
5129            _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
5130        }
5131
5132        // If there was no negative pattern, or if the negative pattern is identical to
5133        // the positive pattern, then prepend the minus sign to the positive pattern to
5134        // form the negative pattern.
5135
5136        // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
5137
5138        if (!gotNegative ||
5139            (negPrefixPattern.equals(posPrefixPattern)
5140             && negSuffixPattern.equals(posSuffixPattern))) {
5141            negSuffixPattern = posSuffixPattern;
5142            negPrefixPattern = PATTERN_MINUS_SIGN + posPrefixPattern;
5143        }
5144        setLocale(null, null);
5145        // save the pattern
5146        formatPattern = pattern;
5147
5148        // special handlings for currency instance
5149        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
5150            // reset rounding increment and max/min fractional digits
5151            // by the currency
5152            Currency theCurrency = getCurrency();
5153            if (theCurrency != null) {
5154                setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
5155                int d = theCurrency.getDefaultFractionDigits(currencyUsage);
5156                setMinimumFractionDigits(d);
5157                _setMaximumFractionDigits(d);
5158            }
5159
5160            // initialize currencyPluralInfo if needed
5161            if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT
5162                && currencyPluralInfo == null) {
5163                currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
5164            }
5165        }
5166        resetActualRounding();
5167    }
5168
5169
5170    private void patternError(String msg, String pattern) {
5171        throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
5172    }
5173
5174
5175    // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits
5176    // for a Java double [Richard/GCL]
5177
5178    /**
5179     * Sets the maximum number of digits allowed in the integer portion of a number. This
5180     * override limits the integer digit count to 2,000,000,000 to match ICU4C.
5181     *
5182     * @see NumberFormat#setMaximumIntegerDigits
5183     */
5184    @Override
5185    public void setMaximumIntegerDigits(int newValue) {
5186        // Android changed: Allow 2 billion integer digits.
5187        super.setMaximumIntegerDigits(Math.min(newValue, MAX_INTEGER_DIGITS));
5188    }
5189
5190    /**
5191     * Sets the minimum number of digits allowed in the integer portion of a number. This
5192     * override limits the integer digit count to 309.
5193     *
5194     * @see NumberFormat#setMinimumIntegerDigits
5195     */
5196    @Override
5197    public void setMinimumIntegerDigits(int newValue) {
5198        super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
5199    }
5200
5201    /**
5202     * <strong>[icu]</strong> Returns the minimum number of significant digits that will be
5203     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
5204     * returns true.
5205     *
5206     * @return the fewest significant digits that will be shown
5207     */
5208    public int getMinimumSignificantDigits() {
5209        return minSignificantDigits;
5210    }
5211
5212    /**
5213     * <strong>[icu]</strong> Returns the maximum number of significant digits that will be
5214     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
5215     * returns true.
5216     *
5217     * @return the most significant digits that will be shown
5218     */
5219    public int getMaximumSignificantDigits() {
5220        return maxSignificantDigits;
5221    }
5222
5223    /**
5224     * <strong>[icu]</strong> Sets the minimum number of significant digits that will be displayed. If
5225     * <code>min</code> is less than one then it is set to one. If the maximum significant
5226     * digits count is less than <code>min</code>, then it is set to <code>min</code>.
5227     * This function also enables the use of significant digits by this formatter -
5228     * {@link #areSignificantDigitsUsed()} will return true.
5229     *
5230     * @param min the fewest significant digits to be shown
5231     */
5232    public void setMinimumSignificantDigits(int min) {
5233        if (min < 1) {
5234            min = 1;
5235        }
5236        // pin max sig dig to >= min
5237        int max = Math.max(maxSignificantDigits, min);
5238        minSignificantDigits = min;
5239        maxSignificantDigits = max;
5240        setSignificantDigitsUsed(true);
5241    }
5242
5243    /**
5244     * <strong>[icu]</strong> Sets the maximum number of significant digits that will be displayed. If
5245     * <code>max</code> is less than one then it is set to one. If the minimum significant
5246     * digits count is greater than <code>max</code>, then it is set to <code>max</code>.
5247     * This function also enables the use of significant digits by this formatter -
5248     * {@link #areSignificantDigitsUsed()} will return true.
5249     *
5250     * @param max the most significant digits to be shown
5251     */
5252    public void setMaximumSignificantDigits(int max) {
5253        if (max < 1) {
5254            max = 1;
5255        }
5256        // pin min sig dig to 1..max
5257        int min = Math.min(minSignificantDigits, max);
5258        minSignificantDigits = min;
5259        maxSignificantDigits = max;
5260        setSignificantDigitsUsed(true);
5261    }
5262
5263    /**
5264     * <strong>[icu]</strong> Returns true if significant digits are in use or false if integer and
5265     * fraction digit counts are in use.
5266     *
5267     * @return true if significant digits are in use
5268     */
5269    public boolean areSignificantDigitsUsed() {
5270        return useSignificantDigits;
5271    }
5272
5273    /**
5274     * <strong>[icu]</strong> Sets whether significant digits are in use, or integer and fraction digit
5275     * counts are in use.
5276     *
5277     * @param useSignificantDigits true to use significant digits, or false to use integer
5278     * and fraction digit counts
5279     */
5280    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
5281        this.useSignificantDigits = useSignificantDigits;
5282    }
5283
5284    /**
5285     * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
5286     * effect immediately, if this format is a currency format. If this format is not a
5287     * currency format, then the currency object is used if and when this object becomes a
5288     * currency format through the application of a new pattern.
5289     *
5290     * @param theCurrency new currency object to use. Must not be null.
5291     */
5292    @Override
5293    public void setCurrency(Currency theCurrency) {
5294        // If we are a currency format, then modify our affixes to
5295        // encode the currency symbol for the given currency in our
5296        // locale, and adjust the decimal digits and rounding for the
5297        // given currency.
5298
5299        super.setCurrency(theCurrency);
5300        if (theCurrency != null) {
5301            String s = theCurrency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, null);
5302            symbols.setCurrency(theCurrency);
5303            symbols.setCurrencySymbol(s);
5304        }
5305
5306        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
5307            if (theCurrency != null) {
5308                setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
5309                int d = theCurrency.getDefaultFractionDigits(currencyUsage);
5310                setMinimumFractionDigits(d);
5311                setMaximumFractionDigits(d);
5312            }
5313            if (currencySignCount != CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
5314                // This is not necessary for plural format type
5315                // because affixes will be resolved in subformat
5316                expandAffixes(null);
5317            }
5318        }
5319    }
5320
5321    /**
5322     * Sets the <tt>Currency Usage</tt> object used to display currency.
5323     * This takes effect immediately, if this format is a
5324     * currency format.
5325     * @param newUsage new currency context object to use.
5326     */
5327    public void setCurrencyUsage(CurrencyUsage newUsage) {
5328        if (newUsage == null) {
5329            throw new NullPointerException("return value is null at method AAA");
5330        }
5331        currencyUsage = newUsage;
5332        Currency theCurrency = this.getCurrency();
5333
5334        // We set rounding/digit based on currency context
5335        if (theCurrency != null) {
5336            setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
5337            int d = theCurrency.getDefaultFractionDigits(currencyUsage);
5338            setMinimumFractionDigits(d);
5339            _setMaximumFractionDigits(d);
5340        }
5341    }
5342
5343    /**
5344     * Returns the <tt>Currency Usage</tt> object used to display currency
5345     */
5346    public CurrencyUsage getCurrencyUsage() {
5347        return currencyUsage;
5348    }
5349
5350    /**
5351     * Returns the currency in effect for this formatter. Subclasses should override this
5352     * method as needed. Unlike getCurrency(), this method should never return null.
5353     *
5354     * @deprecated This API is ICU internal only.
5355     * @hide original deprecated declaration
5356     * @hide draft / provisional / internal are hidden on Android
5357     */
5358    @Deprecated
5359    @Override
5360    protected Currency getEffectiveCurrency() {
5361        Currency c = getCurrency();
5362        if (c == null) {
5363            c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
5364        }
5365        return c;
5366    }
5367
5368    /**
5369     * Sets the maximum number of digits allowed in the fraction portion of a number. This
5370     * override limits the fraction digit count to 340.
5371     *
5372     * @see NumberFormat#setMaximumFractionDigits
5373     */
5374    @Override
5375    public void setMaximumFractionDigits(int newValue) {
5376        _setMaximumFractionDigits(newValue);
5377        resetActualRounding();
5378    }
5379
5380    /*
5381     * Internal method for DecimalFormat, setting maximum fractional digits
5382     * without triggering actual rounding recalculated.
5383     */
5384    private void _setMaximumFractionDigits(int newValue) {
5385        super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
5386    }
5387
5388    /**
5389     * Sets the minimum number of digits allowed in the fraction portion of a number. This
5390     * override limits the fraction digit count to 340.
5391     *
5392     * @see NumberFormat#setMinimumFractionDigits
5393     */
5394    @Override
5395    public void setMinimumFractionDigits(int newValue) {
5396        super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
5397    }
5398
5399    /**
5400     * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
5401     * default value is false.
5402     *
5403     * @param value true if {@link #parse(String, ParsePosition)}
5404     * returns BigDecimal.
5405     */
5406    public void setParseBigDecimal(boolean value) {
5407        parseBigDecimal = value;
5408    }
5409
5410    /**
5411     * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
5412     *
5413     * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
5414     */
5415    public boolean isParseBigDecimal() {
5416        return parseBigDecimal;
5417    }
5418
5419    /**
5420    * Set the maximum number of exponent digits when parsing a number.
5421    * If the limit is set too high, an OutOfMemoryException may be triggered.
5422    * The default value is 1000.
5423    * @param newValue the new limit
5424    */
5425    public void setParseMaxDigits(int newValue) {
5426        if (newValue > 0) {
5427            PARSE_MAX_EXPONENT = newValue;
5428        }
5429    }
5430
5431    /**
5432    * Get the current maximum number of exponent digits when parsing a
5433    * number.
5434    * @return the maximum number of exponent digits for parsing
5435    */
5436    public int getParseMaxDigits() {
5437        return PARSE_MAX_EXPONENT;
5438    }
5439
5440    private void writeObject(ObjectOutputStream stream) throws IOException {
5441        // Ticket#6449 Format.Field instances are not serializable. When
5442        // formatToCharacterIterator is called, attributes (ArrayList) stores
5443        // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is
5444        // not serializable, we need to clear the contents of the list when writeObject is
5445        // called. We could remove the field or make it transient, but it will break
5446        // serialization compatibility.
5447        attributes.clear();
5448
5449        stream.defaultWriteObject();
5450    }
5451
5452    /**
5453     * First, read the default serializable fields from the stream. Then if
5454     * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was
5455     * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since
5456     * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the
5457     * maximum allowed value so that default serialization will work properly if this
5458     * object is streamed out again.
5459     */
5460    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
5461        stream.defaultReadObject();
5462
5463        // Bug 4185761 validate fields [Richard/GCL]
5464
5465        // We only need to check the maximum counts because NumberFormat .readObject has
5466        // already ensured that the maximum is greater than the minimum count.
5467
5468        // Commented for compatibility with previous version, and reserved for further use
5469        // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
5470        // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new
5471        // InvalidObjectException("Digit count out of range"); }
5472
5473
5474        // Android changed: Allow 2 billion integer digits.
5475        // Truncate the maximumIntegerDigits to MAX_INTEGER_DIGITS and
5476        // maximumFractionDigits to DOUBLE_FRACTION_DIGITS
5477
5478        if (getMaximumIntegerDigits() > MAX_INTEGER_DIGITS) {
5479            setMaximumIntegerDigits(MAX_INTEGER_DIGITS);
5480        }
5481        if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
5482            _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
5483        }
5484        if (serialVersionOnStream < 2) {
5485            exponentSignAlwaysShown = false;
5486            setInternalRoundingIncrement(null);
5487            roundingMode = BigDecimal.ROUND_HALF_EVEN;
5488            formatWidth = 0;
5489            pad = ' ';
5490            padPosition = PAD_BEFORE_PREFIX;
5491            if (serialVersionOnStream < 1) {
5492                // Didn't have exponential fields
5493                useExponentialNotation = false;
5494            }
5495        }
5496        if (serialVersionOnStream < 3) {
5497            // Versions prior to 3 do not store a currency object.  Create one to match
5498            // the DecimalFormatSymbols object.
5499            setCurrencyForSymbols();
5500        }
5501        if (serialVersionOnStream < 4) {
5502            currencyUsage = CurrencyUsage.STANDARD;
5503        }
5504        serialVersionOnStream = currentSerialVersion;
5505        digitList = new DigitList();
5506
5507        if (roundingIncrement != null) {
5508            setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
5509        }
5510        resetActualRounding();
5511    }
5512
5513    private void setInternalRoundingIncrement(BigDecimal value) {
5514        roundingIncrementICU = value;
5515        roundingIncrement = value == null ? null : value.toBigDecimal();
5516    }
5517
5518    // ----------------------------------------------------------------------
5519    // INSTANCE VARIABLES
5520    // ----------------------------------------------------------------------
5521
5522    private transient DigitList digitList = new DigitList();
5523
5524    /**
5525     * The symbol used as a prefix when formatting positive numbers, e.g. "+".
5526     *
5527     * @serial
5528     * @see #getPositivePrefix
5529     */
5530    private String positivePrefix = "";
5531
5532    /**
5533     * The symbol used as a suffix when formatting positive numbers. This is often an
5534     * empty string.
5535     *
5536     * @serial
5537     * @see #getPositiveSuffix
5538     */
5539    private String positiveSuffix = "";
5540
5541    /**
5542     * The symbol used as a prefix when formatting negative numbers, e.g. "-".
5543     *
5544     * @serial
5545     * @see #getNegativePrefix
5546     */
5547    private String negativePrefix = "-";
5548
5549    /**
5550     * The symbol used as a suffix when formatting negative numbers. This is often an
5551     * empty string.
5552     *
5553     * @serial
5554     * @see #getNegativeSuffix
5555     */
5556    private String negativeSuffix = "";
5557
5558    /**
5559     * The prefix pattern for non-negative numbers. This variable corresponds to
5560     * <code>positivePrefix</code>.
5561     *
5562     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
5563     * <code>positivePrefix</code> to update the latter to reflect changes in
5564     * <code>symbols</code>. If this variable is <code>null</code> then
5565     * <code>positivePrefix</code> is taken as a literal value that does not change when
5566     * <code>symbols</code> changes.  This variable is always <code>null</code> for
5567     * <code>DecimalFormat</code> objects older than stream version 2 restored from
5568     * stream.
5569     *
5570     * @serial
5571     */
5572    // [Richard/GCL]
5573    private String posPrefixPattern;
5574
5575    /**
5576     * The suffix pattern for non-negative numbers. This variable corresponds to
5577     * <code>positiveSuffix</code>. This variable is analogous to
5578     * <code>posPrefixPattern</code>; see that variable for further documentation.
5579     *
5580     * @serial
5581     */
5582    // [Richard/GCL]
5583    private String posSuffixPattern;
5584
5585    /**
5586     * The prefix pattern for negative numbers. This variable corresponds to
5587     * <code>negativePrefix</code>. This variable is analogous to
5588     * <code>posPrefixPattern</code>; see that variable for further documentation.
5589     *
5590     * @serial
5591     */
5592    // [Richard/GCL]
5593    private String negPrefixPattern;
5594
5595    /**
5596     * The suffix pattern for negative numbers. This variable corresponds to
5597     * <code>negativeSuffix</code>. This variable is analogous to
5598     * <code>posPrefixPattern</code>; see that variable for further documentation.
5599     *
5600     * @serial
5601     */
5602    // [Richard/GCL]
5603    private String negSuffixPattern;
5604
5605    /**
5606     * Formatter for ChoiceFormat-based currency names. If this field is not null, then
5607     * delegate to it to format currency symbols.
5608     * TODO: This is obsolete: Remove, and design extensible serialization. ICU ticket #12090.
5609     */
5610    private ChoiceFormat currencyChoice;
5611
5612    /**
5613     * The multiplier for use in percent, permill, etc.
5614     *
5615     * @serial
5616     * @see #getMultiplier
5617     */
5618    private int multiplier = 1;
5619
5620    /**
5621     * The number of digits between grouping separators in the integer portion of a
5622     * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true.
5623     *
5624     * @serial
5625     * @see #getGroupingSize
5626     * @see NumberFormat#isGroupingUsed
5627     */
5628    private byte groupingSize = 3; // invariant, > 0 if useThousands
5629
5630    /**
5631     * The secondary grouping size. This is only used for Hindi numerals, which use a
5632     * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this
5633     * value is less than 1, then secondary grouping is equal to the primary grouping.
5634     *
5635     */
5636    private byte groupingSize2 = 0;
5637
5638    /**
5639     * If true, forces the decimal separator to always appear in a formatted number, even
5640     * if the fractional part of the number is zero.
5641     *
5642     * @serial
5643     * @see #isDecimalSeparatorAlwaysShown
5644     */
5645    private boolean decimalSeparatorAlwaysShown = false;
5646
5647    /**
5648     * The <code>DecimalFormatSymbols</code> object used by this format. It contains the
5649     * symbols used to format numbers, e.g. the grouping separator, decimal separator, and
5650     * so on.
5651     *
5652     * @serial
5653     * @see #setDecimalFormatSymbols
5654     * @see DecimalFormatSymbols
5655     */
5656    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
5657
5658    /**
5659     * True to use significant digits rather than integer and fraction digit counts.
5660     *
5661     * @serial
5662     */
5663    private boolean useSignificantDigits = false;
5664
5665    /**
5666     * The minimum number of significant digits to show. Must be &gt;= 1 and &lt;=
5667     * maxSignificantDigits. Ignored unless useSignificantDigits == true.
5668     *
5669     * @serial
5670     */
5671    private int minSignificantDigits = 1;
5672
5673    /**
5674     * The maximum number of significant digits to show. Must be &gt;=
5675     * minSignficantDigits. Ignored unless useSignificantDigits == true.
5676     *
5677     * @serial
5678     */
5679    private int maxSignificantDigits = 6;
5680
5681    /**
5682     * True to force the use of exponential (i.e. scientific) notation
5683     * when formatting numbers.
5684     *
5685     *<p> Note that the JDK 1.2 public API provides no way to set this
5686     * field, even though it is supported by the implementation and
5687     * the stream format. The intent is that this will be added to the
5688     * API in the future.
5689     *
5690     * @serial
5691     */
5692    private boolean useExponentialNotation; // Newly persistent in JDK 1.2
5693
5694    /**
5695     * The minimum number of digits used to display the exponent when a number is
5696     * formatted in exponential notation.  This field is ignored if
5697     * <code>useExponentialNotation</code> is not true.
5698     *
5699     * <p>Note that the JDK 1.2 public API provides no way to set this field, even though
5700     * it is supported by the implementation and the stream format. The intent is that
5701     * this will be added to the API in the future.
5702     *
5703     * @serial
5704     */
5705    private byte minExponentDigits; // Newly persistent in JDK 1.2
5706
5707    /**
5708     * If true, the exponent is always prefixed with either the plus sign or the minus
5709     * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has
5710     * no effect unless <code>useExponentialNotation</code> is true.
5711     *
5712     * @serial
5713     */
5714    private boolean exponentSignAlwaysShown = false;
5715
5716    /**
5717     * The value to which numbers are rounded during formatting. For example, if the
5718     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
5719     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
5720     * positive value if rounding is in effect. Default value <code>null</code>.
5721     *
5722     * @serial
5723     */
5724    // Note: this is kept in sync with roundingIncrementICU.
5725    // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
5726    private java.math.BigDecimal roundingIncrement = null;
5727
5728    /**
5729     * The value to which numbers are rounded during formatting. For example, if the
5730     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
5731     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
5732     * positive value if rounding is in effect. Default value <code>null</code>. WARNING:
5733     * the roundingIncrement value is the one serialized.
5734     *
5735     * @serial
5736     */
5737    private transient BigDecimal roundingIncrementICU = null;
5738
5739    /**
5740     * The rounding mode. This value controls any rounding operations which occur when
5741     * applying a rounding increment or when reducing the number of fraction digits to
5742     * satisfy a maximum fraction digits limit. The value may assume any of the
5743     * <code>BigDecimal</code> rounding mode values. Default value
5744     * <code>BigDecimal.ROUND_HALF_EVEN</code>.
5745     *
5746     * @serial
5747     */
5748    private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
5749
5750    /**
5751     * Operations on <code>BigDecimal</code> numbers are controlled by a {@link
5752     * MathContext} object, which provides the context (precision and other information)
5753     * for the operation. The default <code>MathContext</code> settings are
5754     * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>;
5755     * these settings perform fixed point arithmetic with unlimited precision, as defined
5756     * for the original BigDecimal class in Java 1.1 and Java 1.2
5757     */
5758    // context for plain unlimited math
5759    private MathContext mathContext = new MathContext(0, MathContext.PLAIN);
5760
5761    /**
5762     * The padded format width, or zero if there is no padding. Must be &gt;= 0. Default
5763     * value zero.
5764     *
5765     * @serial
5766     */
5767    private int formatWidth = 0;
5768
5769    /**
5770     * The character used to pad the result of format to <code>formatWidth</code>, if
5771     * padding is in effect. Default value ' '.
5772     *
5773     * @serial
5774     */
5775    private char pad = ' ';
5776
5777    /**
5778     * The position in the string at which the <code>pad</code> character will be
5779     * inserted, if padding is in effect.  Must have a value from
5780     * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value
5781     * <code>PAD_BEFORE_PREFIX</code>.
5782     *
5783     * @serial
5784     */
5785    private int padPosition = PAD_BEFORE_PREFIX;
5786
5787    /**
5788     * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than
5789     * Long, Double or BigDecimal except special values. This property is introduced for
5790     * J2SE 5 compatibility support.
5791     *
5792     * @serial
5793     * @see #setParseBigDecimal(boolean)
5794     * @see #isParseBigDecimal()
5795     */
5796    private boolean parseBigDecimal = false;
5797
5798    /**
5799     * The currency usage for the NumberFormat(standard or cash usage).
5800     * It is used as STANDARD by default
5801     */
5802    private CurrencyUsage currencyUsage = CurrencyUsage.STANDARD;
5803
5804    // ----------------------------------------------------------------------
5805
5806    static final int currentSerialVersion = 4;
5807
5808    /**
5809     * The internal serial version which says which version was written Possible values
5810     * are:
5811     *
5812     * <ul>
5813     *
5814     * <li><b>0</b> (default): versions before JDK 1.2
5815     *
5816     * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
5817     * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
5818     *
5819     * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad,
5820     * padPosition, exponentSignAlwaysShown, roundingIncrement.
5821     *
5822     * <li><b>3</b>: ICU 2.2. Adds currency object.
5823     *
5824     * <li><b>4</b>: ICU 54. Adds currency usage(standard vs cash)
5825     *
5826     * </ul>
5827     *
5828     * @serial
5829     */
5830    private int serialVersionOnStream = currentSerialVersion;
5831
5832    // ----------------------------------------------------------------------
5833    // CONSTANTS
5834    // ----------------------------------------------------------------------
5835
5836    /**
5837     * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
5838     * specify pad characters inserted before the prefix.
5839     *
5840     * @see #setPadPosition
5841     * @see #getPadPosition
5842     * @see #PAD_AFTER_PREFIX
5843     * @see #PAD_BEFORE_SUFFIX
5844     * @see #PAD_AFTER_SUFFIX
5845     */
5846    public static final int PAD_BEFORE_PREFIX = 0;
5847
5848    /**
5849     * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
5850     * specify pad characters inserted after the prefix.
5851     *
5852     * @see #setPadPosition
5853     * @see #getPadPosition
5854     * @see #PAD_BEFORE_PREFIX
5855     * @see #PAD_BEFORE_SUFFIX
5856     * @see #PAD_AFTER_SUFFIX
5857     */
5858    public static final int PAD_AFTER_PREFIX = 1;
5859
5860    /**
5861     * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
5862     * specify pad characters inserted before the suffix.
5863     *
5864     * @see #setPadPosition
5865     * @see #getPadPosition
5866     * @see #PAD_BEFORE_PREFIX
5867     * @see #PAD_AFTER_PREFIX
5868     * @see #PAD_AFTER_SUFFIX
5869     */
5870    public static final int PAD_BEFORE_SUFFIX = 2;
5871
5872    /**
5873     * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
5874     * specify pad characters inserted after the suffix.
5875     *
5876     * @see #setPadPosition
5877     * @see #getPadPosition
5878     * @see #PAD_BEFORE_PREFIX
5879     * @see #PAD_AFTER_PREFIX
5880     * @see #PAD_BEFORE_SUFFIX
5881     */
5882    public static final int PAD_AFTER_SUFFIX = 3;
5883
5884    // Constants for characters used in programmatic (unlocalized) patterns.
5885    static final char PATTERN_ZERO_DIGIT = '0';
5886    static final char PATTERN_ONE_DIGIT = '1';
5887    static final char PATTERN_TWO_DIGIT = '2';
5888    static final char PATTERN_THREE_DIGIT = '3';
5889    static final char PATTERN_FOUR_DIGIT = '4';
5890    static final char PATTERN_FIVE_DIGIT = '5';
5891    static final char PATTERN_SIX_DIGIT = '6';
5892    static final char PATTERN_SEVEN_DIGIT = '7';
5893    static final char PATTERN_EIGHT_DIGIT = '8';
5894    static final char PATTERN_NINE_DIGIT = '9';
5895    static final char PATTERN_GROUPING_SEPARATOR = ',';
5896    static final char PATTERN_DECIMAL_SEPARATOR = '.';
5897    static final char PATTERN_DIGIT = '#';
5898    static final char PATTERN_SIGNIFICANT_DIGIT = '@';
5899    static final char PATTERN_EXPONENT = 'E';
5900    static final char PATTERN_PLUS_SIGN = '+';
5901    static final char PATTERN_MINUS_SIGN = '-';
5902
5903    // Affix
5904    private static final char PATTERN_PER_MILLE = '\u2030';
5905    private static final char PATTERN_PERCENT = '%';
5906    static final char PATTERN_PAD_ESCAPE = '*';
5907
5908    // Other
5909    private static final char PATTERN_SEPARATOR = ';';
5910
5911    // Pad escape is package private to allow access by DecimalFormatSymbols.
5912    // Also plus sign. Also exponent.
5913
5914    /**
5915     * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in
5916     * patterns and substitued with either the currency symbol, or if it is doubled, with
5917     * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then
5918     * the decimal separator is replaced with the monetary decimal separator.
5919     *
5920     * The CURRENCY_SIGN is not localized.
5921     */
5922    private static final char CURRENCY_SIGN = '\u00A4';
5923
5924    private static final char QUOTE = '\'';
5925
5926    /**
5927     * Upper limit on integer and fraction digits for a Java double [Richard/GCL]
5928     */
5929    static final int DOUBLE_INTEGER_DIGITS = 309;
5930    // Android changed: Allow 2 billion integer digits.
5931    // This change is necessary to stay feature-compatible in java.text.DecimalFormat which
5932    // used to be implemented using ICU4C (which has a 2 billion integer digits limit) and
5933    // is now implemented based on this class.
5934    static final int MAX_INTEGER_DIGITS = 2000000000;
5935    static final int DOUBLE_FRACTION_DIGITS = 340;
5936
5937    /**
5938     * When someone turns on scientific mode, we assume that more than this number of
5939     * digits is due to flipping from some other mode that didn't restrict the maximum,
5940     * and so we force 1 integer digit. We don't bother to track and see if someone is
5941     * using exponential notation with more than this number, it wouldn't make sense
5942     * anyway, and this is just to make sure that someone turning on scientific mode with
5943     * default settings doesn't end up with lots of zeroes.
5944     */
5945    static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
5946
5947    // Proclaim JDK 1.1 serial compatibility.
5948    private static final long serialVersionUID = 864413376551465018L;
5949
5950    private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>();
5951
5952    // The following are used in currency format
5953
5954    // -- triple currency sign char array
5955    // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
5956    // -- triple currency sign string
5957    // private static final String tripleCurrencyStr = new String(tripleCurrencySign);
5958    //
5959    // -- default currency plural pattern char array
5960    // private static final char[] defaultCurrencyPluralPatternChar =
5961    //   {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
5962    // -- default currency plural pattern string
5963    // private static final String defaultCurrencyPluralPattern =
5964    //     new String(defaultCurrencyPluralPatternChar);
5965
5966    // pattern used in this formatter
5967    private String formatPattern = "";
5968    // style is only valid when decimal formatter is constructed by
5969    // DecimalFormat(pattern, decimalFormatSymbol, style)
5970    private int style = NumberFormat.NUMBERSTYLE;
5971    /**
5972     * Represents whether this is a currency format, and which currency format style. 0:
5973     * not currency format type; 1: currency style -- symbol name, such as "$" for US
5974     * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style
5975     * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for
5976     * "3.00 US Dollars".
5977     */
5978    private int currencySignCount = CURRENCY_SIGN_COUNT_ZERO;
5979
5980    /**
5981     * For parsing purposes, we need to remember all prefix patterns and suffix patterns
5982     * of every currency format pattern, including the pattern of the default currency
5983     * style, ISO currency style, and plural currency style. The patterns are set through
5984     * applyPattern. The following are used to represent the affix patterns in currency
5985     * plural formats.
5986     */
5987    private static final class AffixForCurrency {
5988        // negative prefix pattern
5989        private String negPrefixPatternForCurrency = null;
5990        // negative suffix pattern
5991        private String negSuffixPatternForCurrency = null;
5992        // positive prefix pattern
5993        private String posPrefixPatternForCurrency = null;
5994        // positive suffix pattern
5995        private String posSuffixPatternForCurrency = null;
5996        private final int patternType;
5997
5998        public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix,
5999                                String posSuffix, int type) {
6000            negPrefixPatternForCurrency = negPrefix;
6001            negSuffixPatternForCurrency = negSuffix;
6002            posPrefixPatternForCurrency = posPrefix;
6003            posSuffixPatternForCurrency = posSuffix;
6004            patternType = type;
6005        }
6006
6007        public String getNegPrefix() {
6008            return negPrefixPatternForCurrency;
6009        }
6010
6011        public String getNegSuffix() {
6012            return negSuffixPatternForCurrency;
6013        }
6014
6015        public String getPosPrefix() {
6016            return posPrefixPatternForCurrency;
6017        }
6018
6019        public String getPosSuffix() {
6020            return posSuffixPatternForCurrency;
6021        }
6022
6023        public int getPatternType() {
6024            return patternType;
6025        }
6026    }
6027
6028    // Affix pattern set for currency.  It is a set of AffixForCurrency, each element of
6029    // the set saves the negative prefix, negative suffix, positive prefix, and positive
6030    // suffix of a pattern.
6031    private transient Set<AffixForCurrency> affixPatternsForCurrency = null;
6032
6033    // For currency parsing. Since currency parsing needs to parse against all currency
6034    // patterns, before the parsing, we need to set up the affix patterns for all currencies.
6035    private transient boolean isReadyForParsing = false;
6036
6037    // Information needed for DecimalFormat to format/parse currency plural.
6038    private CurrencyPluralInfo currencyPluralInfo = null;
6039
6040    /**
6041     * Unit is an immutable class for the textual representation of a unit, in
6042     * particular its prefix and suffix.
6043     *
6044     * @author rocketman
6045     *
6046     */
6047    static class Unit {
6048        private final String prefix;
6049        private final String suffix;
6050
6051        public Unit(String prefix, String suffix) {
6052            this.prefix = prefix;
6053            this.suffix = suffix;
6054        }
6055
6056        public void writeSuffix(StringBuffer toAppendTo) {
6057            toAppendTo.append(suffix);
6058        }
6059
6060        public void writePrefix(StringBuffer toAppendTo) {
6061            toAppendTo.append(prefix);
6062        }
6063
6064        @Override
6065        public boolean equals(Object obj) {
6066            if (this == obj) {
6067                return true;
6068            }
6069            if (!(obj instanceof Unit)) {
6070                return false;
6071            }
6072            Unit other = (Unit) obj;
6073            return prefix.equals(other.prefix) && suffix.equals(other.suffix);
6074        }
6075        @Override
6076        public String toString() {
6077            return prefix + "/" + suffix;
6078        }
6079    }
6080
6081    static final Unit NULL_UNIT = new Unit("", "");
6082
6083    // Note about rounding implementation
6084    //
6085    // The original design intended to skip rounding operation when roundingIncrement is not
6086    // set. However, rounding may need to occur when fractional digits exceed the width of
6087    // fractional part of pattern.
6088    //
6089    // DigitList class has built-in rounding mechanism, using ROUND_HALF_EVEN. This implementation
6090    // forces non-null roundingIncrement if the setting is other than ROUND_HALF_EVEN, otherwise,
6091    // when rounding occurs in DigitList by pattern's fractional digits' width, the result
6092    // does not match the rounding mode.
6093    //
6094    // Ideally, all rounding operation should be done in one place like ICU4C trunk does
6095    // (ICU4C rounding implementation was rewritten recently). This is intrim implemetation
6096    // to fix various issues. In the future, we should entire implementation of rounding
6097    // in this class, like ICU4C did.
6098    //
6099    // Once we fully implement rounding logic in DigitList, then following fields and methods
6100    // should be gone.
6101
6102    private transient BigDecimal actualRoundingIncrementICU = null;
6103    private transient java.math.BigDecimal actualRoundingIncrement = null;
6104
6105    /*
6106     * The actual rounding increment as a double.
6107     */
6108    private transient double roundingDouble = 0.0;
6109
6110    /*
6111     * If the roundingDouble is the reciprocal of an integer (the most common case!), this
6112     * is set to be that integer.  Otherwise it is 0.0.
6113     */
6114    private transient double roundingDoubleReciprocal = 0.0;
6115
6116    /*
6117     * Set roundingDouble, roundingDoubleReciprocal and actualRoundingIncrement
6118     * based on rounding mode and width of fractional digits. Whenever setting affecting
6119     * rounding mode, rounding increment and maximum width of fractional digits, then
6120     * this method must be called.
6121     *
6122     * roundingIncrementICU is the field storing the custom rounding increment value,
6123     * while actual rounding increment could be larger.
6124     */
6125    private void resetActualRounding() {
6126        if (roundingIncrementICU != null) {
6127            BigDecimal byWidth = getMaximumFractionDigits() > 0 ?
6128                    BigDecimal.ONE.movePointLeft(getMaximumFractionDigits()) : BigDecimal.ONE;
6129            if (roundingIncrementICU.compareTo(byWidth) >= 0) {
6130                actualRoundingIncrementICU = roundingIncrementICU;
6131            } else {
6132                actualRoundingIncrementICU = byWidth.equals(BigDecimal.ONE) ? null : byWidth;
6133            }
6134        } else {
6135            if (roundingMode == BigDecimal.ROUND_HALF_EVEN || isScientificNotation()) {
6136                // This rounding fix is irrelevant if mode is ROUND_HALF_EVEN as DigitList
6137                // does ROUND_HALF_EVEN for us.  This rounding fix won't work at all for
6138                // scientific notation.
6139                actualRoundingIncrementICU = null;
6140            } else {
6141                if (getMaximumFractionDigits() > 0) {
6142                    actualRoundingIncrementICU = BigDecimal.ONE.movePointLeft(getMaximumFractionDigits());
6143                }  else {
6144                    actualRoundingIncrementICU = BigDecimal.ONE;
6145                }
6146            }
6147        }
6148
6149        if (actualRoundingIncrementICU == null) {
6150            setRoundingDouble(0.0d);
6151            actualRoundingIncrement = null;
6152        } else {
6153            setRoundingDouble(actualRoundingIncrementICU.doubleValue());
6154            actualRoundingIncrement = actualRoundingIncrementICU.toBigDecimal();
6155        }
6156    }
6157
6158    static final double roundingIncrementEpsilon = 0.000000001;
6159
6160    private void setRoundingDouble(double newValue) {
6161        roundingDouble = newValue;
6162        if (roundingDouble > 0.0d) {
6163            double rawRoundedReciprocal = 1.0d / roundingDouble;
6164            roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
6165            if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
6166                roundingDoubleReciprocal = 0.0d;
6167            }
6168        } else {
6169            roundingDoubleReciprocal = 0.0d;
6170        }
6171    }
6172}
6173
6174// eof
6175