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