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