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