/*
 *******************************************************************************
 * Copyright (C) 1996-2013, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.text;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.ChoiceFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.ibm.icu.impl.ICUConfig;
import com.ibm.icu.impl.PatternProps;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.math.MathContext;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;

/**
 * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
 *
 * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
 * decimal numbers. It has a variety of features designed to make it possible to parse and
 * format numbers in any locale, including support for Western, Arabic, or Indic digits.
 * It also supports different flavors of numbers, including integers ("123"), fixed-point
 * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
 * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be
 * easily localized.
 *
 * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
 * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
 * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
 * directly, unless you know what you are doing, since the {@link NumberFormat} factory
 * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
 * customize the format object, do something like this:
 *
 * <blockquote><pre>
 * NumberFormat f = NumberFormat.getInstance(loc);
 * if (f instanceof DecimalFormat) {
 *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
 * }</pre></blockquote>
 *
 * <p><strong>Example Usage</strong>
 *
 * Print out a number using the localized number, currency, and percent
 * format for each locale.
 *
 * <blockquote><pre>
 * Locale[] locales = NumberFormat.getAvailableLocales();
 * double myNumber = -1234.56;
 * NumberFormat format;
 * for (int j=0; j<3; ++j) {
 *     System.out.println("FORMAT");
 *     for (int i = 0; i < locales.length; ++i) {
 *         if (locales[i].getCountry().length() == 0) {
 *            // Skip language-only locales
 *            continue;
 *         }
 *         System.out.print(locales[i].getDisplayName());
 *         switch (j) {
 *         case 0:
 *             format = NumberFormat.getInstance(locales[i]); break;
 *         case 1:
 *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
 *         default:
 *             format = NumberFormat.getPercentInstance(locales[i]); break;
 *         }
 *         try {
 *             // Assume format is a DecimalFormat
 *             System.out.print(": " + ((DecimalFormat) format).toPattern()
 *                              + " -> " + form.format(myNumber));
 *         } catch (Exception e) {}
 *         try {
 *             System.out.println(" -> " + format.parse(form.format(myNumber)));
 *         } catch (ParseException e) {}
 *     }
 * }</pre></blockquote>
 *
 * <p>Another example use getInstance(style).<br/>
 * Print out a number using the localized number, currency, percent,
 * scientific, integer, iso currency, and plural currency format for each locale.
 *
 * <blockquote><pre>
 * ULocale locale = new ULocale("en_US");
 * double myNumber = 1234.56;
 * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
 *     NumberFormat format = NumberFormat.getInstance(locale, j);
 *     try {
 *         // Assume format is a DecimalFormat
 *         System.out.print(": " + ((DecimalFormat) format).toPattern()
 *                          + " -> " + form.format(myNumber));
 *     } catch (Exception e) {}
 *     try {
 *         System.out.println(" -> " + format.parse(form.format(myNumber)));
 *     } catch (ParseException e) {}
 * }</pre></blockquote>
 *
 * <h4>Patterns</h4>
 *
 * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
 * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or
 * indirectly using other API methods which manipulate aspects of the pattern, such as the
 * minimum number of integer digits.  The symbols are stored in a {@link
 * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the
 * pattern and symbols are read from ICU's locale data.
 *
 * <h4>Special Pattern Characters</h4>
 *
 * <p>Many characters in a pattern are taken literally; they are matched during parsing
 * and output unchanged during formatting.  Special characters, on the other hand, stand
 * for other characters, strings, or classes of characters.  For example, the '#'
 * character is replaced by a localized digit.  Often the replacement character is the
 * same as the pattern character; in the U.S. locale, the ',' grouping character is
 * replaced by ','.  However, the replacement is still happening, and if the symbols are
 * modified, the grouping character changes.  Some special characters affect the behavior
 * of the formatter by their presence; for example, if the percent character is seen, then
 * the value is multiplied by 100 before being displayed.
 *
 * <p>To insert a special character in a pattern as a literal, that is, without any
 * special meaning, the character must be quoted.  There are some exceptions to this which
 * are noted below.
 *
 * <p>The characters listed here are used in non-localized patterns.  Localized patterns
 * use the corresponding characters taken from this formatter's {@link
 * DecimalFormatSymbols} object instead, and these characters lose their special status.
 * Two exceptions are the currency sign and quote, which are not localized.
 *
 * <blockquote>
 * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
 *  location, localized, and meaning.">
 *   <tr bgcolor="#ccccff">
 *     <th align=left>Symbol
 *     <th align=left>Location
 *     <th align=left>Localized?
 *     <th align=left>Meaning
 *   <tr valign=top>
 *     <td><code>0</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Digit
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>1-9</code>
 *     <td>Number
 *     <td>Yes
 *     <td>'1' through '9' indicate rounding.
 *   <tr valign=top>
 *     <td><code>@</code>
 *     <td>Number
 *     <td>No
 *     <td>Significant digit
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>#</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Digit, zero shows as absent
 *   <tr valign=top>
 *     <td><code>.</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Decimal separator or monetary decimal separator
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>-</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Minus sign
 *   <tr valign=top>
 *     <td><code>,</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Grouping separator
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>E</code>
 *     <td>Number
 *     <td>Yes
 *     <td>Separates mantissa and exponent in scientific notation.
 *         <em>Need not be quoted in prefix or suffix.</em>
 *   <tr valign=top>
 *     <td><code>+</code>
 *     <td>Exponent
 *     <td>Yes
 *     <td>Prefix positive exponents with localized plus sign.
 *         <em>Need not be quoted in prefix or suffix.</em>
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>;</code>
 *     <td>Subpattern boundary
 *     <td>Yes
 *     <td>Separates positive and negative subpatterns
 *   <tr valign=top>
 *     <td><code>%</code>
 *     <td>Prefix or suffix
 *     <td>Yes
 *     <td>Multiply by 100 and show as percentage
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>&#92;u2030</code>
 *     <td>Prefix or suffix
 *     <td>Yes
 *     <td>Multiply by 1000 and show as per mille
 *   <tr valign=top>
 *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
 *     <td>Prefix or suffix
 *     <td>No
 *     <td>Currency sign, replaced by currency symbol.  If
 *         doubled, replaced by international currency symbol.
 *         If tripled, replaced by currency plural names, for example,
 *         "US dollar" or "US dollars" for America.
 *         If present in a pattern, the monetary decimal separator
 *         is used instead of the decimal separator.
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>'</code>
 *     <td>Prefix or suffix
 *     <td>No
 *     <td>Used to quote special characters in a prefix or suffix,
 *         for example, <code>"'#'#"</code> formats 123 to
 *         <code>"#123"</code>.  To create a single quote
 *         itself, use two in a row: <code>"# o''clock"</code>.
 *   <tr valign=top>
 *     <td><code>*</code>
 *     <td>Prefix or suffix boundary
 *     <td>Yes
 *     <td>Pad escape, precedes pad character
 * </table>
 * </blockquote>
 *
 * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
 * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a
 * suffix.  If there is no explicit negative subpattern, the negative subpattern is the
 * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
 * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves
 * only to specify the negative prefix and suffix; the number of digits, minimal digits,
 * and other characteristics are ignored in the negative subpattern. That means that
 * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
 *
 * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
 * separators, decimal separators, etc. may be set to arbitrary values, and they will
 * appear properly during formatting.  However, care must be taken that the symbols and
 * strings do not conflict, or parsing will be unreliable.  For example, either the
 * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
 * be able to distinguish positive from negative values.  Another example is that the
 * decimal separator and thousands separator should be distinct characters, or parsing
 * will be impossible.
 *
 * <p>The <em>grouping separator</em> is a character that separates clusters of integer
 * digits to make large numbers more legible.  It commonly used for thousands, but in some
 * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits
 * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
 * 0000". There are actually two different grouping sizes: One used for the least
 * significant integer digits, the <em>primary grouping size</em>, and one used for all
 * others, the <em>secondary grouping size</em>.  In most locales these are the same, but
 * sometimes they are different. For example, if the primary grouping interval is 3, and
 * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
 * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping
 * separators, the interval between the last one and the end of the integer defines the
 * primary grouping size, and the interval between the last two defines the secondary
 * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
 * "##,#,###,####".
 *
 * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
 * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
 * that describes the problem.
 *
 * <h4>Pattern BNF</h4>
 *
 * <pre>
 * pattern    := subpattern (';' subpattern)?
 * subpattern := prefix? number exponent? suffix?
 * number     := (integer ('.' fraction)?) | sigDigits
 * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
 * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
 * integer    := '#'* '0'* '0'
 * fraction   := '0'* '#'*
 * sigDigits  := '#'* '@' '@'* '#'*
 * exponent   := 'E' '+'? '0'* '0'
 * padSpec    := '*' padChar
 * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
 * &#32;
 * Notation:
 *   X*       0 or more instances of X
 *   X?       0 or 1 instances of X
 *   X|Y      either X or Y
 *   C..D     any character from C up to D, inclusive
 *   S-T      characters in S, except those in T
 * </pre>
 * The first subpattern is for positive numbers. The second (optional)
 * subpattern is for negative numbers.
 *
 * <p>Not indicated in the BNF syntax above:
 *
 * <ul>
 *
 * <li>The grouping separator ',' can occur inside the integer and sigDigits
 * elements, between any two pattern characters of that element, as long as the integer or
 * sigDigits element is not followed by the exponent element.
 *
 * <li>Two grouping intervals are recognized: That between the decimal point and the first
 * grouping symbol, and that between the first and second grouping symbols. These
 * intervals are identical in most locales, but in some locales they differ. For example,
 * the pattern &quot;#,##,###&quot; formats the number 123456789 as
 * &quot;12,34,56,789&quot;.
 *
 * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
 * prefix, before the suffix, after the suffix, or not at all.
 *
 * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
 * increment.
 *
 * </ul>
 *
 * <h4>Parsing</h4>
 *
 * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
 * digits, as defined by {@link UCharacter#digit}.  In addition,
 * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
 * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
 * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.
 *
 * <p>During parsing, grouping separators are ignored.
 *
 * <p>For currency parsing, the formatter is able to parse every currency style formats no
 * matter which style the formatter is constructed with.  For example, a formatter
 * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
 * parse formats such as "USD1.00" and "3.00 US dollars".
 *
 * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
 * <code>null</code> and leaves the parse position unchanged.  The convenience method
 * {@link #parse(String)} indicates parse failure by throwing a {@link
 * java.text.ParseException}.
 *
 * <p>Parsing an extremely large or small absolute value (such as 1.0E10000 or 1.0E-10000)
 * requires huge memory allocation for representing the parsed number. Such input may expose
 * a risk of DoS attacks. To prevent huge memory allocation triggered by such inputs,
 * <code>DecimalFormat</code> internally limits of maximum decimal digits to be 1000. Thus,
 * an input string resulting more than 1000 digits in plain decimal representation (non-exponent)
 * will be treated as either overflow (positive/negative infinite) or underflow (+0.0/-0.0).
 *
 * <h4>Formatting</h4>
 *
 * <p>Formatting is guided by several parameters, all of which can be specified either
 * using a pattern or using the API.  The following description applies to formats that do
 * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
 * digits</a>.
 *
 * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
 * digits</em>, then only the least significant digits are shown.  For example, 1997 is
 * formatted as "97" if the maximum integer digits is set to 2.
 *
 * <li>If the number of actual integer digits is less than the <em>minimum integer
 * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"
 * if the minimum integer digits is set to 5.
 *
 * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
 * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For
 * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This
 * behavior can be changed by specifying a rounding increment and a rounding mode.
 *
 * <li>If the number of actual fraction digits is less than the <em>minimum fraction
 * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as
 * "0.1250" if the mimimum fraction digits is set to 4.
 *
 * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
 * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
 * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
 * </ul>
 *
 * <p><strong>Special Values</strong>
 *
 * <p><code>NaN</code> is represented as a single character, typically
 * <code>&#92;uFFFD</code>.  This character is determined by the {@link
 * DecimalFormatSymbols} object.  This is the only value for which the prefixes and
 * suffixes are not used.
 *
 * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,
 * with the positive or negative prefixes and suffixes applied.  The infinity character is
 * determined by the {@link DecimalFormatSymbols} object.
 *
 * <a name="sci"><h4>Scientific Notation</h4></a>
 *
 * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
 * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
 * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
 * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
 * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
 * or through the pattern.  In a pattern, the exponent character immediately followed by
 * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats
 * the number 1234 as "1.234E3".
 *
 * <ul>
 *
 * <li>The number of digit characters after the exponent character gives the minimum
 * exponent digit count.  There is no maximum.  Negative exponents are formatted using the
 * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows
 * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus
 * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
 * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign
 * rather than '+'.)
 *
 * <li>The minimum number of integer digits is achieved by adjusting the exponent.
 * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if
 * there is no maximum number of integer digits.  If there is a maximum, then the minimum
 * number of integer digits is fixed at one.
 *
 * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
 * The most common use of this is to generate <em>engineering notation</em>, in which the
 * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted
 * using "##0.####E0" as "12.345E3".
 *
 * <li>When using scientific notation, the formatter controls the digit counts using
 * significant digits logic.  The maximum number of significant digits limits the total
 * number of integer and fraction digits that will be shown in the mantissa; it does not
 * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the
 * section on significant digits for more details.
 *
 * <li>The number of significant digits shown is determined as follows: If
 * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
 * shown is one, and the maximum number of significant digits shown is the sum of the
 * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
 * maximum integer digits.  If this sum is zero, then all significant digits are shown.
 * If areSignificantDigitsUsed() returns true, then the significant digit counts are
 * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this
 * case, the number of integer digits is fixed at one, and there is no exponent grouping.
 *
 * <li>Exponential patterns may not contain grouping separators.
 *
 * </ul>
 *
 * <a name="sigdig"><h4>Significant Digits</h4></a>
 *
 * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
 * significant digits counts, or (b) integer and fraction digit counts.  Integer and
 * fraction digit counts are described above.  When a formatter is using significant
 * digits counts, the number of integer and fraction digits is not specified directly, and
 * the formatter settings for these counts are ignored.  Instead, the formatter uses
 * however many integer and fraction digits are required to display the specified number
 * of significant digits.  Examples:
 *
 * <blockquote>
 * <table border=0 cellspacing=3 cellpadding=0>
 *   <tr bgcolor="#ccccff">
 *     <th align=left>Pattern
 *     <th align=left>Minimum significant digits
 *     <th align=left>Maximum significant digits
 *     <th align=left>Number
 *     <th align=left>Output of format()
 *   <tr valign=top>
 *     <td><code>@@@</code>
 *     <td>3
 *     <td>3
 *     <td>12345
 *     <td><code>12300</code>
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>@@@</code>
 *     <td>3
 *     <td>3
 *     <td>0.12345
 *     <td><code>0.123</code>
 *   <tr valign=top>
 *     <td><code>@@##</code>
 *     <td>2
 *     <td>4
 *     <td>3.14159
 *     <td><code>3.142</code>
 *   <tr valign=top bgcolor="#eeeeff">
 *     <td><code>@@##</code>
 *     <td>2
 *     <td>4
 *     <td>1.23004
 *     <td><code>1.23</code>
 * </table>
 * </blockquote>
 *
 * <ul>
 *
 * <li>Significant digit counts may be expressed using patterns that specify a minimum and
 * maximum number of significant digits.  These are indicated by the <code>'@'</code> and
 * <code>'#'</code> characters.  The minimum number of significant digits is the number of
 * <code>'@'</code> characters.  The maximum number of significant digits is the number of
 * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
 * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
 * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
 * Trailing zero digits to the right of the decimal separator are suppressed after the
 * minimum number of significant digits have been shown.  For example, the pattern
 * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
 *
 * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
 * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or
 * <code>"@.###"</code> are disallowed.
 *
 * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
 * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum
 * significant digits counts, but may be used to position grouping separators.  For
 * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
 * of two significant digits, and a grouping size of three.
 *
 * <li>In order to enable significant digits formatting, use a pattern containing the
 * <code>'@'</code> pattern character.  Alternatively, call {@link
 * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
 *
 * <li>In order to disable significant digits formatting, use a pattern that does not
 * contain the <code>'@'</code> pattern character. Alternatively, call {@link
 * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
 *
 * <li>The number of significant digits has no effect on parsing.
 *
 * <li>Significant digits may be used together with exponential notation. Such patterns
 * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
 * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
 * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
 * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
 * <code>"0.0###E0"</code>.
 *
 * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
 * via the API, are ignored.  If significant digits are not in use, then the signficant
 * digit counts, as set via the API, are ignored.
 *
 * </ul>
 *
 * <h4>Padding</h4>
 *
 * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
 * specific width.  Padding may be specified either through the API or through the pattern
 * syntax.  In a pattern the pad escape character, followed by a single pad character,
 * causes padding to be parsed and formatted.  The pad escape character is '*' in
 * unlocalized patterns, and can be localized using {@link
 * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats
 * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
 *
 * <ul>
 *
 * <li>When padding is in effect, the width of the positive subpattern, including prefix
 * and suffix, determines the format width.  For example, in the pattern <code>"* #0
 * o''clock"</code>, the format width is 10.
 *
 * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
 *
 * <li>Some parameters which usually do not matter have meaning when padding is used,
 * because the pattern width is significant with padding.  In the pattern "*
 * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect
 * the grouping size or maximum integer digits, but they do affect the format width.
 *
 * <li>Padding may be inserted at one of four locations: before the prefix, after the
 * prefix, before the suffix, or after the suffix.  If padding is specified in any other
 * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there
 * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
 * suffix.
 *
 * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
 * pad escape is the pad character. This may be any character, including a special pattern
 * character. That is, the pad escape <em>escapes</em> the following character. If there
 * is no character after the pad escape, then the pattern is illegal.
 *
 * </ul>
 *
 * <p>
 * <strong>Rounding</strong>
 *
 * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,
 * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The
 * rounding increment may be specified through the API or in a pattern.  To specify a
 * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"
 * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of
 * 0.05.
 *
 * <ul>
 *
 * <li>Rounding only affects the string produced by formatting.  It does not affect
 * parsing or change any numerical values.
 *
 * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
 * com.ibm.icu.math.BigDecimal} documentation for a description of the modes.  Rounding
 * increments specified in patterns use the default mode, {@link
 * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
 *
 * <li>Some locales use rounding in their currency formats to reflect the smallest
 * currency denomination.
 *
 * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
 * identically to digit '0'.
 *
 * </ul>
 *
 * <h4>Synchronization</h4>
 *
 * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should
 * not access one formatter concurrently.
 *
 * @see          java.text.Format
 * @see          NumberFormat
 * @author       Mark Davis
 * @author       Alan Liu
 * @stable ICU 2.0
 */
public class DecimalFormat extends NumberFormat {

    /**
     * Creates a DecimalFormat using the default pattern and symbols for the default
     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
     * internationalization is not the main concern.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getNumberInstance.  These factories will return the most
     * appropriate sub-class of NumberFormat for a given locale.
     *
     * @see NumberFormat#getInstance
     * @see NumberFormat#getNumberInstance
     * @see NumberFormat#getCurrencyInstance
     * @see NumberFormat#getPercentInstance
     * @see Category#FORMAT
     * @stable ICU 2.0
     */
    public DecimalFormat() {
        ULocale def = ULocale.getDefault(Category.FORMAT);
        String pattern = getPattern(def, 0);
        // Always applyPattern after the symbols are set
        this.symbols = new DecimalFormatSymbols(def);
        setCurrency(Currency.getInstance(def));
        applyPatternWithoutExpandAffix(pattern, false);
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            currencyPluralInfo = new CurrencyPluralInfo(def);
            // the exact pattern is not known until the plural count is known.
            // so, no need to expand affix now.
        } else {
            expandAffixAdjustWidth(null);
        }
    }

    /**
     * Creates a DecimalFormat from the given pattern and the symbols for the default
     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
     * internationalization is not the main concern.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getNumberInstance.  These factories will return the most
     * appropriate sub-class of NumberFormat for a given locale.
     *
     * @param pattern A non-localized pattern string.
     * @throws IllegalArgumentException if the given pattern is invalid.
     * @see NumberFormat#getInstance
     * @see NumberFormat#getNumberInstance
     * @see NumberFormat#getCurrencyInstance
     * @see NumberFormat#getPercentInstance
     * @see Category#FORMAT
     * @stable ICU 2.0
     */
    public DecimalFormat(String pattern) {
        // Always applyPattern after the symbols are set
        ULocale def = ULocale.getDefault(Category.FORMAT);
        this.symbols = new DecimalFormatSymbols(def);
        setCurrency(Currency.getInstance(def));
        applyPatternWithoutExpandAffix(pattern, false);
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            currencyPluralInfo = new CurrencyPluralInfo(def);
        } else {
            expandAffixAdjustWidth(null);
        }
    }

    /**
     * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
     * when you need to completely customize the behavior of the format.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
     * adjustments to a standard format, you can modify the format returned by a
     * NumberFormat factory method.
     *
     * @param pattern a non-localized pattern string
     * @param symbols the set of symbols to be used
     * @exception IllegalArgumentException if the given pattern is invalid
     * @see NumberFormat#getInstance
     * @see NumberFormat#getNumberInstance
     * @see NumberFormat#getCurrencyInstance
     * @see NumberFormat#getPercentInstance
     * @see DecimalFormatSymbols
     * @stable ICU 2.0
     */
    public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
        createFromPatternAndSymbols(pattern, symbols);
    }

    private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
        // Always applyPattern after the symbols are set
        symbols = (DecimalFormatSymbols) inputSymbols.clone();
        setCurrencyForSymbols();
        applyPatternWithoutExpandAffix(pattern, false);
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
        } else {
            expandAffixAdjustWidth(null);
        }
    }

    /**
     * Creates a DecimalFormat from the given pattern, symbols, information used for
     * currency plural format, and format style. Use this constructor when you need to
     * completely customize the behavior of the format.
     *
     * <p>To obtain standard formats for a given locale, use the factory methods on
     * NumberFormat such as getInstance or getCurrencyInstance.
     *
     * <p>If you need only minor adjustments to a standard format, you can modify the
     * format returned by a NumberFormat factory method using the setters.
     *
     * <p>If you want to completely customize a decimal format, using your own
     * DecimalFormatSymbols (such as group separators) and your own information for
     * currency plural formatting (such as plural rule and currency plural patterns), you
     * can use this constructor.
     *
     * @param pattern a non-localized pattern string
     * @param symbols the set of symbols to be used
     * @param infoInput the information used for currency plural format, including
     * currency plural patterns and plural rules.
     * @param style the decimal formatting style, it is one of the following values:
     * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
     * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
     * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
     * @stable ICU 4.2
     */
    public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
                         int style) {
        CurrencyPluralInfo info = infoInput;
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            info = (CurrencyPluralInfo) infoInput.clone();
        }
        create(pattern, symbols, info, style);
    }

    private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info,
                        int inputStyle) {
        if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
            createFromPatternAndSymbols(pattern, inputSymbols);
        } else {
            // Always applyPattern after the symbols are set
            symbols = (DecimalFormatSymbols) inputSymbols.clone();
            currencyPluralInfo = info;
            // the pattern used in format is not fixed until formatting, in which, the
            // number is known and will be used to pick the right pattern based on plural
            // count.  Here, set the pattern as the pattern of plural count == "other".
            // For most locale, the patterns are probably the same for all plural
            // count. If not, the right pattern need to be re-applied during format.
            String currencyPluralPatternForOther =
                currencyPluralInfo.getCurrencyPluralPattern("other");
            applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false);
            setCurrencyForSymbols();
        }
        style = inputStyle;
    }

    /**
     * Creates a DecimalFormat for currency plural format from the given pattern, symbols,
     * and style.
     */
    DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
        CurrencyPluralInfo info = null;
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            info = new CurrencyPluralInfo(inputSymbols.getULocale());
        }
        create(pattern, inputSymbols, info, style);
    }

    /**
     * {@inheritDoc}
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    // See if number is negative.
    // usage: isNegative(multiply(numberToBeFormatted));
    private boolean isNegative(double number) {
        // Detecting whether a double is negative is easy with the exception of the value
        // -0.0. This is a double which has a zero mantissa (and exponent), but a negative
        // sign bit. It is semantically distinct from a zero with a positive sign bit, and
        // this distinction is important to certain kinds of computations. However, it's a
        // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you
        // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
        // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by
        // bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
        return (number < 0.0) || (number == 0.0 && 1 / number < 0.0);
    }

    // Rounds the number and strips of the negative sign.
    // usage: round(multiply(numberToBeFormatted))
    private double round(double number) {
        boolean isNegative = isNegative(number);
        if (isNegative)
            number = -number;

        // Apply rounding after multiplier
        if (roundingDouble > 0.0) {
            // number = roundingDouble
            //    * round(number / roundingDouble, roundingMode, isNegative);
            return round(
                number, roundingDouble, roundingDoubleReciprocal, roundingMode,
                isNegative);
        }
        return number;
    }

    // Multiplies given number by multipler (if there is one) returning the new
    // number. If there is no multiplier, returns the number passed in unchanged.
    private double multiply(double number) {
        if (multiplier != 1) {
            return number * multiplier;
        }
        return number;
    }

    // [Spark/CDL] The actual method to format number. If boolean value
    // parseAttr == true, then attribute information will be recorded.
    private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition,
                                boolean parseAttr) {
        fieldPosition.setBeginIndex(0);
        fieldPosition.setEndIndex(0);

        if (Double.isNaN(number)) {
            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setBeginIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setBeginIndex(result.length());
            }

            result.append(symbols.getNaN());
            // [Spark/CDL] Add attribute for NaN here.
            // result.append(symbols.getNaN());
            if (parseAttr) {
                addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(),
                             result.length());
            }
            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setEndIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setEndIndex(result.length());
            }

            addPadding(result, fieldPosition, 0, 0);
            return result;
        }

        // Do this BEFORE checking to see if value is negative or infinite and
        // before rounding.
        number = multiply(number);
        boolean isNegative = isNegative(number);
        number = round(number);

        if (Double.isInfinite(number)) {
            int prefixLen = appendAffix(result, isNegative, true, parseAttr);

            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setBeginIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setBeginIndex(result.length());
            }

            // [Spark/CDL] Add attribute for infinity here.
            result.append(symbols.getInfinity());
            if (parseAttr) {
                addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(),
                             result.length());
            }
            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                fieldPosition.setEndIndex(result.length());
            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                fieldPosition.setEndIndex(result.length());
            }

            int suffixLen = appendAffix(result, isNegative, false, parseAttr);

            addPadding(result, fieldPosition, prefixLen, suffixLen);
            return result;
        }

        // At this point we are guaranteed a nonnegative finite
        // number.
        synchronized (digitList) {
            digitList.set(number, precision(false), !useExponentialNotation &&
                          !areSignificantDigitsUsed());
            return subformat(number, result, fieldPosition, isNegative, false, parseAttr);
        }
    }

    /**
     * This is a special function used by the CompactDecimalFormat subclass.
     * It completes only the rounding portion of the formatting and returns
     * the resulting double. CompactDecimalFormat uses the result to compute
     * the plural form to use.
     *
     * @param number The number to format.
     * @return The number rounded to the correct number of significant digits
     * with negative sign stripped off.
     * @internal
     * @deprecated
     */
    @Deprecated
    double adjustNumberAsInFormatting(double number) {
        if (Double.isNaN(number)) {
            return number;
        }
        number = round(multiply(number));
        if (Double.isInfinite(number)) {
            return number;
        }
        DigitList dl = new DigitList();
        dl.set(number, precision(false), false);
        return dl.getDouble();
    }

    /**
      * This is a special function used by the CompactDecimalFormat subclass
      * to determine if the number to be formatted is negative.
      *
      * @param number The number to format.
      * @return True if number is negative.
      * @internal
      * @deprecated
      */
     @Deprecated
     boolean isNumberNegative(double number) {
         if (Double.isNaN(number)) {
             return false;
         }
         return isNegative(multiply(number));
     }

    /**
     * Round a double value to the nearest multiple of the given rounding increment,
     * according to the given mode. This is equivalent to rounding value/roundingInc to
     * the nearest integer, according to the given mode, and returning that integer *
     * roundingInc. Note this is changed from the version in 2.4, since division of
     * doubles have inaccuracies. jitterbug 1871.
     *
     * @param number
     *            the absolute value of the number to be rounded
     * @param roundingInc
     *            the rounding increment
     * @param roundingIncReciprocal
     *            if non-zero, is the
     * @param mode
     *            a BigDecimal rounding mode
     * @param isNegative
     *            true if the number to be rounded is negative
     * @return the absolute value of the rounded result
     */
    private static double round(double number, double roundingInc, double roundingIncReciprocal,
                                int mode, boolean isNegative) {

        double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number *
            roundingIncReciprocal;

        // do the absolute cases first

        switch (mode) {
        case BigDecimal.ROUND_CEILING:
            div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
            break;
        case BigDecimal.ROUND_FLOOR:
            div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
            break;
        case BigDecimal.ROUND_DOWN:
            div = (Math.floor(div + epsilon));
            break;
        case BigDecimal.ROUND_UP:
            div = (Math.ceil(div - epsilon));
            break;
        case BigDecimal.ROUND_UNNECESSARY:
            if (div != Math.floor(div)) {
                throw new ArithmeticException("Rounding necessary");
            }
            return number;
        default:

            // Handle complex cases, where the choice depends on the closer value.

            // We figure out the distances to the two possible values, ceiling and floor.
            // We then go for the diff that is smaller.  Only if they are equal does the
            // mode matter.

            double ceil = Math.ceil(div);
            double ceildiff = ceil - div; // (ceil * roundingInc) - number;
            double floor = Math.floor(div);
            double floordiff = div - floor; // number - (floor * roundingInc);

            // Note that the diff values were those mapped back to the "normal" space by
            // using the roundingInc. I don't have access to the original author of the
            // code but suspect that that was to produce better result in edge cases
            // because of machine precision, rather than simply using the difference
            // between, say, ceil and div.  However, it didn't work in all cases. Am
            // trying instead using an epsilon value.

            switch (mode) {
            case BigDecimal.ROUND_HALF_EVEN:
                // We should be able to just return Math.rint(a), but this
                // doesn't work in some VMs.
                // if one is smaller than the other, take the corresponding side
                if (floordiff + epsilon < ceildiff) {
                    div = floor;
                } else if (ceildiff + epsilon < floordiff) {
                    div = ceil;
                } else { // they are equal, so we want to round to whichever is even
                    double testFloor = floor / 2;
                    div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
                }
                break;
            case BigDecimal.ROUND_HALF_DOWN:
                div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
                break;
            case BigDecimal.ROUND_HALF_UP:
                div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
                break;
            default:
                throw new IllegalArgumentException("Invalid rounding mode: " + mode);
            }
        }
        number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal;
        return number;
    }

    private static double epsilon = 0.00000000001;

    /**
     * @stable ICU 2.0
     */
    // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
    @Override
    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition,
                                boolean parseAttr) {
        fieldPosition.setBeginIndex(0);
        fieldPosition.setEndIndex(0);

        // If we are to do rounding, we need to move into the BigDecimal
        // domain in order to do divide/multiply correctly.
        if (roundingIncrementICU != null) {
            return format(BigDecimal.valueOf(number), result, fieldPosition);
        }

        boolean isNegative = (number < 0);
        if (isNegative)
            number = -number;

        // In general, long values always represent real finite numbers, so we don't have
        // to check for +/- Infinity or NaN. However, there is one case we have to be
        // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE
        // outside the legal range. We check for this before multiplying, and if it
        // happens we use BigInteger instead.
        if (multiplier != 1) {
            boolean tooBig = false;
            if (number < 0) { // This can only happen if number == Long.MIN_VALUE
                long cutoff = Long.MIN_VALUE / multiplier;
                tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
            } else {
                long cutoff = Long.MAX_VALUE / multiplier;
                tooBig = (number > cutoff);
            }
            if (tooBig) {
                // [Spark/CDL] Use
                // format_BigInteger_StringBuffer_FieldPosition_boolean instead
                // parseAttr is used to judge whether to synthesize attributes.
                return format(BigInteger.valueOf(isNegative ? -number : number), result,
                              fieldPosition, parseAttr);
            }
        }

        number *= multiplier;
        synchronized (digitList) {
            digitList.set(number, precision(true));
            return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
        }
    }

    /**
     * Formats a BigInteger number.
     *
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(BigInteger number, StringBuffer result,
                               FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition,
                                boolean parseAttr) {
        // If we are to do rounding, we need to move into the BigDecimal
        // domain in order to do divide/multiply correctly.
        if (roundingIncrementICU != null) {
            return format(new BigDecimal(number), result, fieldPosition);
        }

        if (multiplier != 1) {
            number = number.multiply(BigInteger.valueOf(multiplier));
        }

        // At this point we are guaranteed a nonnegative finite
        // number.
        synchronized (digitList) {
            digitList.set(number, precision(true));
            return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
                             parseAttr);
        }
    }

    /**
     * Formats a BigDecimal number.
     *
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
                               FieldPosition fieldPosition) {
        return format(number, result, fieldPosition, false);
    }

    private StringBuffer format(java.math.BigDecimal number, StringBuffer result,
                                FieldPosition fieldPosition,
            boolean parseAttr) {
        if (multiplier != 1) {
            number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
        }

        if (roundingIncrement != null) {
            number = number.divide(roundingIncrement, 0, roundingMode).multiply(roundingIncrement);
        }

        synchronized (digitList) {
            digitList.set(number, precision(false), !useExponentialNotation &&
                          !areSignificantDigitsUsed());
            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
                             false, parseAttr);
        }
    }

    /**
     * Formats a BigDecimal number.
     *
     * @stable ICU 2.0
     */
    @Override
    public StringBuffer format(BigDecimal number, StringBuffer result,
                               FieldPosition fieldPosition) {
         // This method is just a copy of the corresponding java.math.BigDecimal method
         // for now. It isn't very efficient since it must create a conversion object to
         // do math on the rounding increment. In the future we may try to clean this up,
         // or even better, limit our support to just one flavor of BigDecimal.
        if (multiplier != 1) {
            number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
        }

        if (roundingIncrementICU != null) {
            number = number.divide(roundingIncrementICU, 0, roundingMode)
                .multiply(roundingIncrementICU, mathContext);
        }

        synchronized (digitList) {
            digitList.set(number, precision(false), !useExponentialNotation &&
                          !areSignificantDigitsUsed());
            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
                             false, false);
        }
    }

    /**
     * Returns true if a grouping separator belongs at the given position, based on whether
     * grouping is in use and the values of the primary and secondary grouping interval.
     *
     * @param pos the number of integer digits to the right of the current position. Zero
     * indicates the position after the rightmost integer digit.
     * @return true if a grouping character belongs at the current position.
     */
    private boolean isGroupingPosition(int pos) {
        boolean result = false;
        if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
            if ((groupingSize2 > 0) && (pos > groupingSize)) {
                result = ((pos - groupingSize) % groupingSize2) == 0;
            } else {
                result = pos % groupingSize == 0;
            }
        }
        return result;
    }

    /**
     * Return the number of fraction digits to display, or the total
     * number of digits for significant digit formats and exponential
     * formats.
     */
    private int precision(boolean isIntegral) {
        if (areSignificantDigitsUsed()) {
            return getMaximumSignificantDigits();
        } else if (useExponentialNotation) {
            return getMinimumIntegerDigits() + getMaximumFractionDigits();
        } else {
            return isIntegral ? 0 : getMaximumFractionDigits();
        }
    }

    private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition,
                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            return subformat(currencyPluralInfo.select(number), result, fieldPosition, isNegative,
                             isInteger, parseAttr);
        } else {
            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
        }
    }

    private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition,
                                   boolean isNegative,
            boolean isInteger, boolean parseAttr) {
        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
            return subformat(currencyPluralInfo.select(number), result, fieldPosition, isNegative,
                             isInteger, parseAttr);
        } else {
            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
        }
    }

    private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition,
            boolean isNegative, boolean isInteger, boolean parseAttr) {
        // There are 2 ways to activate currency plural format: by applying a pattern with
        // 3 currency sign directly, or by instantiate a decimal formatter using
        // PLURALCURRENCYSTYLE.  For both cases, the number of currency sign in the
        // pattern is 3.  Even if the number of currency sign in the pattern is 3, it does
        // not mean we need to reset the pattern.  For 1st case, we do not need to reset
        // pattern.  For 2nd case, we might need to reset pattern, if the default pattern
        // (corresponding to plural count 'other') we use is different from the pattern
        // based on 'pluralCount'.
        //
        // style is only valid when decimal formatter is constructed through
        // DecimalFormat(pattern, symbol, style)
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
            String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
            if (formatPattern.equals(currencyPluralPattern) == false) {
                applyPatternWithoutExpandAffix(currencyPluralPattern, false);
            }
        }
        // Expand the affix to the right name according to the plural rule.  This is only
        // used for currency plural formatting.  Currency plural name is not a fixed
        // static one, it is a dynamic name based on the currency plural count.  So, the
        // affixes need to be expanded here.  For other cases, the affix is a static one
        // based on pattern alone, and it is already expanded during applying pattern, or
        // setDecimalFormatSymbols, or setCurrency.
        expandAffixAdjustWidth(pluralCount);
        return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
    }

    /**
     * Complete the formatting of a finite number. On entry, the
     * digitList must be filled in with the correct digits.
     */
    private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,
                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
        // NOTE: This isn't required anymore because DigitList takes care of this.
        //
        // // The negative of the exponent represents the number of leading // zeros
        // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g.,
        // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction
        // digits, then we have an underflow // for the printed representation. We
        // recognize this here and set // the DigitList representation to zero in this
        // situation.
        //
        // if (-digitList.decimalAt >= getMaximumFractionDigits())
        // {
        // digitList.count = 0;
        // }



        // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as
        // zero. This allows sensible computations and preserves relations such as
        // signum(1/x) = signum(x), where x is +Infinity or -Infinity.  Prior to this fix,
        // we always formatted zero values as if they were positive. Liu 7/6/98.
        if (digitList.isZero()) {
            digitList.decimalAt = 0; // Normalize
        }

        int prefixLen = appendAffix(result, isNegative, true, parseAttr);

        if (useExponentialNotation) {
            subformatExponential(result, fieldPosition, parseAttr);
        } else {
            subformatFixed(result, fieldPosition, isInteger, parseAttr);
        }

        int suffixLen = appendAffix(result, isNegative, false, parseAttr);

        addPadding(result, fieldPosition, prefixLen, suffixLen);
        return result;
    }

    private void subformatFixed(StringBuffer result,
            FieldPosition fieldPosition,
            boolean isInteger,
            boolean parseAttr) {
        char [] digits = symbols.getDigitsLocal();

        char grouping = currencySignCount > 0 ? symbols.getMonetaryGroupingSeparator() :
            symbols.getGroupingSeparator();
        char decimal = currencySignCount > 0 ? symbols.getMonetaryDecimalSeparator() :
            symbols.getDecimalSeparator();
        boolean useSigDig = areSignificantDigitsUsed();
        int maxIntDig = getMaximumIntegerDigits();
        int minIntDig = getMinimumIntegerDigits();
        int i;
        // [Spark/CDL] Record the integer start index.
        int intBegin = result.length();
        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            fieldPosition.setBeginIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            fieldPosition.setBeginIndex(result.length());
        }

        int sigCount = 0;
        int minSigDig = getMinimumSignificantDigits();
        int maxSigDig = getMaximumSignificantDigits();
        if (!useSigDig) {
            minSigDig = 0;
            maxSigDig = Integer.MAX_VALUE;
        }

        // Output the integer portion. Here 'count' is the total number of integer
        // digits we will display, including both leading zeros required to satisfy
        // getMinimumIntegerDigits, and actual digits present in the number.
        int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig;
        if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
            count = digitList.decimalAt;
        }

        // Handle the case where getMaximumIntegerDigits() is smaller than the real
        // number of integer digits. If this is so, we output the least significant
        // max integer digits. For example, the value 1997 printed with 2 max integer
        // digits is just "97".

        int digitIndex = 0; // Index into digitList.fDigits[]
        if (count > maxIntDig && maxIntDig >= 0) {
            count = maxIntDig;
            digitIndex = digitList.decimalAt - count;
        }

        int sizeBeforeIntegerPart = result.length();
        for (i = count - 1; i >= 0; --i) {
            if (i < digitList.decimalAt && digitIndex < digitList.count
                && sigCount < maxSigDig) {
                // Output a real digit
                result.append(digits[digitList.getDigitValue(digitIndex++)]);
                ++sigCount;
            } else {
                // Output a zero (leading or trailing)
                result.append(digits[0]);
                if (sigCount > 0) {
                    ++sigCount;
                }
            }

            // Output grouping separator if necessary.
            if (isGroupingPosition(i)) {
                result.append(grouping);
                // [Spark/CDL] Add grouping separator attribute here.
                if (parseAttr) {
                    // Length of grouping separator is 1.
                    addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
                }
            }
        }

        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            fieldPosition.setEndIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            fieldPosition.setEndIndex(result.length());
        }

        // Determine whether or not there are any printable fractional digits. If
        // we've used up the digits we know there aren't.
        boolean fractionPresent = (!isInteger && digitIndex < digitList.count)
                || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));

        // If there is no fraction present, and we haven't printed any integer digits,
        // then print a zero. Otherwise we won't print _any_ digits, and we won't be
        // able to parse this string.
        if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
            result.append(digits[0]);
        // [Spark/CDL] Add attribute for integer part.
        if (parseAttr) {
            addAttribute(Field.INTEGER, intBegin, result.length());
        }
        // Output the decimal separator if we always do so.
        if (decimalSeparatorAlwaysShown || fractionPresent) {
            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
                fieldPosition.setBeginIndex(result.length());
            }
            result.append(decimal);
            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
                fieldPosition.setEndIndex(result.length());
            }
            // [Spark/CDL] Add attribute for decimal separator
            if (parseAttr) {
                addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length());
            }
        }

        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            fieldPosition.setBeginIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            fieldPosition.setBeginIndex(result.length());
        }

        // [Spark/CDL] Record the begin index of fraction part.
        int fracBegin = result.length();

        count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
        if (useSigDig && (sigCount == maxSigDig ||
                          (sigCount >= minSigDig && digitIndex == digitList.count))) {
            count = 0;
        }
        for (i = 0; i < count; ++i) {
            // Here is where we escape from the loop. We escape if we've output the
            // maximum fraction digits (specified in the for expression above). We
            // also stop when we've output the minimum digits and either: we have an
            // integer, so there is no fractional stuff to display, or we're out of
            // significant digits.
            if (!useSigDig && i >= getMinimumFractionDigits() &&
                (isInteger || digitIndex >= digitList.count)) {
                break;
            }

            // Output leading fractional zeros. These are zeros that come after the
            // decimal but before any significant digits. These are only output if
            // abs(number being formatted) < 1.0.
            if (-1 - i > (digitList.decimalAt - 1)) {
                result.append(digits[0]);
                continue;
            }

            // Output a digit, if we have any precision left, or a zero if we
            // don't. We don't want to output noise digits.
            if (!isInteger && digitIndex < digitList.count) {
                result.append(digits[digitList.getDigitValue(digitIndex++)]);
            } else {
                result.append(digits[0]);
            }

            // If we reach the maximum number of significant digits, or if we output
            // all the real digits and reach the minimum, then we are done.
            ++sigCount;
            if (useSigDig && (sigCount == maxSigDig ||
                              (digitIndex == digitList.count && sigCount >= minSigDig))) {
                break;
            }
        }

        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            fieldPosition.setEndIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            fieldPosition.setEndIndex(result.length());
        }

        // [Spark/CDL] Add attribute information if necessary.
        if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
            addAttribute(Field.FRACTION, fracBegin, result.length());
        }
    }

    private void subformatExponential(StringBuffer result,
            FieldPosition fieldPosition,
            boolean parseAttr) {
        char [] digits = symbols.getDigitsLocal();
        char decimal = currencySignCount > 0 ? symbols.getMonetaryDecimalSeparator() :
            symbols.getDecimalSeparator();
        boolean useSigDig = areSignificantDigitsUsed();
        int maxIntDig = getMaximumIntegerDigits();
        int minIntDig = getMinimumIntegerDigits();
        int i;
        // Record field information for caller.
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            fieldPosition.setBeginIndex(result.length());
            fieldPosition.setEndIndex(-1);
        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            fieldPosition.setBeginIndex(-1);
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            fieldPosition.setBeginIndex(result.length());
            fieldPosition.setEndIndex(-1);
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            fieldPosition.setBeginIndex(-1);
        }

        // [Spark/CDL]
        // the begin index of integer part
        // the end index of integer part
        // the begin index of fractional part
        int intBegin = result.length();
        int intEnd = -1;
        int fracBegin = -1;
        int minFracDig = 0;
        if (useSigDig) {
            maxIntDig = minIntDig = 1;
            minFracDig = getMinimumSignificantDigits() - 1;
        } else {
            minFracDig = getMinimumFractionDigits();
            if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
                maxIntDig = 1;
                if (maxIntDig < minIntDig) {
                    maxIntDig = minIntDig;
                }
            }
            if (maxIntDig > minIntDig) {
                minIntDig = 1;
            }
        }

        // Minimum integer digits are handled in exponential format by adjusting the
        // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".

        // Maximum integer digits are interpreted as indicating the repeating
        // range. This is useful for engineering notation, in which the exponent is
        // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer
        // digits is "12.34e-3".  If maximum integer digits are defined and are larger
        // than minimum integer digits, then minimum integer digits are ignored.

        int exponent = digitList.decimalAt;
        if (maxIntDig > 1 && maxIntDig != minIntDig) {
            // A exponent increment is defined; adjust to it.
            exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1;
            exponent *= maxIntDig;
        } else {
            // No exponent increment is defined; use minimum integer digits.
            // If none is specified, as in "#E0", generate 1 integer digit.
            exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1;
        }

        // We now output a minimum number of digits, and more if there are more
        // digits, up to the maximum number of digits. We place the decimal point
        // after the "integer" digits, which are the first (decimalAt - exponent)
        // digits.
        int minimumDigits = minIntDig + minFracDig;
        // The number of integer digits is handled specially if the number
        // is zero, since then there may be no digits.
        int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent;
        int totalDigits = digitList.count;
        if (minimumDigits > totalDigits)
            totalDigits = minimumDigits;
        if (integerDigits > totalDigits)
            totalDigits = integerDigits;

        for (i = 0; i < totalDigits; ++i) {
            if (i == integerDigits) {
                // Record field information for caller.
                if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                    fieldPosition.setEndIndex(result.length());
                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
                    fieldPosition.setEndIndex(result.length());
                }

                // [Spark/CDL] Add attribute for integer part
                if (parseAttr) {
                    intEnd = result.length();
                    addAttribute(Field.INTEGER, intBegin, result.length());
                }
                result.append(decimal);
                // [Spark/CDL] Add attribute for decimal separator
                if (parseAttr) {
                    // Length of decimal separator is 1.
                    int decimalSeparatorBegin = result.length() - 1;
                    addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin,
                                 result.length());
                    fracBegin = result.length();
                }
                // Record field information for caller.
                if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
                    fieldPosition.setBeginIndex(result.length());
                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
                    fieldPosition.setBeginIndex(result.length());
                }
            }
            result.append((i < digitList.count)
                          ? digits[digitList.getDigitValue(i)]
                          : digits[0]);
        }

        // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
        if (digitList.isZero() && (totalDigits == 0)) {
            result.append(digits[0]);
        }

        // Record field information
        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
            if (fieldPosition.getEndIndex() < 0) {
                fieldPosition.setEndIndex(result.length());
            }
        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
            if (fieldPosition.getBeginIndex() < 0) {
                fieldPosition.setBeginIndex(result.length());
            }
            fieldPosition.setEndIndex(result.length());
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
            if (fieldPosition.getEndIndex() < 0) {
                fieldPosition.setEndIndex(result.length());
            }
        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
            if (fieldPosition.getBeginIndex() < 0) {
                fieldPosition.setBeginIndex(result.length());
            }
            fieldPosition.setEndIndex(result.length());
        }

        // [Spark/CDL] Calcuate the end index of integer part and fractional
        // part if they are not properly processed yet.
        if (parseAttr) {
            if (intEnd < 0) {
                addAttribute(Field.INTEGER, intBegin, result.length());
            }
            if (fracBegin > 0) {
                addAttribute(Field.FRACTION, fracBegin, result.length());
            }
        }

        // The exponent is output using the pattern-specified minimum exponent
        // digits. There is no maximum limit to the exponent digits, since truncating
        // the exponent would result in an unacceptable inaccuracy.
        result.append(symbols.getExponentSeparator());
        // [Spark/CDL] For exponent symbol, add an attribute.
        if (parseAttr) {
            addAttribute(Field.EXPONENT_SYMBOL, result.length() -
                         symbols.getExponentSeparator().length(), result.length());
        }
        // For zero values, we force the exponent to zero. We must do this here, and
        // not earlier, because the value is used to determine integer digit count
        // above.
        if (digitList.isZero())
            exponent = 0;

        boolean negativeExponent = exponent < 0;
        if (negativeExponent) {
            exponent = -exponent;
            result.append(symbols.getMinusSign());
            // [Spark/CDL] If exponent has sign, then add an exponent sign
            // attribute.
            if (parseAttr) {
                // Length of exponent sign is 1.
                addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
            }
        } else if (exponentSignAlwaysShown) {
            result.append(symbols.getPlusSign());
            // [Spark/CDL] Add an plus sign attribute.
            if (parseAttr) {
                // Length of exponent sign is 1.
                int expSignBegin = result.length() - 1;
                addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length());
            }
        }
        int expBegin = result.length();
        digitList.set(exponent);
        {
            int expDig = minExponentDigits;
            if (useExponentialNotation && expDig < 1) {
                expDig = 1;
            }
            for (i = digitList.decimalAt; i < expDig; ++i)
                result.append(digits[0]);
        }
        for (i = 0; i < digitList.decimalAt; ++i) {
            result.append((i < digitList.count) ? digits[digitList.getDigitValue(i)]
                          : digits[0]);
        }
        // [Spark/CDL] Add attribute for exponent part.
        if (parseAttr) {
            addAttribute(Field.EXPONENT, expBegin, result.length());
        }
    }

    private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen,
                                  int suffixLen) {
        if (formatWidth > 0) {
            int len = formatWidth - result.length();
            if (len > 0) {
                char[] padding = new char[len];
                for (int i = 0; i < len; ++i) {
                    padding[i] = pad;
                }
                switch (padPosition) {
                case PAD_AFTER_PREFIX:
                    result.insert(prefixLen, padding);
                    break;
                case PAD_BEFORE_PREFIX:
                    result.insert(0, padding);
                    break;
                case PAD_BEFORE_SUFFIX:
                    result.insert(result.length() - suffixLen, padding);
                    break;
                case PAD_AFTER_SUFFIX:
                    result.append(padding);
                    break;
                }
                if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) {
                    fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
                    fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
                }
            }
        }
    }

    /**
     * Parses the given string, returning a <code>Number</code> object to represent the
     * parsed value. <code>Double</code> objects are returned to represent non-integral
     * values which cannot be stored in a <code>BigDecimal</code>. These are
     * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
     * false (the default), all other values are returned as <code>Long</code>,
     * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
     * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
     * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
     *
     * @param text the string to be parsed
     * @param parsePosition defines the position where parsing is to begin, and upon
     * return, the position where parsing left off. If the position has not changed upon
     * return, then parsing failed.
     * @return a <code>Number</code> object with the parsed value or
     * <code>null</code> if the parse failed
     * @stable ICU 2.0
     */
    @Override
    public Number parse(String text, ParsePosition parsePosition) {
        return (Number) parse(text, parsePosition, null);
    }

    /**
     * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
     * this method will attempt to parse a generic currency name, searching for a match of
     * this object's locale's currency display names, or for a 3-letter ISO currency
     * code. This method will fail if this format is not a currency format, that is, if it
     * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
     *
     * @param text the text to parse
     * @param pos input-output position; on input, the position within text to match; must
     *  have 0 <= pos.getIndex() < text.length(); on output, the position after the last
     *  matched character. If the parse fails, the position in unchanged upon output.
     * @return a CurrencyAmount, or null upon failure
     * @stable ICU 49
     */
    @Override
    public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) {
        Currency[] currency = new Currency[1];
        return (CurrencyAmount) parse(text.toString(), pos, currency);
    }

    /**
     * Parses the given text as either a Number or a CurrencyAmount.
     *
     * @param text the string to parse
     * @param parsePosition input-output position; on input, the position within text to
     * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after
     * the last matched character. If the parse fails, the position in unchanged upon
     * output.
     * @param currency if non-null, a CurrencyAmount is parsed and returned; otherwise a
     * Number is parsed and returned
     * @return a Number or CurrencyAmount or null
     */
    private Object parse(String text, ParsePosition parsePosition, Currency[] currency) {
        int backup;
        int i = backup = parsePosition.getIndex();

        // Handle NaN as a special case:

        // Skip padding characters, if around prefix
        if (formatWidth > 0 &&
            (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {
            i = skipPadding(text, i);
        }
        if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) {
            i += symbols.getNaN().length();
            // Skip padding characters, if around suffix
            if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
                                    padPosition == PAD_AFTER_SUFFIX)) {
                i = skipPadding(text, i);
            }
            parsePosition.setIndex(i);
            return new Double(Double.NaN);
        }

        // NaN parse failed; start over
        i = backup;

        boolean[] status = new boolean[STATUS_LENGTH];
        if (currencySignCount > 0) {
            if (!parseForCurrency(text, parsePosition, currency, status)) {
                return null;
            }
        } else {
            if (!subparse(text, parsePosition, digitList, status, currency, negPrefixPattern,
                          negSuffixPattern, posPrefixPattern, posSuffixPattern,
                          Currency.SYMBOL_NAME)) {
                parsePosition.setIndex(backup);
                return null;
            }
        }

        Number n = null;

        // Handle infinity
        if (status[STATUS_INFINITE]) {
            n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY :
                           Double.NEGATIVE_INFINITY);
        }

        // Handle underflow
        else if (status[STATUS_UNDERFLOW]) {
            n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
        }

        // Handle -0.0
        else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
            n = new Double("-0.0");
        }

        else {
            // Do as much of the multiplier conversion as possible without
            // losing accuracy.
            int mult = multiplier; // Don't modify this.multiplier
            while (mult % 10 == 0) {
                --digitList.decimalAt;
                mult /= 10;
            }

            // Handle integral values
            if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
                // hack quick long
                if (digitList.decimalAt < 12) { // quick check for long
                    long l = 0;
                    if (digitList.count > 0) {
                        int nx = 0;
                        while (nx < digitList.count) {
                            l = l * 10 + (char) digitList.digits[nx++] - '0';
                        }
                        while (nx++ < digitList.decimalAt) {
                            l *= 10;
                        }
                        if (!status[STATUS_POSITIVE]) {
                            l = -l;
                        }
                    }
                    n = Long.valueOf(l);
                } else {
                    BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
                    n = (big.bitLength() < 64) ? (Number) Long.valueOf(big.longValue()) : (Number) big;
                }
            }
            // Handle non-integral values or the case where parseBigDecimal is set
            else {
                BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
                n = big;
                if (mult != 1) {
                    n = big.divide(BigDecimal.valueOf(mult), mathContext);
                }
            }
        }

        // Assemble into CurrencyAmount if necessary
        return (currency != null) ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n;
    }

    private boolean parseForCurrency(String text, ParsePosition parsePosition,
            Currency[] currency, boolean[] status) {
        int origPos = parsePosition.getIndex();
        if (!isReadyForParsing) {
            int savedCurrencySignCount = currencySignCount;
            setupCurrencyAffixForAllPatterns();
            // reset pattern back
            if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
                applyPatternWithoutExpandAffix(formatPattern, false);
            } else {
                applyPattern(formatPattern, false);
            }
            isReadyForParsing = true;
        }
        int maxPosIndex = origPos;
        int maxErrorPos = -1;
        boolean[] savedStatus = null;
        // First, parse against current pattern.
        // Since current pattern could be set by applyPattern(),
        // it could be an arbitrary pattern, and it may not be the one
        // defined in current locale.
        boolean[] tmpStatus = new boolean[STATUS_LENGTH];
        ParsePosition tmpPos = new ParsePosition(origPos);
        DigitList tmpDigitList = new DigitList();
        boolean found;
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
                             Currency.LONG_NAME);
        } else {
            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
                             Currency.SYMBOL_NAME);
        }
        if (found) {
            if (tmpPos.getIndex() > maxPosIndex) {
                maxPosIndex = tmpPos.getIndex();
                savedStatus = tmpStatus;
                digitList = tmpDigitList;
            }
        } else {
            maxErrorPos = tmpPos.getErrorIndex();
        }
        // Then, parse against affix patterns.  Those are currency patterns and currency
        // plural patterns defined in the locale.
        for (AffixForCurrency affix : affixPatternsForCurrency) {
            tmpStatus = new boolean[STATUS_LENGTH];
            tmpPos = new ParsePosition(origPos);
            tmpDigitList = new DigitList();
            boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                                      affix.getNegPrefix(), affix.getNegSuffix(),
                                      affix.getPosPrefix(), affix.getPosSuffix(),
                                      affix.getPatternType());
            if (result) {
                found = true;
                if (tmpPos.getIndex() > maxPosIndex) {
                    maxPosIndex = tmpPos.getIndex();
                    savedStatus = tmpStatus;
                    digitList = tmpDigitList;
                }
            } else {
                maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex()
                    : maxErrorPos;
            }
        }
        // Finally, parse against simple affix to find the match.  For example, in
        // TestMonster suite, if the to-be-parsed text is "-\u00A40,00".
        // complexAffixCompare will not find match, since there is no ISO code matches
        // "\u00A4", and the parse stops at "\u00A4".  We will just use simple affix
        // comparison (look for exact match) to pass it.
        tmpStatus = new boolean[STATUS_LENGTH];
        tmpPos = new ParsePosition(origPos);
        tmpDigitList = new DigitList();
        int savedCurrencySignCount = currencySignCount;
        // set currencySignCount to -1 so that compareAffix function will fall to
        // compareSimpleAffix path, not compareComplexAffix path.
        currencySignCount = -1;
        boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
                                  negativePrefix, negativeSuffix, positivePrefix, positiveSuffix,
                                  Currency.SYMBOL_NAME);
        currencySignCount = savedCurrencySignCount;
        if (result) {
            if (tmpPos.getIndex() > maxPosIndex) {
                maxPosIndex = tmpPos.getIndex();
                savedStatus = tmpStatus;
                digitList = tmpDigitList;
            }
            found = true;
        } else {
            maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() :
                maxErrorPos;
        }

        if (!found) {
            // parsePosition.setIndex(origPos);
            parsePosition.setErrorIndex(maxErrorPos);
        } else {
            parsePosition.setIndex(maxPosIndex);
            parsePosition.setErrorIndex(-1);
            for (int index = 0; index < STATUS_LENGTH; ++index) {
                status[index] = savedStatus[index];
            }
        }
        return found;
    }

    // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and
    // currency plural pattern (CurrencyUnitPatterns).
    private void setupCurrencyAffixForAllPatterns() {
        if (currencyPluralInfo == null) {
            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
        }
        affixPatternsForCurrency = new HashSet<AffixForCurrency>();

        // save the current pattern, since it will be changed by
        // applyPatternWithoutExpandAffix
        String savedFormatPattern = formatPattern;

        // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so,
        // only need to save one of them.  Here, chose onlyApplyPatternWithoutExpandAffix
        // without saving the actualy pattern in 'pattern' data member.  TODO: is it uloc?
        applyPatternWithoutExpandAffix(getPattern(symbols.getULocale(), NumberFormat.CURRENCYSTYLE),
                                       false);
        AffixForCurrency affixes = new AffixForCurrency(
            negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
            Currency.SYMBOL_NAME);
        affixPatternsForCurrency.add(affixes);

        // add plural pattern
        Iterator<String> iter = currencyPluralInfo.pluralPatternIterator();
        Set<String> currencyUnitPatternSet = new HashSet<String>();
        while (iter.hasNext()) {
            String pluralCount = iter.next();
            String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
            if (currencyPattern != null &&
                currencyUnitPatternSet.contains(currencyPattern) == false) {
                currencyUnitPatternSet.add(currencyPattern);
                applyPatternWithoutExpandAffix(currencyPattern, false);
                affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern,
                                               posSuffixPattern, Currency.LONG_NAME);
                affixPatternsForCurrency.add(affixes);
            }
        }
        // reset pattern back
        formatPattern = savedFormatPattern;
    }

    private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
    private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
    private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;

    private static final int STATUS_INFINITE = 0;
    private static final int STATUS_POSITIVE = 1;
    private static final int STATUS_UNDERFLOW = 2;
    private static final int STATUS_LENGTH = 3;

    private static final UnicodeSet dotEquivalents = new UnicodeSet(
            //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]"
            0x002E, 0x002E,
            0x2024, 0x2024,
            0x3002, 0x3002,
            0xFE12, 0xFE12,
            0xFE52, 0xFE52,
            0xFF0E, 0xFF0E,
            0xFF61, 0xFF61).freeze();

    private static final UnicodeSet commaEquivalents = new UnicodeSet(
            //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]"
            0x002C, 0x002C,
            0x060C, 0x060C,
            0x066B, 0x066B,
            0x3001, 0x3001,
            0xFE10, 0xFE11,
            0xFE50, 0xFE51,
            0xFF0C, 0xFF0C,
            0xFF64, 0xFF64).freeze();

//    private static final UnicodeSet otherGroupingSeparators = new UnicodeSet(
//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
//            0x0020, 0x0020,
//            0x0027, 0x0027,
//            0x00A0, 0x00A0,
//            0x066C, 0x066C,
//            0x2000, 0x200A,
//            0x2018, 0x2019,
//            0x202F, 0x202F,
//            0x205F, 0x205F,
//            0x3000, 0x3000,
//            0xFF07, 0xFF07).freeze();

    private static final UnicodeSet strictDotEquivalents = new UnicodeSet(
            //"[.\u2024\uFE52\uFF0E\uFF61]"
            0x002E, 0x002E,
            0x2024, 0x2024,
            0xFE52, 0xFE52,
            0xFF0E, 0xFF0E,
            0xFF61, 0xFF61).freeze();

    private static final UnicodeSet strictCommaEquivalents = new UnicodeSet(
            //"[,\u066B\uFE10\uFE50\uFF0C]"
            0x002C, 0x002C,
            0x066B, 0x066B,
            0xFE10, 0xFE10,
            0xFE50, 0xFE50,
            0xFF0C, 0xFF0C).freeze();

//    private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet(
//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
//            0x0020, 0x0020,
//            0x0027, 0x0027,
//            0x00A0, 0x00A0,
//            0x066C, 0x066C,
//            0x2000, 0x200A,
//            0x2018, 0x2019,
//            0x202F, 0x202F,
//            0x205F, 0x205F,
//            0x3000, 0x3000,
//            0xFF07, 0xFF07).freeze();

    private static final UnicodeSet defaultGroupingSeparators =
        // new UnicodeSet(dotEquivalents).addAll(commaEquivalents)
        //     .addAll(otherGroupingSeparators).freeze();
        new UnicodeSet(
                0x0020, 0x0020,
                0x0027, 0x0027,
                0x002C, 0x002C,
                0x002E, 0x002E,
                0x00A0, 0x00A0,
                0x060C, 0x060C,
                0x066B, 0x066C,
                0x2000, 0x200A,
                0x2018, 0x2019,
                0x2024, 0x2024,
                0x202F, 0x202F,
                0x205F, 0x205F,
                0x3000, 0x3002,
                0xFE10, 0xFE12,
                0xFE50, 0xFE52,
                0xFF07, 0xFF07,
                0xFF0C, 0xFF0C,
                0xFF0E, 0xFF0E,
                0xFF61, 0xFF61,
                0xFF64, 0xFF64).freeze();

    private static final UnicodeSet strictDefaultGroupingSeparators =
        // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents)
        //     .addAll(strictOtherGroupingSeparators).freeze();
        new UnicodeSet(
                0x0020, 0x0020,
                0x0027, 0x0027,
                0x002C, 0x002C,
                0x002E, 0x002E,
                0x00A0, 0x00A0,
                0x066B, 0x066C,
                0x2000, 0x200A,
                0x2018, 0x2019,
                0x2024, 0x2024,
                0x202F, 0x202F,
                0x205F, 0x205F,
                0x3000, 0x3000,
                0xFE10, 0xFE10,
                0xFE50, 0xFE50,
                0xFE52, 0xFE52,
                0xFF07, 0xFF07,
                0xFF0C, 0xFF0C,
                0xFF0E, 0xFF0E,
                0xFF61, 0xFF61).freeze();

    // When parsing a number with big exponential value, it requires to transform the
    // value into a string representation to construct BigInteger instance.  We want to
    // set the maximum size because it can easily trigger OutOfMemoryException.
    // PARSE_MAX_EXPONENT is currently set to 1000 (See getParseMaxDigits()),
    // which is much bigger than MAX_VALUE of Double ( See the problem reported by ticket#5698
    private int PARSE_MAX_EXPONENT = 1000;

    /**
     * Parses the given text into a number. The text is parsed beginning at parsePosition,
     * until an unparseable character is seen.
     *
     * @param text the string to parse.
     * @param parsePosition the position at which to being parsing. Upon return, the first
     * unparseable character.
     * @param digits the DigitList to set to the parsed value.
     * @param status Upon return contains boolean status flags indicating whether the
     * value was infinite and whether it was positive.
     * @param currency return value for parsed currency, for generic currency parsing
     * mode, or null for normal parsing. In generic currency parsing mode, any currency is
     * parsed, not just the currency that this formatter is set to.
     * @param negPrefix negative prefix pattern
     * @param negSuffix negative suffix pattern
     * @param posPrefix positive prefix pattern
     * @param negSuffix negative suffix pattern
     * @param type type of currency to parse against, LONG_NAME only or not.
     */
    private final boolean subparse(
        String text, ParsePosition parsePosition, DigitList digits,
        boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix,
        String posSuffix, int type) {

        int position = parsePosition.getIndex();
        int oldStart = parsePosition.getIndex();

        // Match padding before prefix
        if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
            position = skipPadding(text, position);
        }

        // Match positive and negative prefixes; prefer longest match.
        int posMatch = compareAffix(text, position, false, true, posPrefix, type, currency);
        int negMatch = compareAffix(text, position, true, true, negPrefix, type, currency);
        if (posMatch >= 0 && negMatch >= 0) {
            if (posMatch > negMatch) {
                negMatch = -1;
            } else if (negMatch > posMatch) {
                posMatch = -1;
            }
        }
        if (posMatch >= 0) {
            position += posMatch;
        } else if (negMatch >= 0) {
            position += negMatch;
        } else {
            parsePosition.setErrorIndex(position);
            return false;
        }

        // Match padding after prefix
        if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
            position = skipPadding(text, position);
        }

        // process digits or Inf, find decimal position
        status[STATUS_INFINITE] = false;
        if (text.regionMatches(position, symbols.getInfinity(), 0,
                                              symbols.getInfinity().length())) {
            position += symbols.getInfinity().length();
            status[STATUS_INFINITE] = true;
        } else {
            // We now have a string of digits, possibly with grouping symbols, and decimal
            // points. We want to process these into a DigitList.  We don't want to put a
            // bunch of leading zeros into the DigitList though, so we keep track of the
            // location of the decimal point, put only significant digits into the
            // DigitList, and adjust the exponent as needed.

            digits.decimalAt = digits.count = 0;
            char [] digitSymbols = symbols.getDigitsLocal();
            char decimal = currencySignCount == 0 ? symbols.getDecimalSeparator()
                    : symbols.getMonetaryDecimalSeparator();
            char grouping = symbols.getGroupingSeparator();

            String exponentSep = symbols.getExponentSeparator();
            boolean sawDecimal = false;
            boolean sawGrouping = false;
            boolean sawExponent = false;
            boolean sawDigit = false;
            long exponent = 0; // Set to the exponent value, if any
            int digit = 0;

            // strict parsing
            boolean strictParse = isParseStrict();
            boolean strictFail = false; // did we exit with a strict parse failure?
            int lastGroup = -1; // where did we last see a grouping separator?
            int digitStart = position; // where did the digit start?
            int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;

            // equivalent grouping and decimal support
            boolean skipExtendedSeparatorParsing = ICUConfig.get(
                "com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
                .equals("true");

            UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
                getEquivalentDecimals(decimal, strictParse);
            UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
                (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators);

            // We have to track digitCount ourselves, because digits.count will pin when
            // the maximum allowable digits is reached.
            int digitCount = 0;

            int backup = -1;
            int ch;
            for (; position < text.length(); position += UTF16.getCharCount(ch)) {
                ch = UTF16.charAt(text,position);


                // We recognize all digit ranges, not only the Latin digit range
                // '0'..'9'. We do so by using the UCharacter.digit() method, which
                // converts a valid Unicode digit to the range 0..9.
                //
                // The character 'ch' may be a digit. If so, place its value from 0 to 9
                // in 'digit'. First try using the locale digit, which may or MAY NOT be a
                // standard Unicode digit range. If this fails, try using the standard
                // Unicode digit ranges by calling UCharacter.digit(). If this also fails,
                // digit will have a value outside the range 0..9.
                digit = ch - digitSymbols[0];
                if (digit < 0 || digit > 9)
                    digit = UCharacter.digit(ch, 10);
                if (digit < 0 || digit > 9) {
                    for ( digit = 0 ; digit < 10 ; digit++) {
                        if ( ch == digitSymbols[digit] )
                            break;
                    }
                }



                if (digit == 0) {
                    // Cancel out backup setting (see grouping handler below)
                    if (strictParse && backup != -1) {
                        // comma followed by digit, so group before comma is a secondary
                        // group. If there was a group separator before that, the group
                        // must == the secondary group length, else it can be <= the the
                        // secondary group length.
                        if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
                                || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
                            strictFail = true;
                            break;
                        }
                        lastGroup = backup;
                    }
                    backup = -1; // Do this BEFORE continue statement below!!!
                    sawDigit = true;

                    // Handle leading zeros
                    if (digits.count == 0) {
                        if (!sawDecimal) {
                            // Ignore leading zeros in integer part of number.
                            continue;
                        }

                        // If we have seen the decimal, but no significant digits yet,
                        // then we account for leading zeros by decrementing the
                        // digits.decimalAt into negative values.
                        --digits.decimalAt;
                    } else {
                        ++digitCount;
                        digits.append((char) (digit + '0'));
                    }
                } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
                {
                    if (strictParse) {
                        if (backup != -1) {
                            if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
                                    || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
                                strictFail = true;
                                break;
                            }
                            lastGroup = backup;
                        }
                    }

                    sawDigit = true;
                    ++digitCount;
                    digits.append((char) (digit + '0'));

                    // Cancel out backup setting (see grouping handler below)
                    backup = -1;
                } else if (ch == decimal) {
                    if (strictParse) {
                        if (backup != -1 ||
                            (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
                            strictFail = true;
                            break;
                        }
                    }
                    // If we're only parsing integers, or if we ALREADY saw the decimal,
                    // then don't parse this one.
                    if (isParseIntegerOnly() || sawDecimal) {
                        break;
                    }
                    digits.decimalAt = digitCount; // Not digits.count!
                    sawDecimal = true;
                } else if (isGroupingUsed() && ch == grouping) {
                    if (sawDecimal) {
                        break;
                    }
                    if (strictParse) {
                        if ((!sawDigit || backup != -1)) {
                            // leading group, or two group separators in a row
                            strictFail = true;
                            break;
                        }
                    }
                    // Ignore grouping characters, if we are using them, but require that
                    // they be followed by a digit. Otherwise we backup and reprocess
                    // them.
                    backup = position;
                    sawGrouping = true;
                } else if (!sawDecimal && decimalEquiv.contains(ch)) {
                    if (strictParse) {
                        if (backup != -1 ||
                            (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
                            strictFail = true;
                            break;
                        }
                    }
                    // If we're only parsing integers, then don't parse this one.
                    if (isParseIntegerOnly())
                        break;
                    digits.decimalAt = digitCount; // Not digits.count!

                    // Once we see a decimal separator character, we only accept that
                    // decimal separator character from then on.
                    decimal = (char) ch;
                    sawDecimal = true;
                } else if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(ch)) {
                    if (sawDecimal) {
                        break;
                    }
                    if (strictParse) {
                        if ((!sawDigit || backup != -1)) {
                            // leading group, or two group separators in a row
                            strictFail = true;
                            break;
                        }
                    }
                    // Once we see a grouping character, we only accept that grouping
                    // character from then on.
                    grouping = (char) ch;

                    // Ignore grouping characters, if we are using them, but require that
                    // they be followed by a digit. Otherwise we backup and reprocess
                    // them.
                    backup = position;
                    sawGrouping = true;
                } else if (!sawExponent && text.regionMatches(true, position, exponentSep, 0, exponentSep.length())) {
                    // Parse sign, if present
                    boolean negExp = false;
                    int pos = position + exponentSep.length();
                    if (pos < text.length()) {
                        ch = UTF16.charAt(text,pos);
                        if (ch == symbols.getPlusSign()) {
                            ++pos;
                        } else if (ch == symbols.getMinusSign()) {
                            ++pos;
                            negExp = true;
                        }
                    }

                    DigitList exponentDigits = new DigitList();
                    exponentDigits.count = 0;
                    while (pos < text.length()) {
                        digit = UTF16.charAt(text,pos) - digitSymbols[0];
                        if (digit < 0 || digit > 9) {
                            // Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
                            // Should update reassign the value of 'ch' in the code: digit
                            // = Character.digit(ch, 10); [Richard/GCL]
                            digit = UCharacter.digit(UTF16.charAt(text,pos), 10);
                        }
                        if (digit >= 0 && digit <= 9) {
                            exponentDigits.append((char) (digit + '0'));
                            pos += UTF16.getCharCount(UTF16.charAt(text,pos));
                        } else {
                            break;
                        }
                    }

                    if (exponentDigits.count > 0) {
                        // defer strict parse until we know we have a bona-fide exponent
                        if (strictParse) {
                            if (backup != -1 || lastGroup != -1) {
                                strictFail = true;
                                break;
                            }
                        }

                        // Quick overflow check for exponential part.  Actual limit check
                        // will be done later in this code.
                        if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
                            if (negExp) {
                                // set underflow flag
                                status[STATUS_UNDERFLOW] = true;
                            } else {
                                // set infinite flag
                                status[STATUS_INFINITE] = true;
                            }
                        } else {
                            exponentDigits.decimalAt = exponentDigits.count;
                            exponent = exponentDigits.getLong();
                            if (negExp) {
                                exponent = -exponent;
                            }
                        }
                        position = pos; // Advance past the exponent
                        sawExponent = true;
                    }

                    break; // Whether we fail or succeed, we exit this loop
                } else {
                    break;
                }
            }

            if (backup != -1)
                position = backup;

            // If there was no decimal point we have an integer
            if (!sawDecimal)
                digits.decimalAt = digitCount; // Not digits.count!

            // check for strict parse errors
            if (strictParse && !sawDecimal) {
                if (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1) {
                    strictFail = true;
                }
            }
            if (strictFail) {
                // only set with strictParse and a leading zero error leading zeros are an
                // error with strict parsing except immediately before nondigit (except
                // group separator followed by digit), or end of text.

                parsePosition.setIndex(oldStart);
                parsePosition.setErrorIndex(position);
                return false;
            }

            // Adjust for exponent, if any
            exponent += digits.decimalAt;
            if (exponent < -getParseMaxDigits()) {
                status[STATUS_UNDERFLOW] = true;
            } else if (exponent > getParseMaxDigits()) {
                status[STATUS_INFINITE] = true;
            } else {
                digits.decimalAt = (int) exponent;
            }

            // If none of the text string was recognized. For example, parse "x" with
            // pattern "#0.00" (return index and error index both 0) parse "$" with
            // pattern "$#0.00". (return index 0 and error index 1).
            if (!sawDigit && digitCount == 0) {
                parsePosition.setIndex(oldStart);
                parsePosition.setErrorIndex(oldStart);
                return false;
            }
        }

        // Match padding before suffix
        if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
            position = skipPadding(text, position);
        }

        // Match positive and negative suffixes; prefer longest match.
        if (posMatch >= 0) {
            posMatch = compareAffix(text, position, false, false, posSuffix, type, currency);
        }
        if (negMatch >= 0) {
            negMatch = compareAffix(text, position, true, false, negSuffix, type, currency);
        }
        if (posMatch >= 0 && negMatch >= 0) {
            if (posMatch > negMatch) {
                negMatch = -1;
            } else if (negMatch > posMatch) {
                posMatch = -1;
            }
        }

        // Fail if neither or both
        if ((posMatch >= 0) == (negMatch >= 0)) {
            parsePosition.setErrorIndex(position);
            return false;
        }

        position += (posMatch >= 0 ? posMatch : negMatch);

        // Match padding after suffix
        if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
            position = skipPadding(text, position);
        }

        parsePosition.setIndex(position);

        status[STATUS_POSITIVE] = (posMatch >= 0);

        if (parsePosition.getIndex() == oldStart) {
            parsePosition.setErrorIndex(position);
            return false;
        }
        return true;
    }

    // Utility method used to count the number of codepoints
    private int countCodePoints(String str,int start, int end) {
        int count = 0;
        int index = start;
        while ( index < end ) {
            count++;
            index += UTF16.getCharCount(UTF16.charAt(str, index));
        }
        return count;
    }
    /**
     * Returns a set of characters equivalent to the given desimal separator used for
     * parsing number.  This method may return an empty set.
     */
    private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) {
        UnicodeSet equivSet = UnicodeSet.EMPTY;
        if (strictParse) {
            if (strictDotEquivalents.contains(decimal)) {
                equivSet = strictDotEquivalents;
            } else if (strictCommaEquivalents.contains(decimal)) {
                equivSet = strictCommaEquivalents;
            }
        } else {
            if (dotEquivalents.contains(decimal)) {
                equivSet = dotEquivalents;
            } else if (commaEquivalents.contains(decimal)) {
                equivSet = commaEquivalents;
            }
        }
        return equivSet;
    }

    /**
     * Starting at position, advance past a run of pad characters, if any. Return the
     * index of the first character after position that is not a pad character. Result is
     * >= position.
     */
    private final int skipPadding(String text, int position) {
        while (position < text.length() && text.charAt(position) == pad) {
            ++position;
        }
        return position;
    }

    /**
     * Returns the length matched by the given affix, or -1 if none. Runs of white space
     * in the affix, match runs of white space in the input. Pattern white space and input
     * white space are determined differently; see code.
     *
     * @param text input text
     * @param pos offset into input at which to begin matching
     * @param isNegative
     * @param isPrefix
     * @param affixPat affix pattern used for currency affix comparison
     * @param type compare against currency type, LONG_NAME only or not.
     * @param currency return value for parsed currency, for generic currency parsing
     * mode, or null for normal parsing.  In generic currency parsing mode, any currency
     * is parsed, not just the currency that this formatter is set to.
     * @return length of input that matches, or -1 if match failure
     */
    private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix,
                             String affixPat, int type, Currency[] currency) {
        if (currency != null || currencyChoice != null || currencySignCount > 0) {
            return compareComplexAffix(affixPat, text, pos, type, currency);
        }
        if (isPrefix) {
            return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos);
        } else {
            return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos);
        }

    }

    /**
     * Return the length matched by the given affix, or -1 if none. Runs of white space in
     * the affix, match runs of white space in the input. Pattern white space and input
     * white space are determined differently; see code.
     *
     * @param affix pattern string, taken as a literal
     * @param input input text
     * @param pos offset into input at which to begin matching
     * @return length of input that matches, or -1 if match failure
     */
    private static int compareSimpleAffix(String affix, String input, int pos) {
        int start = pos;
        for (int i = 0; i < affix.length();) {
            int c = UTF16.charAt(affix, i);
            int len = UTF16.getCharCount(c);
            if (PatternProps.isWhiteSpace(c)) {
                // We may have a pattern like: \u200F and input text like: \u200F Note
                // that U+200F and U+0020 are Pattern_White_Space but only U+0020 is
                // UWhiteSpace. So we have to first do a direct match of the run of RULE
                // whitespace in the pattern, then match any extra characters.
                boolean literalMatch = false;
                while (pos < input.length() && UTF16.charAt(input, pos) == c) {
                    literalMatch = true;
                    i += len;
                    pos += len;
                    if (i == affix.length()) {
                        break;
                    }
                    c = UTF16.charAt(affix, i);
                    len = UTF16.getCharCount(c);
                    if (!PatternProps.isWhiteSpace(c)) {
                        break;
                    }
                }

                // Advance over run in affix
                i = skipPatternWhiteSpace(affix, i);

                // Advance over run in input text. Must see at least one white space char
                // in input, unless we've already matched some characters literally.
                int s = pos;
                pos = skipUWhiteSpace(input, pos);
                if (pos == s && !literalMatch) {
                    return -1;
                }
                // If we skip UWhiteSpace in the input text, we need to skip it in the
                // pattern.  Otherwise, the previous lines may have skipped over text
                // (such as U+00A0) that is also in the affix.
                i = skipUWhiteSpace(affix, i);
            } else {
                if (pos < input.length() && UTF16.charAt(input, pos) == c) {
                    i += len;
                    pos += len;
                } else {
                    return -1;
                }
            }
        }
        return pos - start;
    }

    /**
     * Skips over a run of zero or more Pattern_White_Space characters at pos in text.
     */
    private static int skipPatternWhiteSpace(String text, int pos) {
        while (pos < text.length()) {
            int c = UTF16.charAt(text, pos);
            if (!PatternProps.isWhiteSpace(c)) {
                break;
            }
            pos += UTF16.getCharCount(c);
        }
        return pos;
    }

    /**
     * Skips over a run of zero or more isUWhiteSpace() characters at pos in text.
     */
    private static int skipUWhiteSpace(String text, int pos) {
        while (pos < text.length()) {
            int c = UTF16.charAt(text, pos);
            if (!UCharacter.isUWhiteSpace(c)) {
                break;
            }
            pos += UTF16.getCharCount(c);
        }
        return pos;
    }

    /**
     * Returns the length matched by the given affix, or -1 if none.
     *
     * @param affixPat pattern string
     * @param text input text
     * @param pos offset into input at which to begin matching
     * @param type parse against currency type, LONG_NAME only or not.
     * @param currency return value for parsed currency, for generic
     * currency parsing mode, or null for normal parsing.  In generic
     * currency parsing mode, any currency is parsed, not just the
     * currency that this formatter is set to.
     * @return position after the matched text, or -1 if match failure
     */
    private int compareComplexAffix(String affixPat, String text, int pos, int type,
                                    Currency[] currency) {
        int start = pos;
        for (int i = 0; i < affixPat.length() && pos >= 0;) {
            char c = affixPat.charAt(i++);
            if (c == QUOTE) {
                for (;;) {
                    int j = affixPat.indexOf(QUOTE, i);
                    if (j == i) {
                        pos = match(text, pos, QUOTE);
                        i = j + 1;
                        break;
                    } else if (j > i) {
                        pos = match(text, pos, affixPat.substring(i, j));
                        i = j + 1;
                        if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) {
                            pos = match(text, pos, QUOTE);
                            ++i;
                            // loop again
                        } else {
                            break;
                        }
                    } else {
                        // Unterminated quote; should be caught by apply
                        // pattern.
                        throw new RuntimeException();
                    }
                }
                continue;
            }

            switch (c) {
            case CURRENCY_SIGN:
                // since the currency names in choice format is saved the same way as
                // other currency names, do not need to do currency choice parsing here.
                // the general currency parsing parse against all names, including names
                // in choice format.  assert(currency != null || (getCurrency() != null &&
                // currencyChoice != null));
                boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
                if (intl) {
                    ++i;
                }
                boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
                if (plural) {
                    ++i;
                    intl = false;
                }
                // Parse generic currency -- anything for which we have a display name, or
                // any 3-letter ISO code.  Try to parse display name for our locale; first
                // determine our locale.  TODO: use locale in CurrencyPluralInfo
                ULocale uloc = getLocale(ULocale.VALID_LOCALE);
                if (uloc == null) {
                    // applyPattern has been called; use the symbols
                    uloc = symbols.getLocale(ULocale.VALID_LOCALE);
                }
                // Delegate parse of display name => ISO code to Currency
                ParsePosition ppos = new ParsePosition(pos);
                // using Currency.parse to handle mixed style parsing.
                String iso = Currency.parse(uloc, text, type, ppos);

                // If parse succeeds, populate currency[0]
                if (iso != null) {
                    if (currency != null) {
                        currency[0] = Currency.getInstance(iso);
                    } else {
                        // The formatter is currency-style but the client has not requested
                        // the value of the parsed currency. In this case, if that value does
                        // not match the formatter's current value, then the parse fails.
                        Currency effectiveCurr = getEffectiveCurrency();
                        if (iso.compareTo(effectiveCurr.getCurrencyCode()) != 0) {
                            pos = -1;
                            continue;
                        }
                    }
                    pos = ppos.getIndex();
                } else {
                    pos = -1;
                }
                continue;
            case PATTERN_PERCENT:
                c = symbols.getPercent();
                break;
            case PATTERN_PER_MILLE:
                c = symbols.getPerMill();
                break;
            case PATTERN_MINUS:
                c = symbols.getMinusSign();
                break;
            }
            pos = match(text, pos, c);
            if (PatternProps.isWhiteSpace(c)) {
                i = skipPatternWhiteSpace(affixPat, i);
            }
        }

        return pos - start;
    }

    /**
     * Matches a single character at text[pos] and return the index of the next character
     * upon success. Return -1 on failure. If ch is a Pattern_White_Space then match a run of
     * white space in text.
     */
    static final int match(String text, int pos, int ch) {
        if (pos >= text.length()) {
            return -1;
        }
        if (PatternProps.isWhiteSpace(ch)) {
            // Advance over run of white space in input text
            // Must see at least one white space char in input
            int s = pos;
            pos = skipPatternWhiteSpace(text, pos);
            if (pos == s) {
                return -1;
            }
            return pos;
        }
        return (pos >= 0 && UTF16.charAt(text, pos) == ch) ? (pos + UTF16.getCharCount(ch)) : -1;
    }

    /**
     * Matches a string at text[pos] and return the index of the next character upon
     * success. Return -1 on failure. Match a run of white space in str with a run of
     * white space in text.
     */
    static final int match(String text, int pos, String str) {
        for (int i = 0; i < str.length() && pos >= 0;) {
            int ch = UTF16.charAt(str, i);
            i += UTF16.getCharCount(ch);
            pos = match(text, pos, ch);
            if (PatternProps.isWhiteSpace(ch)) {
                i = skipPatternWhiteSpace(str, i);
            }
        }
        return pos;
    }

    /**
     * Returns a copy of the decimal format symbols used by this format.
     *
     * @return desired DecimalFormatSymbols
     * @see DecimalFormatSymbols
     * @stable ICU 2.0
     */
    public DecimalFormatSymbols getDecimalFormatSymbols() {
        try {
            // don't allow multiple references
            return (DecimalFormatSymbols) symbols.clone();
        } catch (Exception foo) {
            return null; // should never happen
        }
    }

    /**
     * Sets the decimal format symbols used by this format. The format uses a copy of the
     * provided symbols.
     *
     * @param newSymbols desired DecimalFormatSymbols
     * @see DecimalFormatSymbols
     * @stable ICU 2.0
     */
    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
        symbols = (DecimalFormatSymbols) newSymbols.clone();
        setCurrencyForSymbols();
        expandAffixes(null);
    }

    /**
     * Update the currency object to match the symbols. This method is used only when the
     * caller has passed in a symbols object that may not be the default object for its
     * locale.
     */
    private void setCurrencyForSymbols() {

        // Bug 4212072 Update the affix strings according to symbols in order to keep the
        // affix strings up to date.  [Richard/GCL]

        // With the introduction of the Currency object, the currency symbols in the DFS
        // object are ignored. For backward compatibility, we check any explicitly set DFS
        // object. If it is a default symbols object for its locale, we change the
        // currency object to one for that locale. If it is custom, we set the currency to
        // null.
        DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getULocale());

        if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())
                && symbols.getInternationalCurrencySymbol()
                       .equals(def.getInternationalCurrencySymbol())) {
            setCurrency(Currency.getInstance(symbols.getULocale()));
        } else {
            setCurrency(null);
        }
    }

    /**
     * Returns the positive prefix.
     *
     * <p>Examples: +123, $123, sFr123
     * @return the prefix
     * @stable ICU 2.0
     */
    public String getPositivePrefix() {
        return positivePrefix;
    }

    /**
     * Sets the positive prefix.
     *
     * <p>Examples: +123, $123, sFr123
     * @param newValue the prefix
     * @stable ICU 2.0
     */
    public void setPositivePrefix(String newValue) {
        positivePrefix = newValue;
        posPrefixPattern = null;
    }

    /**
     * Returns the negative prefix.
     *
     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
     *
     * @return the prefix
     * @stable ICU 2.0
     */
    public String getNegativePrefix() {
        return negativePrefix;
    }

    /**
     * Sets the negative prefix.
     *
     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
     * @param newValue the prefix
     * @stable ICU 2.0
     */
    public void setNegativePrefix(String newValue) {
        negativePrefix = newValue;
        negPrefixPattern = null;
    }

    /**
     * Returns the positive suffix.
     *
     * <p>Example: 123%
     *
     * @return the suffix
     * @stable ICU 2.0
     */
    public String getPositiveSuffix() {
        return positiveSuffix;
    }

    /**
     * Sets the positive suffix.
     *
     * <p>Example: 123%
     * @param newValue the suffix
     * @stable ICU 2.0
     */
    public void setPositiveSuffix(String newValue) {
        positiveSuffix = newValue;
        posSuffixPattern = null;
    }

    /**
     * Returns the negative suffix.
     *
     * <p>Examples: -123%, ($123) (with positive suffixes)
     *
     * @return the suffix
     * @stable ICU 2.0
     */
    public String getNegativeSuffix() {
        return negativeSuffix;
    }

    /**
     * Sets the positive suffix.
     *
     * <p>Examples: 123%
     * @param newValue the suffix
     * @stable ICU 2.0
     */
    public void setNegativeSuffix(String newValue) {
        negativeSuffix = newValue;
        negSuffixPattern = null;
    }

    /**
     * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
     * 1000.
     *
     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
     *
     * @return the multiplier
     * @stable ICU 2.0
     */
    public int getMultiplier() {
        return multiplier;
    }

    /**
     * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
     * 1000.
     *
     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
     *
     * @param newValue the multiplier
     * @stable ICU 2.0
     */
    public void setMultiplier(int newValue) {
        if (newValue == 0) {
            throw new IllegalArgumentException("Bad multiplier: " + newValue);
        }
        multiplier = newValue;
    }

    /**
     * {@icu} Returns the rounding increment.
     *
     * @return A positive rounding increment, or <code>null</code> if rounding is not in
     * effect.
     * @see #setRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 2.0
     */
    public java.math.BigDecimal getRoundingIncrement() {
        if (roundingIncrementICU == null)
            return null;
        return roundingIncrementICU.toBigDecimal();
    }

    /**
     * {@icu} Sets the rounding increment. This method also controls whether rounding is
     * enabled.
     *
     * @param newValue A positive rounding increment, or <code>null</code> or
     * <code>BigDecimal(0.0)</code> to disable rounding.
     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 2.0
     */
    public void setRoundingIncrement(java.math.BigDecimal newValue) {
        if (newValue == null) {
            setRoundingIncrement((BigDecimal) null);
        } else {
            setRoundingIncrement(new BigDecimal(newValue));
        }
    }

    /**
     * {@icu} Sets the rounding increment. This method also controls whether rounding is
     * enabled.
     *
     * @param newValue A positive rounding increment, or <code>null</code> or
     * <code>BigDecimal(0.0)</code> to disable rounding.
     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 3.6
     */
    public void setRoundingIncrement(BigDecimal newValue) {
        int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO);
        if (i < 0) {
            throw new IllegalArgumentException("Illegal rounding increment");
        }
        if (i == 0) {
            setInternalRoundingIncrement(null);
        } else {
            setInternalRoundingIncrement(newValue);
        }
        setRoundingDouble();
    }

    /**
     * {@icu} Sets the rounding increment. This method also controls whether rounding is
     * enabled.
     *
     * @param newValue A positive rounding increment, or 0.0 to disable rounding.
     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see #setRoundingMode
     * @stable ICU 2.0
     */
    public void setRoundingIncrement(double newValue) {
        if (newValue < 0.0) {
            throw new IllegalArgumentException("Illegal rounding increment");
        }
        roundingDouble = newValue;
        roundingDoubleReciprocal = 0.0d;
        if (newValue == 0.0d) {
            setRoundingIncrement((BigDecimal) null);
        } else {
            roundingDouble = newValue;
            if (roundingDouble < 1.0d) {
                double rawRoundedReciprocal = 1.0d / roundingDouble;
                setRoundingDoubleReciprocal(rawRoundedReciprocal);
            }
            setInternalRoundingIncrement(new BigDecimal(newValue));
        }
    }

    private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {
        roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
        if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
            roundingDoubleReciprocal = 0.0d;
        }
    }

    static final double roundingIncrementEpsilon = 0.000000001;

    /**
     * Returns the rounding mode.
     *
     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
     * @see #setRoundingIncrement
     * @see #getRoundingIncrement
     * @see #setRoundingMode
     * @see java.math.BigDecimal
     * @stable ICU 2.0
     */
    @Override
    public int getRoundingMode() {
        return roundingMode;
    }

    /**
     * Sets the rounding mode. This has no effect unless the rounding increment is greater
     * than zero.
     *
     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
     * @see #setRoundingIncrement
     * @see #getRoundingIncrement
     * @see #getRoundingMode
     * @see java.math.BigDecimal
     * @stable ICU 2.0
     */
    @Override
    public void setRoundingMode(int roundingMode) {
        if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
            throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);
        }

        this.roundingMode = roundingMode;

        if (getRoundingIncrement() == null) {
            setRoundingIncrement(Math.pow(10.0, -getMaximumFractionDigits()));
        }
    }

    /**
     * Returns the width to which the output of <code>format()</code> is padded. The width is
     * counted in 16-bit code units.
     *
     * @return the format width, or zero if no padding is in effect
     * @see #setFormatWidth
     * @see #getPadCharacter
     * @see #setPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public int getFormatWidth() {
        return formatWidth;
    }

    /**
     * Sets the width to which the output of <code>format()</code> is
     * padded. The width is counted in 16-bit code units.  This method
     * also controls whether padding is enabled.
     *
     * @param width the width to which to pad the result of
     * <code>format()</code>, or zero to disable padding
     * @exception IllegalArgumentException if <code>width</code> is < 0
     * @see #getFormatWidth
     * @see #getPadCharacter
     * @see #setPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public void setFormatWidth(int width) {
        if (width < 0) {
            throw new IllegalArgumentException("Illegal format width");
        }
        formatWidth = width;
    }

    /**
     * {@icu} Returns the character used to pad to the format width. The default is ' '.
     *
     * @return the pad character
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #setPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public char getPadCharacter() {
        return pad;
    }

    /**
     * {@icu} Sets the character used to pad to the format width. If padding is not
     * enabled, then this will take effect if padding is later enabled.
     *
     * @param padChar the pad character
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #getPadCharacter
     * @see #getPadPosition
     * @see #setPadPosition
     * @stable ICU 2.0
     */
    public void setPadCharacter(char padChar) {
        pad = padChar;
    }

    /**
     * {@icu} Returns the position at which padding will take place. This is the location at
     * which padding will be inserted if the result of <code>format()</code> is shorter
     * than the format width.
     *
     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
     *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
     *         <code>PAD_AFTER_SUFFIX</code>.
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #setPadCharacter
     * @see #getPadCharacter
     * @see #setPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public int getPadPosition() {
        return padPosition;
    }

    /**
     * {@icu} Sets the position at which padding will take place. This is the location at
     * which padding will be inserted if the result of <code>format()</code> is shorter
     * than the format width. This has no effect unless padding is enabled.
     *
     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
     * <code>PAD_AFTER_SUFFIX</code>.
     * @exception IllegalArgumentException if the pad position in unrecognized
     * @see #setFormatWidth
     * @see #getFormatWidth
     * @see #setPadCharacter
     * @see #getPadCharacter
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public void setPadPosition(int padPos) {
        if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
            throw new IllegalArgumentException("Illegal pad position");
        }
        padPosition = padPos;
    }

    /**
     * {@icu} Returns whether or not scientific notation is used.
     *
     * @return true if this object formats and parses scientific notation
     * @see #setScientificNotation
     * @see #getMinimumExponentDigits
     * @see #setMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public boolean isScientificNotation() {
        return useExponentialNotation;
    }

    /**
     * {@icu} Sets whether or not scientific notation is used. When scientific notation is
     * used, the effective maximum number of integer digits is <= 8. If the maximum number
     * of integer digits is set to more than 8, the effective maximum will be 1. This
     * allows this call to generate a 'default' scientific number format without
     * additional changes.
     *
     * @param useScientific true if this object formats and parses scientific notation
     * @see #isScientificNotation
     * @see #getMinimumExponentDigits
     * @see #setMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public void setScientificNotation(boolean useScientific) {
        useExponentialNotation = useScientific;
    }

    /**
     * {@icu} Returns the minimum exponent digits that will be shown.
     *
     * @return the minimum exponent digits that will be shown
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #setMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public byte getMinimumExponentDigits() {
        return minExponentDigits;
    }

    /**
     * {@icu} Sets the minimum exponent digits that will be shown. This has no effect
     * unless scientific notation is in use.
     *
     * @param minExpDig a value >= 1 indicating the fewest exponent
     * digits that will be shown
     * @exception IllegalArgumentException if <code>minExpDig</code> < 1
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #getMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public void setMinimumExponentDigits(byte minExpDig) {
        if (minExpDig < 1) {
            throw new IllegalArgumentException("Exponent digits must be >= 1");
        }
        minExponentDigits = minExpDig;
    }

    /**
     * {@icu} Returns whether the exponent sign is always shown.
     *
     * @return true if the exponent is always prefixed with either the localized minus
     * sign or the localized plus sign, false if only negative exponents are prefixed with
     * the localized minus sign.
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #setMinimumExponentDigits
     * @see #getMinimumExponentDigits
     * @see #setExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public boolean isExponentSignAlwaysShown() {
        return exponentSignAlwaysShown;
    }

    /**
     * {@icu} Sets whether the exponent sign is always shown. This has no effect unless
     * scientific notation is in use.
     *
     * @param expSignAlways true if the exponent is always prefixed with either the
     * localized minus sign or the localized plus sign, false if only negative exponents
     * are prefixed with the localized minus sign.
     * @see #setScientificNotation
     * @see #isScientificNotation
     * @see #setMinimumExponentDigits
     * @see #getMinimumExponentDigits
     * @see #isExponentSignAlwaysShown
     * @stable ICU 2.0
     */
    public void setExponentSignAlwaysShown(boolean expSignAlways) {
        exponentSignAlwaysShown = expSignAlways;
    }

    /**
     * Returns the grouping size. Grouping size is the number of digits between grouping
     * separators in the integer portion of a number. For example, in the number
     * "123,456.78", the grouping size is 3.
     *
     * @see #setGroupingSize
     * @see NumberFormat#isGroupingUsed
     * @see DecimalFormatSymbols#getGroupingSeparator
     * @stable ICU 2.0
     */
    public int getGroupingSize() {
        return groupingSize;
    }

    /**
     * Sets the grouping size. Grouping size is the number of digits between grouping
     * separators in the integer portion of a number. For example, in the number
     * "123,456.78", the grouping size is 3.
     *
     * @see #getGroupingSize
     * @see NumberFormat#setGroupingUsed
     * @see DecimalFormatSymbols#setGroupingSeparator
     * @stable ICU 2.0
     */
    public void setGroupingSize(int newValue) {
        groupingSize = (byte) newValue;
    }

    /**
     * {@icu} Returns the secondary grouping size. In some locales one grouping interval
     * is used for the least significant integer digits (the primary grouping size), and
     * another is used for all others (the secondary grouping size). A formatter
     * supporting a secondary grouping size will return a positive integer unequal to the
     * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
     * the primary grouping size is 4, and the secondary grouping size is 2, then the
     * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
     *
     * @return the secondary grouping size, or a value less than one if there is none
     * @see #setSecondaryGroupingSize
     * @see NumberFormat#isGroupingUsed
     * @see DecimalFormatSymbols#getGroupingSeparator
     * @stable ICU 2.0
     */
    public int getSecondaryGroupingSize() {
        return groupingSize2;
    }

    /**
     * {@icu} Sets the secondary grouping size. If set to a value less than 1, then
     * secondary grouping is turned off, and the primary grouping size is used for all
     * intervals, not just the least significant.
     *
     * @see #getSecondaryGroupingSize
     * @see NumberFormat#setGroupingUsed
     * @see DecimalFormatSymbols#setGroupingSeparator
     * @stable ICU 2.0
     */
    public void setSecondaryGroupingSize(int newValue) {
        groupingSize2 = (byte) newValue;
    }

    /**
     * {@icu} Returns the MathContext used by this format.
     *
     * @return desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public MathContext getMathContextICU() {
        return mathContext;
    }

    /**
     * {@icu} Returns the MathContext used by this format.
     *
     * @return desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public java.math.MathContext getMathContext() {
        try {
            // don't allow multiple references
            return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(),
                    java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
        } catch (Exception foo) {
            return null; // should never happen
        }
    }

    /**
     * {@icu} Sets the MathContext used by this format.
     *
     * @param newValue desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public void setMathContextICU(MathContext newValue) {
        mathContext = newValue;
    }

    /**
     * {@icu} Sets the MathContext used by this format.
     *
     * @param newValue desired MathContext
     * @see #getMathContext
     * @stable ICU 4.2
     */
    public void setMathContext(java.math.MathContext newValue) {
        mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false,
                                      (newValue.getRoundingMode()).ordinal());
    }

    /**
     * Returns the behavior of the decimal separator with integers. (The decimal
     * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 ->
     * 12345.; OFF: 12345 -> 12345
     *
     * @stable ICU 2.0
     */
    public boolean isDecimalSeparatorAlwaysShown() {
        return decimalSeparatorAlwaysShown;
    }

    /**
     * Sets the behavior of the decimal separator with integers. (The decimal separator
     * will always appear with decimals.)
     *
     * <p>This only affects formatting, and only where there might be no digits after the
     * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This
     * is independent of parsing. If you want parsing to stop at the decimal point, use
     * setParseIntegerOnly.
     *
     * <p>
     * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
     *
     * @stable ICU 2.0
     */
    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
        decimalSeparatorAlwaysShown = newValue;
    }

    /**
     * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might
     * return null if the decimal format is not a plural type currency decimal
     * format. Plural type currency decimal format means either the pattern in the decimal
     * format contains 3 currency signs, or the decimal format is initialized with
     * PLURALCURRENCYSTYLE.
     *
     * @return desired CurrencyPluralInfo
     * @see CurrencyPluralInfo
     * @stable ICU 4.2
     */
    public CurrencyPluralInfo getCurrencyPluralInfo() {
        try {
            // don't allow multiple references
            return currencyPluralInfo == null ? null :
                (CurrencyPluralInfo) currencyPluralInfo.clone();
        } catch (Exception foo) {
            return null; // should never happen
        }
    }

    /**
     * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of
     * the provided information.
     *
     * @param newInfo desired CurrencyPluralInfo
     * @see CurrencyPluralInfo
     * @stable ICU 4.2
     */
    public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
        currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
        isReadyForParsing = false;
    }

    /**
     * Overrides clone.
     * @stable ICU 2.0
     */
    @Override
    public Object clone() {
        try {
            DecimalFormat other = (DecimalFormat) super.clone();
            other.symbols = (DecimalFormatSymbols) symbols.clone();
            other.digitList = new DigitList(); // fix for JB#5358
            if (currencyPluralInfo != null) {
                other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
            }
            other.attributes = new ArrayList<FieldPosition>(); // #9240

            // TODO: We need to figure out whether we share a single copy of DigitList by
            // multiple cloned copies.  format/subformat are designed to use a single
            // instance, but parse/subparse implementation is not.
            return other;
        } catch (Exception e) {
            throw new IllegalStateException();
        }
    }

    /**
     * Overrides equals.
     * @stable ICU 2.0
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null)
            return false;
        if (!super.equals(obj))
            return false; // super does class check

        DecimalFormat other = (DecimalFormat) obj;
        // Add the comparison of the four new added fields ,they are posPrefixPattern,
        // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL]
        // following are added to accomodate changes for currency plural format.
        return currencySignCount == other.currencySignCount
                && (style != NumberFormat.PLURALCURRENCYSTYLE ||
                    equals(posPrefixPattern, other.posPrefixPattern)
                && equals(posSuffixPattern, other.posSuffixPattern)
                && equals(negPrefixPattern, other.negPrefixPattern)
                && equals(negSuffixPattern, other.negSuffixPattern))
                && multiplier == other.multiplier
                && groupingSize == other.groupingSize
                && groupingSize2 == other.groupingSize2
                && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
                && useExponentialNotation == other.useExponentialNotation
                && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
                && useSignificantDigits == other.useSignificantDigits
                && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
                        && maxSignificantDigits == other.maxSignificantDigits)
                && symbols.equals(other.symbols)
                && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);
    }

    // method to unquote the strings and compare
    private boolean equals(String pat1, String pat2) {
        if (pat1 == null || pat2 == null) {
            return (pat1 == null && pat2 == null);
        }
        // fast path
        if (pat1.equals(pat2)) {
            return true;
        }
        return unquote(pat1).equals(unquote(pat2));
    }

    private String unquote(String pat) {
        StringBuilder buf = new StringBuilder(pat.length());
        int i = 0;
        while (i < pat.length()) {
            char ch = pat.charAt(i++);
            if (ch != QUOTE) {
                buf.append(ch);
            }
        }
        return buf.toString();
    }

    // protected void handleToString(StringBuffer buf) {
    // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
    // buf.append("positivePrefix: '" + positivePrefix + "'\n");
    // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
    // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
    // buf.append("negPrefixPattern: '" +
    //     com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
    // buf.append("negativePrefix: '" +
    //     com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
    // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
    // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
    // buf.append("multiplier: '" + multiplier + "'\n");
    // buf.append("groupingSize: '" + groupingSize + "'\n");
    // buf.append("groupingSize2: '" + groupingSize2 + "'\n");
    // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
    // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
    // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
    // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
    // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
    // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
    // buf.append("symbols: '" + symbols + "'");
    // }

    /**
     * Overrides hashCode.
     * @stable ICU 2.0
     */
    @Override
    public int hashCode() {
        return super.hashCode() * 37 + positivePrefix.hashCode();
        // just enough fields for a reasonable distribution
    }

    /**
     * Synthesizes a pattern string that represents the current state of this Format
     * object.
     *
     * @see #applyPattern
     * @stable ICU 2.0
     */
    public String toPattern() {
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            // the prefix or suffix pattern might not be defined yet, so they can not be
            // synthesized, instead, get them directly.  but it might not be the actual
            // pattern used in formatting.  the actual pattern used in formatting depends
            // on the formatted number's plural count.
            return formatPattern;
        }
        return toPattern(false);
    }

    /**
     * Synthesizes a localized pattern string that represents the current state of this
     * Format object.
     *
     * @see #applyPattern
     * @stable ICU 2.0
     */
    public String toLocalizedPattern() {
        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
            return formatPattern;
        }
        return toPattern(true);
    }

    /**
     * Expands the affix pattern strings into the expanded affix strings. If any affix
     * pattern string is null, do not expand it. This method should be called any time the
     * symbols or the affix patterns change in order to keep the expanded affix strings up
     * to date. This method also will be called before formatting if format currency
     * plural names, since the plural name is not a static one, it is based on the
     * currency plural count, the affix will be known only after the currency plural count
     * is know. In which case, the parameter 'pluralCount' will be a non-null currency
     * plural count. In all other cases, the 'pluralCount' is null, which means it is not
     * needed.
     */
    // Bug 4212072 [Richard/GCL]
    private void expandAffixes(String pluralCount) {
        // expandAffix() will set currencyChoice to a non-null value if
        // appropriate AND if it is null.
        currencyChoice = null;

        // Reuse one StringBuffer for better performance
        StringBuffer buffer = new StringBuffer();
        if (posPrefixPattern != null) {
            expandAffix(posPrefixPattern, pluralCount, buffer, false);
            positivePrefix = buffer.toString();
        }
        if (posSuffixPattern != null) {
            expandAffix(posSuffixPattern, pluralCount, buffer, false);
            positiveSuffix = buffer.toString();
        }
        if (negPrefixPattern != null) {
            expandAffix(negPrefixPattern, pluralCount, buffer, false);
            negativePrefix = buffer.toString();
        }
        if (negSuffixPattern != null) {
            expandAffix(negSuffixPattern, pluralCount, buffer, false);
            negativeSuffix = buffer.toString();
        }
    }

    /**
     * Expands an affix pattern into an affix string. All characters in the pattern are
     * literal unless bracketed by QUOTEs. The following characters outside QUOTE are
     * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
     * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international
     * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural
     * long names, such as "US Dollars". Any other character outside QUOTE represents
     * itself. Quoted text must be well-formed.
     *
     * This method is used in two distinct ways. First, it is used to expand the stored
     * affix patterns into actual affixes. For this usage, doFormat must be false. Second,
     * it is used to expand the stored affix patterns given a specific number (doFormat ==
     * true), for those rare cases in which a currency format references a ChoiceFormat
     * (e.g., en_IN display name for INR). The number itself is taken from digitList.
     *
     * When used in the first way, this method has a side effect: It sets currencyChoice
     * to a ChoiceFormat object, if the currency's display name in this locale is a
     * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to
     * start with.
     *
     * @param pattern the non-null, possibly empty pattern
     * @param pluralCount the plural count. It is only used for currency plural format. In
     * which case, it is the plural count of the currency amount. For example, in en_US,
     * it is the singular "one", or the plural "other". For all other cases, it is null,
     * and is not being used.
     * @param buffer a scratch StringBuffer; its contents will be lost
     * @param doFormat if false, then the pattern will be expanded, and if a currency
     * symbol is encountered that expands to a ChoiceFormat, the currencyChoice member
     * variable will be initialized if it is null. If doFormat is true, then it is assumed
     * that the currencyChoice has been created, and it will be used to format the value
     * in digitList.
     */
    // Bug 4212072 [Richard/GCL]
    private void expandAffix(String pattern, String pluralCount, StringBuffer buffer,
                             boolean doFormat) {
        buffer.setLength(0);
        for (int i = 0; i < pattern.length();) {
            char c = pattern.charAt(i++);
            if (c == QUOTE) {
                for (;;) {
                    int j = pattern.indexOf(QUOTE, i);
                    if (j == i) {
                        buffer.append(QUOTE);
                        i = j + 1;
                        break;
                    } else if (j > i) {
                        buffer.append(pattern.substring(i, j));
                        i = j + 1;
                        if (i < pattern.length() && pattern.charAt(i) == QUOTE) {
                            buffer.append(QUOTE);
                            ++i;
                            // loop again
                        } else {
                            break;
                        }
                    } else {
                        // Unterminated quote; should be caught by apply
                        // pattern.
                        throw new RuntimeException();
                    }
                }
                continue;
            }

            switch (c) {
            case CURRENCY_SIGN:
                // As of ICU 2.2 we use the currency object, and ignore the currency
                // symbols in the DFS, unless we have a null currency object. This occurs
                // if resurrecting a pre-2.2 object or if the user sets a custom DFS.
                boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN;
                boolean plural = false;
                if (intl) {
                    ++i;
                    if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) {
                        plural = true;
                        intl = false;
                        ++i;
                    }
                }
                String s = null;
                Currency currency = getCurrency();
                if (currency != null) {
                    // plural name is only needed when pluralCount != null, which means
                    // when formatting currency plural names.  For other cases,
                    // pluralCount == null, and plural names are not needed.
                    if (plural && pluralCount != null) {
                        boolean isChoiceFormat[] = new boolean[1];
                        s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,
                                             pluralCount, isChoiceFormat);
                    } else if (!intl) {
                        boolean isChoiceFormat[] = new boolean[1];
                        s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME,
                                             isChoiceFormat);
                        if (isChoiceFormat[0]) {
                            // Two modes here: If doFormat is false, we set up
                            // currencyChoice. If doFormat is true, we use the previously
                            // created currencyChoice to format the value in digitList.
                            if (!doFormat) {
                                // If the currency is handled by a ChoiceFormat, then
                                // we're not going to use the expanded
                                // patterns. Instantiate the ChoiceFormat and return.
                                if (currencyChoice == null) {
                                    currencyChoice = new ChoiceFormat(s);
                                }
                                // We could almost return null or "" here, since the
                                // expanded affixes are almost not used at all in this
                                // situation. However, one method -- toPattern() -- still
                                // does use the expanded affixes, in order to set up a
                                // padding pattern. We use the CURRENCY_SIGN as a
                                // placeholder.
                                s = String.valueOf(CURRENCY_SIGN);
                            } else {
                                FieldPosition pos = new FieldPosition(0); // ignored
                                currencyChoice.format(digitList.getDouble(), buffer, pos);
                                continue;
                            }
                        }
                    } else {
                        s = currency.getCurrencyCode();
                    }
                } else {
                    s = intl ? symbols.getInternationalCurrencySymbol() :
                        symbols.getCurrencySymbol();
                }
                buffer.append(s);
                continue;
            case PATTERN_PERCENT:
                c = symbols.getPercent();
                break;
            case PATTERN_PER_MILLE:
                c = symbols.getPerMill();
                break;
            case PATTERN_MINUS:
                c = symbols.getMinusSign();
                break;
            }
            buffer.append(c);
        }
    }

    /**
     * Append an affix to the given StringBuffer.
     *
     * @param buf
     *            buffer to append to
     * @param isNegative
     * @param isPrefix
     */
    private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,
                            boolean parseAttr) {
        if (currencyChoice != null) {
            String affixPat = null;
            if (isPrefix) {
                affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
            } else {
                affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
            }
            StringBuffer affixBuf = new StringBuffer();
            expandAffix(affixPat, null, affixBuf, true);
            buf.append(affixBuf);
            return affixBuf.length();
        }

        String affix = null;
        if (isPrefix) {
            affix = isNegative ? negativePrefix : positivePrefix;
        } else {
            affix = isNegative ? negativeSuffix : positiveSuffix;
        }
        // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
        if (parseAttr) {
            int offset = affix.indexOf(symbols.getCurrencySymbol());
            if (-1 == offset) {
                offset = affix.indexOf(symbols.getPercent());
                if (-1 == offset) {
                    offset = 0;
                }
            }
            formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length());
        }
        buf.append(affix);
        return affix.length();
    }

    /**
     * [Spark/CDL] This is a newly added method, used to add attributes for prefix and
     * suffix.
     */
    private void formatAffix2Attribute(String affix, int begin, int end) {
        // [Spark/CDL] It is the invoker's responsibility to ensure that, before the
        // invocation of this method, attributes is not null.  if( attributes == null )
        // return;
        if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
            addAttribute(Field.CURRENCY, begin, end);
        } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
            addAttribute(Field.SIGN, begin, end);
        } else if (affix.indexOf(symbols.getPercent()) > -1) {
            addAttribute(Field.PERCENT, begin, end);
        } else if (affix.indexOf(symbols.getPerMill()) > -1) {
            addAttribute(Field.PERMILLE, begin, end);
        }
    }

    /**
     * [Spark/CDL] Use this method to add attribute.
     */
    private void addAttribute(Field field, int begin, int end) {
        FieldPosition pos = new FieldPosition(field);
        pos.setBeginIndex(begin);
        pos.setEndIndex(end);
        attributes.add(pos);
    }

    /**
     * Formats the object to an attributed string, and return the corresponding iterator.
     *
     * @stable ICU 3.6
     */
    @Override
    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
      return formatToCharacterIterator(obj, NULL_UNIT);
    }

    AttributedCharacterIterator formatToCharacterIterator(Object obj, Unit unit) {
        if (!(obj instanceof Number))
            throw new IllegalArgumentException();
        Number number = (Number) obj;
        StringBuffer text = new StringBuffer();
        unit.writePrefix(text);
        attributes.clear();
        if (obj instanceof BigInteger) {
            format((BigInteger) number, text, new FieldPosition(0), true);
        } else if (obj instanceof java.math.BigDecimal) {
            format((java.math.BigDecimal) number, text, new FieldPosition(0)
                          , true);
        } else if (obj instanceof Double) {
            format(number.doubleValue(), text, new FieldPosition(0), true);
        } else if (obj instanceof Integer || obj instanceof Long) {
            format(number.longValue(), text, new FieldPosition(0), true);
        } else {
            throw new IllegalArgumentException();
        }
        unit.writeSuffix(text);
        AttributedString as = new AttributedString(text.toString());

        // add NumberFormat field attributes to the AttributedString
        for (int i = 0; i < attributes.size(); i++) {
            FieldPosition pos = attributes.get(i);
            Format.Field attribute = pos.getFieldAttribute();
            as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());
        }

        // return the CharacterIterator from AttributedString
        return as.getIterator();
    }

    /**
     * Appends an affix pattern to the given StringBuffer. Localize unquoted specials.
     */
    private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,
                                    boolean localized) {
        String affixPat = null;
        if (isPrefix) {
            affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
        } else {
            affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
        }

        // When there is a null affix pattern, we use the affix itself.
        if (affixPat == null) {
            String affix = null;
            if (isPrefix) {
                affix = isNegative ? negativePrefix : positivePrefix;
            } else {
                affix = isNegative ? negativeSuffix : positiveSuffix;
            }
            // Do this crudely for now: Wrap everything in quotes.
            buffer.append(QUOTE);
            for (int i = 0; i < affix.length(); ++i) {
                char ch = affix.charAt(i);
                if (ch == QUOTE) {
                    buffer.append(ch);
                }
                buffer.append(ch);
            }
            buffer.append(QUOTE);
            return;
        }

        if (!localized) {
            buffer.append(affixPat);
        } else {
            int i, j;
            for (i = 0; i < affixPat.length(); ++i) {
                char ch = affixPat.charAt(i);
                switch (ch) {
                case QUOTE:
                    j = affixPat.indexOf(QUOTE, i + 1);
                    if (j < 0) {
                        throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
                    }
                    buffer.append(affixPat.substring(i, j + 1));
                    i = j;
                    continue;
                case PATTERN_PER_MILLE:
                    ch = symbols.getPerMill();
                    break;
                case PATTERN_PERCENT:
                    ch = symbols.getPercent();
                    break;
                case PATTERN_MINUS:
                    ch = symbols.getMinusSign();
                    break;
                }
                // check if char is same as any other symbol
                if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) {
                    buffer.append(QUOTE);
                    buffer.append(ch);
                    buffer.append(QUOTE);
                } else {
                    buffer.append(ch);
                }
            }
        }
    }

    /**
     * Does the real work of generating a pattern.
     */
    private String toPattern(boolean localized) {
        StringBuffer result = new StringBuffer();
        char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
        char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
        char sigDigit = 0;
        boolean useSigDig = areSignificantDigitsUsed();
        if (useSigDig) {
            sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
        }
        char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR;
        int i;
        int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
        String roundingDigits = null;
        int padPos = (formatWidth > 0) ? padPosition : -1;
        String padSpec = (formatWidth > 0)
            ? new StringBuffer(2).append(localized
                                         ? symbols.getPadEscape()
                                         : PATTERN_PAD_ESCAPE).append(pad).toString()
            : null;
        if (roundingIncrementICU != null) {
            i = roundingIncrementICU.scale();
            roundingDigits = roundingIncrementICU.movePointRight(i).toString();
            roundingDecimalPos = roundingDigits.length() - i;
        }
        for (int part = 0; part < 2; ++part) {
            // variable not used int partStart = result.length();
            if (padPos == PAD_BEFORE_PREFIX) {
                result.append(padSpec);
            }

            // Use original symbols read from resources in pattern eg. use "\u00A4"
            // instead of "$" in Locale.US [Richard/GCL]
            appendAffixPattern(result, part != 0, true, localized);
            if (padPos == PAD_AFTER_PREFIX) {
                result.append(padSpec);
            }
            int sub0Start = result.length();
            int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
            if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
                g += groupingSize2;
            }
            int maxDig = 0, minDig = 0, maxSigDig = 0;
            if (useSigDig) {
                minDig = getMinimumSignificantDigits();
                maxDig = maxSigDig = getMaximumSignificantDigits();
            } else {
                minDig = getMinimumIntegerDigits();
                maxDig = getMaximumIntegerDigits();
            }
            if (useExponentialNotation) {
                if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
                    maxDig = 1;
                }
            } else if (useSigDig) {
                maxDig = Math.max(maxDig, g + 1);
            } else {
                maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1;
            }
            for (i = maxDig; i > 0; --i) {
                if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) {
                    result.append(group);
                }
                if (useSigDig) {
                    // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos,
                    // count from the right) Use # if pos > maxSigDig or 1 <= pos <=
                    // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <=
                    // maxSigDig
                    result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
                } else {
                    if (roundingDigits != null) {
                        int pos = roundingDecimalPos - i;
                        if (pos >= 0 && pos < roundingDigits.length()) {
                            result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
                            continue;
                        }
                    }
                    result.append(i <= minDig ? zero : digit);
                }
            }
            if (!useSigDig) {
                if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
                    result.append(localized ? symbols.getDecimalSeparator() :
                                  PATTERN_DECIMAL_SEPARATOR);
                }
                int pos = roundingDecimalPos;
                for (i = 0; i < getMaximumFractionDigits(); ++i) {
                    if (roundingDigits != null && pos < roundingDigits.length()) {
                        result.append(pos < 0 ? zero :
                                      (char) (roundingDigits.charAt(pos) - '0' + zero));
                        ++pos;
                        continue;
                    }
                    result.append(i < getMinimumFractionDigits() ? zero : digit);
                }
            }
            if (useExponentialNotation) {
                if (localized) {
                    result.append(symbols.getExponentSeparator());
                } else {
                    result.append(PATTERN_EXPONENT);
                }
                if (exponentSignAlwaysShown) {
                    result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN);
                }
                for (i = 0; i < minExponentDigits; ++i) {
                    result.append(zero);
                }
            }
            if (padSpec != null && !useExponentialNotation) {
                int add = formatWidth
                        - result.length()
                        + sub0Start
                        - ((part == 0)
                           ? positivePrefix.length() + positiveSuffix.length()
                           : negativePrefix.length() + negativeSuffix.length());
                while (add > 0) {
                    result.insert(sub0Start, digit);
                    ++maxDig;
                    --add;
                    // Only add a grouping separator if we have at least 2 additional
                    // characters to be added, so we don't end up with ",###".
                    if (add > 1 && isGroupingPosition(maxDig)) {
                        result.insert(sub0Start, group);
                        --add;
                    }
                }
            }
            if (padPos == PAD_BEFORE_SUFFIX) {
                result.append(padSpec);
            }
            // Use original symbols read from resources in pattern eg. use "\u00A4"
            // instead of "$" in Locale.US [Richard/GCL]
            appendAffixPattern(result, part != 0, false, localized);
            if (padPos == PAD_AFTER_SUFFIX) {
                result.append(padSpec);
            }
            if (part == 0) {
                if (negativeSuffix.equals(positiveSuffix) &&
                    negativePrefix.equals(PATTERN_MINUS + positivePrefix)) {
                    break;
                } else {
                    result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);
                }
            }
        }
        return result.toString();
    }

    /**
     * Applies the given pattern to this Format object. A pattern is a short-hand
     * specification for the various formatting properties. These properties can also be
     * changed individually through the various setter methods.
     *
     * <p>There is no limit to integer digits are set by this routine, since that is the
     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
     * negative numbers, use a second pattern, separated by a semicolon
     *
     * <p>Example "#,#00.0#" -> 1,234.56
     *
     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
     * fraction digits.
     *
     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
     *
     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
     * presumed to be set in the positive pattern.
     *
     * @stable ICU 2.0
     */
    public void applyPattern(String pattern) {
        applyPattern(pattern, false);
    }

    /**
     * Applies the given pattern to this Format object. The pattern is assumed to be in a
     * localized notation. A pattern is a short-hand specification for the various
     * formatting properties. These properties can also be changed individually through
     * the various setter methods.
     *
     * <p>There is no limit to integer digits are set by this routine, since that is the
     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
     * negative numbers, use a second pattern, separated by a semicolon
     *
     * <p>Example "#,#00.0#" -> 1,234.56
     *
     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
     * fraction digits.
     *
     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
     *
     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
     * presumed to be set in the positive pattern.
     *
     * @stable ICU 2.0
     */
    public void applyLocalizedPattern(String pattern) {
        applyPattern(pattern, true);
    }

    /**
     * Does the real work of applying a pattern.
     */
    private void applyPattern(String pattern, boolean localized) {
        applyPatternWithoutExpandAffix(pattern, localized);
        expandAffixAdjustWidth(null);
    }

    private void expandAffixAdjustWidth(String pluralCount) {
        // Bug 4212072 Update the affix strings according to symbols in order to keep the
        // affix strings up to date.  [Richard/GCL]
        expandAffixes(pluralCount);

        // Now that we have the actual prefix and suffix, fix up formatWidth
        if (formatWidth > 0) {
            formatWidth += positivePrefix.length() + positiveSuffix.length();
        }
    }

    private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
        char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
        char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
        char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
        char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
        char percent = PATTERN_PERCENT;
        char perMill = PATTERN_PER_MILLE;
        char digit = PATTERN_DIGIT; // '#'
        char separator = PATTERN_SEPARATOR;
        String exponent = String.valueOf(PATTERN_EXPONENT);
        char plus = PATTERN_PLUS_SIGN;
        char padEscape = PATTERN_PAD_ESCAPE;
        char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL]
        if (localized) {
            zeroDigit = symbols.getZeroDigit();
            sigDigit = symbols.getSignificantDigit();
            groupingSeparator = symbols.getGroupingSeparator();
            decimalSeparator = symbols.getDecimalSeparator();
            percent = symbols.getPercent();
            perMill = symbols.getPerMill();
            digit = symbols.getDigit();
            separator = symbols.getPatternSeparator();
            exponent = symbols.getExponentSeparator();
            plus = symbols.getPlusSign();
            padEscape = symbols.getPadEscape();
            minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL]
        }
        char nineDigit = (char) (zeroDigit + 9);

        boolean gotNegative = false;

        int pos = 0;
        // Part 0 is the positive pattern. Part 1, if present, is the negative
        // pattern.
        for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
            // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,
            // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and
            // suffix, and consists of pattern characters. In the prefix and suffix,
            // percent, permille, and currency symbols are recognized and translated.
            int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;

            // It's important that we don't change any fields of this object
            // prematurely. We set the following variables for the multiplier, grouping,
            // etc., and then only change the actual object fields if everything parses
            // correctly. This also lets us register the data from part 0 and ignore the
            // part 1, except for the prefix and suffix.
            StringBuilder prefix = new StringBuilder();
            StringBuilder suffix = new StringBuilder();
            int decimalPos = -1;
            int multpl = 1;
            int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
            byte groupingCount = -1;
            byte groupingCount2 = -1;
            int padPos = -1;
            char padChar = 0;
            int incrementPos = -1;
            long incrementVal = 0;
            byte expDigits = -1;
            boolean expSignAlways = false;
            int currencySignCnt = 0;

            // The affix is either the prefix or the suffix.
            StringBuilder affix = prefix;

            int start = pos;

            PARTLOOP: for (; pos < pattern.length(); ++pos) {
                char ch = pattern.charAt(pos);
                switch (subpart) {
                case 0: // Pattern proper subpart (between prefix & suffix)
                    // Process the digits, decimal, and grouping characters. We record
                    // five pieces of information. We expect the digits to occur in the
                    // pattern ####00.00####, and we record the number of left digits,
                    // zero (central) digits, and right digits. The position of the last
                    // grouping character is recorded (should be somewhere within the
                    // first two blocks of characters), as is the position of the decimal
                    // point, if any (should be in the zero digits). If there is no
                    // decimal point, then there should be no right digits.
                    if (ch == digit) {
                        if (zeroDigitCount > 0 || sigDigitCount > 0) {
                            ++digitRightCount;
                        } else {
                            ++digitLeftCount;
                        }
                        if (groupingCount >= 0 && decimalPos < 0) {
                            ++groupingCount;
                        }
                    } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
                        if (digitRightCount > 0) {
                            patternError("Unexpected '" + ch + '\'', pattern);
                        }
                        if (ch == sigDigit) {
                            ++sigDigitCount;
                        } else {
                            ++zeroDigitCount;
                            if (ch != zeroDigit) {
                                int p = digitLeftCount + zeroDigitCount + digitRightCount;
                                if (incrementPos >= 0) {
                                    while (incrementPos < p) {
                                        incrementVal *= 10;
                                        ++incrementPos;
                                    }
                                } else {
                                    incrementPos = p;
                                }
                                incrementVal += ch - zeroDigit;
                            }
                        }
                        if (groupingCount >= 0 && decimalPos < 0) {
                            ++groupingCount;
                        }
                    } else if (ch == groupingSeparator) {
                        // Bug 4212072 process the Localized pattern like
                        // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator
                        // == QUOTE) [Richard/GCL]
                        if (ch == QUOTE && (pos + 1) < pattern.length()) {
                            char after = pattern.charAt(pos + 1);
                            if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
                                // A quote outside quotes indicates either the opening
                                // quote or two quotes, which is a quote literal. That is,
                                // we have the first quote in 'do' or o''clock.
                                if (after == QUOTE) {
                                    ++pos;
                                    // Fall through to append(ch)
                                } else {
                                    if (groupingCount < 0) {
                                        subpart = 3; // quoted prefix subpart
                                    } else {
                                        // Transition to suffix subpart
                                        subpart = 2; // suffix subpart
                                        affix = suffix;
                                        sub0Limit = pos--;
                                    }
                                    continue;
                                }
                            }
                        }

                        if (decimalPos >= 0) {
                            patternError("Grouping separator after decimal", pattern);
                        }
                        groupingCount2 = groupingCount;
                        groupingCount = 0;
                    } else if (ch == decimalSeparator) {
                        if (decimalPos >= 0) {
                            patternError("Multiple decimal separators", pattern);
                        }
                        // Intentionally incorporate the digitRightCount, even though it
                        // is illegal for this to be > 0 at this point. We check pattern
                        // syntax below.
                        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
                    } else {
                        if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
                            if (expDigits >= 0) {
                                patternError("Multiple exponential symbols", pattern);
                            }
                            if (groupingCount >= 0) {
                                patternError("Grouping separator in exponential", pattern);
                            }
                            pos += exponent.length();
                            // Check for positive prefix
                            if (pos < pattern.length() && pattern.charAt(pos) == plus) {
                                expSignAlways = true;
                                ++pos;
                            }
                            // Use lookahead to parse out the exponential part of the
                            // pattern, then jump into suffix subpart.
                            expDigits = 0;
                            while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {
                                ++expDigits;
                                ++pos;
                            }

                            // 1. Require at least one mantissa pattern digit
                            // 2. Disallow "#+ @" in mantissa
                            // 3. Require at least one exponent pattern digit
                            if (((digitLeftCount + zeroDigitCount) < 1 &&
                                 (sigDigitCount + digitRightCount) < 1)
                                || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {
                                patternError("Malformed exponential", pattern);
                            }
                        }
                        // Transition to suffix subpart
                        subpart = 2; // suffix subpart
                        affix = suffix;
                        sub0Limit = pos--; // backup: for() will increment
                        continue;
                    }
                    break;
                case 1: // Prefix subpart
                case 2: // Suffix subpart
                    // Process the prefix / suffix characters Process unquoted characters
                    // seen in prefix or suffix subpart.

                    // Several syntax characters implicitly begins the next subpart if we
                    // are in the prefix; otherwise they are illegal if unquoted.
                    if (ch == digit || ch == groupingSeparator || ch == decimalSeparator
                            || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
                        // Any of these characters implicitly begins the
                        // next subpart if we are in the prefix
                        if (subpart == 1) { // prefix subpart
                            subpart = 0; // pattern proper subpart
                            sub0Start = pos--; // Reprocess this character
                            continue;
                        } else if (ch == QUOTE) {
                            // Bug 4212072 process the Localized pattern like
                            // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH",
                            // groupingSeparator == QUOTE) [Richard/GCL]

                            // A quote outside quotes indicates either the opening quote
                            // or two quotes, which is a quote literal. That is, we have
                            // the first quote in 'do' or o''clock.
                            if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                                ++pos;
                                affix.append(ch);
                            } else {
                                subpart += 2; // open quote
                            }
                            continue;
                        }
                        patternError("Unquoted special character '" + ch + '\'', pattern);
                    } else if (ch == CURRENCY_SIGN) {
                        // Use lookahead to determine if the currency sign is
                        // doubled or not.
                        boolean doubled = (pos + 1) < pattern.length() &&
                            pattern.charAt(pos + 1) == CURRENCY_SIGN;

                        // Bug 4212072 To meet the need of expandAffix(String,
                        // StirngBuffer) [Richard/GCL]
                        if (doubled) {
                            ++pos; // Skip over the doubled character
                            affix.append(ch); // append two: one here, one below
                            if ((pos + 1) < pattern.length() &&
                                pattern.charAt(pos + 1) == CURRENCY_SIGN) {
                                ++pos; // Skip over the tripled character
                                affix.append(ch); // append again
                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
                            } else {
                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
                            }
                        } else {
                            currencySignCnt = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
                        }
                        // Fall through to append(ch)
                    } else if (ch == QUOTE) {
                        // A quote outside quotes indicates either the opening quote or
                        // two quotes, which is a quote literal. That is, we have the
                        // first quote in 'do' or o''clock.
                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                            ++pos;
                            affix.append(ch); // append two: one here, one below
                        } else {
                            subpart += 2; // open quote
                        }
                        // Fall through to append(ch)
                    } else if (ch == separator) {
                        // Don't allow separators in the prefix, and don't allow
                        // separators in the second pattern (part == 1).
                        if (subpart == 1 || part == 1) {
                            patternError("Unquoted special character '" + ch + '\'', pattern);
                        }
                        sub2Limit = pos++;
                        break PARTLOOP; // Go to next part
                    } else if (ch == percent || ch == perMill) {
                        // Next handle characters which are appended directly.
                        if (multpl != 1) {
                            patternError("Too many percent/permille characters", pattern);
                        }
                        multpl = (ch == percent) ? 100 : 1000;
                        // Convert to non-localized pattern
                        ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
                        // Fall through to append(ch)
                    } else if (ch == minus) {
                        // Convert to non-localized pattern
                        ch = PATTERN_MINUS;
                        // Fall through to append(ch)
                    } else if (ch == padEscape) {
                        if (padPos >= 0) {
                            patternError("Multiple pad specifiers", pattern);
                        }
                        if ((pos + 1) == pattern.length()) {
                            patternError("Invalid pad specifier", pattern);
                        }
                        padPos = pos++; // Advance past pad char
                        padChar = pattern.charAt(pos);
                        continue;
                    }
                    affix.append(ch);
                    break;
                case 3: // Prefix subpart, in quote
                case 4: // Suffix subpart, in quote
                    // A quote within quotes indicates either the closing quote or two
                    // quotes, which is a quote literal. That is, we have the second quote
                    // in 'do' or 'don''t'.
                    if (ch == QUOTE) {
                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
                            ++pos;
                            affix.append(ch);
                        } else {
                            subpart -= 2; // close quote
                        }
                        // Fall through to append(ch)
                    }
                    // NOTE: In ICU 2.2 there was code here to parse quoted percent and
                    // permille characters _within quotes_ and give them special
                    // meaning. This is incorrect, since quoted characters are literals
                    // without special meaning.
                    affix.append(ch);
                    break;
                }
            }

            if (subpart == 3 || subpart == 4) {
                patternError("Unterminated quote", pattern);
            }

            if (sub0Limit == 0) {
                sub0Limit = pattern.length();
            }

            if (sub2Limit == 0) {
                sub2Limit = pattern.length();
            }

            // Handle patterns with no '0' pattern character. These patterns are legal,
            // but must be recodified to make sense. "##.###" -> "#0.###". ".###" ->
            // ".0##".
            //
            // We allow patterns of the form "####" to produce a zeroDigitCount of zero
            // (got that?); although this seems like it might make it possible for
            // format() to produce empty strings, format() checks for this condition and
            // outputs a zero digit in this situation. Having a zeroDigitCount of zero
            // yields a minimum integer digits of zero, which allows proper round-trip
            // patterns. We don't want "#" to become "#0" when toPattern() is called (even
            // though that's what it really is, semantically).
            if (zeroDigitCount == 0 && sigDigitCount == 0 &&
                digitLeftCount > 0 && decimalPos >= 0) {
                // Handle "###.###" and "###." and ".###"
                int n = decimalPos;
                if (n == 0)
                    ++n; // Handle ".###"
                digitRightCount = digitLeftCount - n;
                digitLeftCount = n - 1;
                zeroDigitCount = 1;
            }

            // Do syntax checking on the digits, decimal points, and quotes.
            if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)
                || (decimalPos >= 0
                    && (sigDigitCount > 0
                        || decimalPos < digitLeftCount
                        || decimalPos > (digitLeftCount + zeroDigitCount)))
                || groupingCount == 0
                || groupingCount2 == 0
                || (sigDigitCount > 0 && zeroDigitCount > 0)
                || subpart > 2) { // subpart > 2 == unmatched quote
                patternError("Malformed pattern", pattern);
            }

            // Make sure pad is at legal position before or after affix.
            if (padPos >= 0) {
                if (padPos == start) {
                    padPos = PAD_BEFORE_PREFIX;
                } else if (padPos + 2 == sub0Start) {
                    padPos = PAD_AFTER_PREFIX;
                } else if (padPos == sub0Limit) {
                    padPos = PAD_BEFORE_SUFFIX;
                } else if (padPos + 2 == sub2Limit) {
                    padPos = PAD_AFTER_SUFFIX;
                } else {
                    patternError("Illegal pad position", pattern);
                }
            }

            if (part == 0) {
                // Set negative affixes temporarily to match the positive
                // affixes. Fix this up later after processing both parts.

                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
                // [Richard/GCL]
                posPrefixPattern = negPrefixPattern = prefix.toString();
                posSuffixPattern = negSuffixPattern = suffix.toString();

                useExponentialNotation = (expDigits >= 0);
                if (useExponentialNotation) {
                    minExponentDigits = expDigits;
                    exponentSignAlwaysShown = expSignAlways;
                }
                int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
                // The effectiveDecimalPos is the position the decimal is at or would be
                // at if there is no decimal. Note that if decimalPos<0, then
                // digitTotalCount == digitLeftCount + zeroDigitCount.
                int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
                boolean useSigDig = (sigDigitCount > 0);
                setSignificantDigitsUsed(useSigDig);
                if (useSigDig) {
                    setMinimumSignificantDigits(sigDigitCount);
                    setMaximumSignificantDigits(sigDigitCount + digitRightCount);
                } else {
                    int minInt = effectiveDecimalPos - digitLeftCount;
                    setMinimumIntegerDigits(minInt);

                    // Upper limit on integer and fraction digits for a Java double
                    // [Richard/GCL]
                    setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt :
                                            DOUBLE_INTEGER_DIGITS);
                    setMaximumFractionDigits(decimalPos >= 0 ?
                                             (digitTotalCount - decimalPos) : 0);
                    setMinimumFractionDigits(decimalPos >= 0 ?
                                             (digitLeftCount + zeroDigitCount - decimalPos) : 0);
                }
                setGroupingUsed(groupingCount > 0);
                this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
                this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
                    ? groupingCount2 : 0;
                this.multiplier = multpl;
                setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
                if (padPos >= 0) {
                    padPosition = padPos;
                    formatWidth = sub0Limit - sub0Start; // to be fixed up below
                    pad = padChar;
                } else {
                    formatWidth = 0;
                }
                if (incrementVal != 0) {
                    // BigDecimal scale cannot be negative (even though this makes perfect
                    // sense), so we need to handle this.
                    int scale = incrementPos - effectiveDecimalPos;
                    roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
                    if (scale < 0) {
                        roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);
                    }
                    setRoundingDouble();
                    roundingMode = BigDecimal.ROUND_HALF_EVEN;
                } else {
                    setRoundingIncrement((BigDecimal) null);
                }

                // Update currency sign count for the new pattern
                currencySignCount = currencySignCnt;
            } else {
                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
                // [Richard/GCL]
                negPrefixPattern = prefix.toString();
                negSuffixPattern = suffix.toString();
                gotNegative = true;
            }
        }


        // Bug 4140009 Process the empty pattern [Richard/GCL]
        if (pattern.length() == 0) {
            posPrefixPattern = posSuffixPattern = "";
            setMinimumIntegerDigits(0);
            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
            setMinimumFractionDigits(0);
            setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
        }

        // If there was no negative pattern, or if the negative pattern is identical to
        // the positive pattern, then prepend the minus sign to the positive pattern to
        // form the negative pattern.

        // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]

        if (!gotNegative ||
            (negPrefixPattern.equals(posPrefixPattern)
             && negSuffixPattern.equals(posSuffixPattern))) {
            negSuffixPattern = posSuffixPattern;
            negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
        }
        setLocale(null, null);
        // save the pattern
        formatPattern = pattern;

        // special handlings for currency instance
        if (currencySignCount > 0) {
            // reset rounding increment and max/min fractional digits
            // by the currency
            Currency theCurrency = getCurrency();
            if (theCurrency != null) {
                setRoundingIncrement(theCurrency.getRoundingIncrement());
                int d = theCurrency.getDefaultFractionDigits();
                setMinimumFractionDigits(d);
                setMaximumFractionDigits(d);
            }

            // initialize currencyPluralInfo if needed
            if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT
                && currencyPluralInfo == null) {
                currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
            }
        }
    }

    /**
     * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.
     */
    private void setRoundingDouble() {
        if (roundingIncrementICU == null) {
            roundingDouble = 0.0d;
            roundingDoubleReciprocal = 0.0d;
        } else {
            roundingDouble = roundingIncrementICU.doubleValue();
            setRoundingDoubleReciprocal(1.0d / roundingDouble);
        }
    }

    private void patternError(String msg, String pattern) {
        throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
    }


    // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits
    // for a Java double [Richard/GCL]

    /**
     * Sets the maximum number of digits allowed in the integer portion of a number. This
     * override limits the integer digit count to 309.
     *
     * @see NumberFormat#setMaximumIntegerDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMaximumIntegerDigits(int newValue) {
        super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
    }

    /**
     * Sets the minimum number of digits allowed in the integer portion of a number. This
     * override limits the integer digit count to 309.
     *
     * @see NumberFormat#setMinimumIntegerDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMinimumIntegerDigits(int newValue) {
        super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
    }

    /**
     * {@icu} Returns the minimum number of significant digits that will be
     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
     * returns true.
     *
     * @return the fewest significant digits that will be shown
     * @stable ICU 3.0
     */
    public int getMinimumSignificantDigits() {
        return minSignificantDigits;
    }

    /**
     * {@icu} Returns the maximum number of significant digits that will be
     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
     * returns true.
     *
     * @return the most significant digits that will be shown
     * @stable ICU 3.0
     */
    public int getMaximumSignificantDigits() {
        return maxSignificantDigits;
    }

    /**
     * {@icu} Sets the minimum number of significant digits that will be displayed. If
     * <code>min</code> is less than one then it is set to one. If the maximum significant
     * digits count is less than <code>min</code>, then it is set to
     * <code>min</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
     * returns true.
     *
     * @param min the fewest significant digits to be shown
     * @stable ICU 3.0
     */
    public void setMinimumSignificantDigits(int min) {
        if (min < 1) {
            min = 1;
        }
        // pin max sig dig to >= min
        int max = Math.max(maxSignificantDigits, min);
        minSignificantDigits = min;
        maxSignificantDigits = max;
    }

    /**
     * {@icu} Sets the maximum number of significant digits that will be displayed. If
     * <code>max</code> is less than one then it is set to one. If the minimum significant
     * digits count is greater than <code>max</code>, then it is set to
     * <code>max</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
     * returns true.
     *
     * @param max the most significant digits to be shown
     * @stable ICU 3.0
     */
    public void setMaximumSignificantDigits(int max) {
        if (max < 1) {
            max = 1;
        }
        // pin min sig dig to 1..max
        int min = Math.min(minSignificantDigits, max);
        minSignificantDigits = min;
        maxSignificantDigits = max;
    }

    /**
     * {@icu} Returns true if significant digits are in use or false if integer and
     * fraction digit counts are in use.
     *
     * @return true if significant digits are in use
     * @stable ICU 3.0
     */
    public boolean areSignificantDigitsUsed() {
        return useSignificantDigits;
    }

    /**
     * {@icu} Sets whether significant digits are in use, or integer and fraction digit
     * counts are in use.
     *
     * @param useSignificantDigits true to use significant digits, or false to use integer
     * and fraction digit counts
     * @stable ICU 3.0
     */
    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
        this.useSignificantDigits = useSignificantDigits;
    }

    /**
     * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
     * effect immediately, if this format is a currency format. If this format is not a
     * currency format, then the currency object is used if and when this object becomes a
     * currency format through the application of a new pattern.
     *
     * @param theCurrency new currency object to use. Must not be null.
     * @stable ICU 2.2
     */
    @Override
    public void setCurrency(Currency theCurrency) {
        // If we are a currency format, then modify our affixes to
        // encode the currency symbol for the given currency in our
        // locale, and adjust the decimal digits and rounding for the
        // given currency.

        super.setCurrency(theCurrency);
        if (theCurrency != null) {
            boolean[] isChoiceFormat = new boolean[1];
            String s = theCurrency.getName(symbols.getULocale(),
                                           Currency.SYMBOL_NAME, isChoiceFormat);
            symbols.setCurrency(theCurrency);
            symbols.setCurrencySymbol(s);
        }

        if (currencySignCount > 0) {
            if (theCurrency != null) {
                setRoundingIncrement(theCurrency.getRoundingIncrement());
                int d = theCurrency.getDefaultFractionDigits();
                setMinimumFractionDigits(d);
                setMaximumFractionDigits(d);
            }
            if (currencySignCount != CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
                // This is not necessary for plural format type
                // because affixes will be resolved in subformat
                expandAffixes(null);
            }
        }
    }

    /**
     * Returns the currency in effect for this formatter. Subclasses should override this
     * method as needed. Unlike getCurrency(), this method should never return null.
     *
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    @Override
    protected Currency getEffectiveCurrency() {
        Currency c = getCurrency();
        if (c == null) {
            c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
        }
        return c;
    }

    /**
     * Sets the maximum number of digits allowed in the fraction portion of a number. This
     * override limits the fraction digit count to 340.
     *
     * @see NumberFormat#setMaximumFractionDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMaximumFractionDigits(int newValue) {
        super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
    }

    /**
     * Sets the minimum number of digits allowed in the fraction portion of a number. This
     * override limits the fraction digit count to 340.
     *
     * @see NumberFormat#setMinimumFractionDigits
     * @stable ICU 2.0
     */
    @Override
    public void setMinimumFractionDigits(int newValue) {
        super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
    }

    /**
     * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
     * default value is false.
     *
     * @param value true if {@link #parse(String, ParsePosition)}
     * returns BigDecimal.
     * @stable ICU 3.6
     */
    public void setParseBigDecimal(boolean value) {
        parseBigDecimal = value;
    }

    /**
     * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
     *
     * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
     * @stable ICU 3.6
     */
    public boolean isParseBigDecimal() {
        return parseBigDecimal;
    }
    
    /**
    * Set the maximum number of exponent digits when parsing a number. 
    * If the limit is set too high, an OutOfMemoryException may be triggered.
    * The default value is 1000.
    * @param newValue the new limit
    * @draft ICU 51
    */
    public void setParseMaxDigits(int newValue) {
        if (newValue > 0) {
            PARSE_MAX_EXPONENT = newValue;
        }
    }
    
    /**
    * Get the current maximum number of exponent digits when parsing a
    * number.
    *
    * @draft ICU 51
    */
    public int getParseMaxDigits() {
        return PARSE_MAX_EXPONENT;
    }

    private void writeObject(ObjectOutputStream stream) throws IOException {
        // Ticket#6449 Format.Field instances are not serializable. When
        // formatToCharacterIterator is called, attributes (ArrayList) stores
        // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is
        // not serializable, we need to clear the contents of the list when writeObject is
        // called. We could remove the field or make it transient, but it will break
        // serialization compatibility.
        attributes.clear();

        stream.defaultWriteObject();
    }

    /**
     * First, read the default serializable fields from the stream. Then if
     * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was
     * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since
     * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the
     * maximum allowed value so that default serialization will work properly if this
     * object is streamed out again.
     */
    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject();

        // Bug 4185761 validate fields [Richard/GCL]

        // We only need to check the maximum counts because NumberFormat .readObject has
        // already ensured that the maximum is greater than the minimum count.

        // Commented for compatibility with previous version, and reserved for further use
        // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
        // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new
        // InvalidObjectException("Digit count out of range"); }


        // Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and
        // maximumFractionDigits to DOUBLE_FRACTION_DIGITS

        if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
        }
        if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
            setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
        }
        if (serialVersionOnStream < 2) {
            exponentSignAlwaysShown = false;
            setInternalRoundingIncrement(null);
            setRoundingDouble();
            roundingMode = BigDecimal.ROUND_HALF_EVEN;
            formatWidth = 0;
            pad = ' ';
            padPosition = PAD_BEFORE_PREFIX;
            if (serialVersionOnStream < 1) {
                // Didn't have exponential fields
                useExponentialNotation = false;
            }
        }
        if (serialVersionOnStream < 3) {
            // Versions prior to 3 do not store a currency object.  Create one to match
            // the DecimalFormatSymbols object.
            setCurrencyForSymbols();
        }
        serialVersionOnStream = currentSerialVersion;
        digitList = new DigitList();

        if (roundingIncrement != null) {
            setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
            setRoundingDouble();
        }
    }

    private void setInternalRoundingIncrement(BigDecimal value) {
        roundingIncrementICU = value;
        roundingIncrement = value == null ? null : value.toBigDecimal();
    }

    // ----------------------------------------------------------------------
    // INSTANCE VARIABLES
    // ----------------------------------------------------------------------

    private transient DigitList digitList = new DigitList();

    /**
     * The symbol used as a prefix when formatting positive numbers, e.g. "+".
     *
     * @serial
     * @see #getPositivePrefix
     */
    private String positivePrefix = "";

    /**
     * The symbol used as a suffix when formatting positive numbers. This is often an
     * empty string.
     *
     * @serial
     * @see #getPositiveSuffix
     */
    private String positiveSuffix = "";

    /**
     * The symbol used as a prefix when formatting negative numbers, e.g. "-".
     *
     * @serial
     * @see #getNegativePrefix
     */
    private String negativePrefix = "-";

    /**
     * The symbol used as a suffix when formatting negative numbers. This is often an
     * empty string.
     *
     * @serial
     * @see #getNegativeSuffix
     */
    private String negativeSuffix = "";

    /**
     * The prefix pattern for non-negative numbers. This variable corresponds to
     * <code>positivePrefix</code>.
     *
     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
     * <code>positivePrefix</code> to update the latter to reflect changes in
     * <code>symbols</code>. If this variable is <code>null</code> then
     * <code>positivePrefix</code> is taken as a literal value that does not change when
     * <code>symbols</code> changes.  This variable is always <code>null</code> for
     * <code>DecimalFormat</code> objects older than stream version 2 restored from
     * stream.
     *
     * @serial
     */
    // [Richard/GCL]
    private String posPrefixPattern;

    /**
     * The suffix pattern for non-negative numbers. This variable corresponds to
     * <code>positiveSuffix</code>. This variable is analogous to
     * <code>posPrefixPattern</code>; see that variable for further documentation.
     *
     * @serial
     */
    // [Richard/GCL]
    private String posSuffixPattern;

    /**
     * The prefix pattern for negative numbers. This variable corresponds to
     * <code>negativePrefix</code>. This variable is analogous to
     * <code>posPrefixPattern</code>; see that variable for further documentation.
     *
     * @serial
     */
    // [Richard/GCL]
    private String negPrefixPattern;

    /**
     * The suffix pattern for negative numbers. This variable corresponds to
     * <code>negativeSuffix</code>. This variable is analogous to
     * <code>posPrefixPattern</code>; see that variable for further documentation.
     *
     * @serial
     */
    // [Richard/GCL]
    private String negSuffixPattern;

    /**
     * Formatter for ChoiceFormat-based currency names. If this field is not null, then
     * delegate to it to format currency symbols.
     *
     * @since ICU 2.6
     */
    private ChoiceFormat currencyChoice;

    /**
     * The multiplier for use in percent, permill, etc.
     *
     * @serial
     * @see #getMultiplier
     */
    private int multiplier = 1;

    /**
     * The number of digits between grouping separators in the integer portion of a
     * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true.
     *
     * @serial
     * @see #getGroupingSize
     * @see NumberFormat#isGroupingUsed
     */
    private byte groupingSize = 3; // invariant, > 0 if useThousands

    /**
     * The secondary grouping size. This is only used for Hindi numerals, which use a
     * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this
     * value is less than 1, then secondary grouping is equal to the primary grouping.
     *
     */
    private byte groupingSize2 = 0;

    /**
     * If true, forces the decimal separator to always appear in a formatted number, even
     * if the fractional part of the number is zero.
     *
     * @serial
     * @see #isDecimalSeparatorAlwaysShown
     */
    private boolean decimalSeparatorAlwaysShown = false;

    /**
     * The <code>DecimalFormatSymbols</code> object used by this format. It contains the
     * symbols used to format numbers, e.g. the grouping separator, decimal separator, and
     * so on.
     *
     * @serial
     * @see #setDecimalFormatSymbols
     * @see DecimalFormatSymbols
     */
    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();

    /**
     * True to use significant digits rather than integer and fraction digit counts.
     *
     * @serial
     * @since ICU 3.0
     */
    private boolean useSignificantDigits = false;

    /**
     * The minimum number of significant digits to show. Must be >= 1 and <=
     * maxSignificantDigits. Ignored unless useSignificantDigits == true.
     *
     * @serial
     * @since ICU 3.0
     */
    private int minSignificantDigits = 1;

    /**
     * The maximum number of significant digits to show. Must be >=
     * minSignficantDigits. Ignored unless useSignificantDigits == true.
     *
     * @serial
     * @since ICU 3.0
     */
    private int maxSignificantDigits = 6;

    /**
     * True to force the use of exponential (i.e. scientific) notation
     * when formatting numbers.
     *
     *<p> Note that the JDK 1.2 public API provides no way to set this
     * field, even though it is supported by the implementation and
     * the stream format. The intent is that this will be added to the
     * API in the future.
     *
     * @serial
     */
    private boolean useExponentialNotation; // Newly persistent in JDK 1.2

    /**
     * The minimum number of digits used to display the exponent when a number is
     * formatted in exponential notation.  This field is ignored if
     * <code>useExponentialNotation</code> is not true.
     *
     * <p>Note that the JDK 1.2 public API provides no way to set this field, even though
     * it is supported by the implementation and the stream format. The intent is that
     * this will be added to the API in the future.
     *
     * @serial
     */
    private byte minExponentDigits; // Newly persistent in JDK 1.2

    /**
     * If true, the exponent is always prefixed with either the plus sign or the minus
     * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has
     * no effect unless <code>useExponentialNotation</code> is true.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private boolean exponentSignAlwaysShown = false;

    /**
     * The value to which numbers are rounded during formatting. For example, if the
     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
     * positive value if rounding is in effect. Default value <code>null</code>.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    // Note: this is kept in sync with roundingIncrementICU.
    // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
    private java.math.BigDecimal roundingIncrement = null;

    /**
     * The value to which numbers are rounded during formatting. For example, if the
     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
     * positive value if rounding is in effect. Default value <code>null</code>. WARNING:
     * the roundingIncrement value is the one serialized.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private transient BigDecimal roundingIncrementICU = null;

    /**
     * The rounding increment as a double. If this value is <= 0, then no rounding is
     * done. This value is <code>roundingIncrementICU.doubleValue()</code>. Default value
     * 0.0.
     */
    private transient double roundingDouble = 0.0;

    /**
     * If the roundingDouble is the reciprocal of an integer (the most common case!), this
     * is set to be that integer.  Otherwise it is 0.0.
     */
    private transient double roundingDoubleReciprocal = 0.0;

    /**
     * The rounding mode. This value controls any rounding operations which occur when
     * applying a rounding increment or when reducing the number of fraction digits to
     * satisfy a maximum fraction digits limit. The value may assume any of the
     * <code>BigDecimal</code> rounding mode values. Default value
     * <code>BigDecimal.ROUND_HALF_EVEN</code>.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private int roundingMode = BigDecimal.ROUND_HALF_EVEN;

    /**
     * Operations on <code>BigDecimal</code> numbers are controlled by a {@link
     * MathContext} object, which provides the context (precision and other information)
     * for the operation. The default <code>MathContext</code> settings are
     * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>;
     * these settings perform fixed point arithmetic with unlimited precision, as defined
     * for the original BigDecimal class in Java 1.1 and Java 1.2
     */
    // context for plain unlimited math
    private MathContext mathContext = new MathContext(0, MathContext.PLAIN);

    /**
     * The padded format width, or zero if there is no padding. Must be >= 0. Default
     * value zero.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private int formatWidth = 0;

    /**
     * The character used to pad the result of format to <code>formatWidth</code>, if
     * padding is in effect. Default value ' '.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private char pad = ' ';

    /**
     * The position in the string at which the <code>pad</code> character will be
     * inserted, if padding is in effect.  Must have a value from
     * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value
     * <code>PAD_BEFORE_PREFIX</code>.
     *
     * @serial
     * @since AlphaWorks NumberFormat
     */
    private int padPosition = PAD_BEFORE_PREFIX;

    /**
     * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than
     * Long, Double or BigDecimal except special values. This property is introduced for
     * J2SE 5 compatibility support.
     *
     * @serial
     * @since ICU 3.6
     * @see #setParseBigDecimal(boolean)
     * @see #isParseBigDecimal()
     */
    private boolean parseBigDecimal = false;

    // ----------------------------------------------------------------------

    static final int currentSerialVersion = 3;

    /**
     * The internal serial version which says which version was written Possible values
     * are:
     *
     * <ul>
     *
     * <li><b>0</b> (default): versions before JDK 1.2
     *
     * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
     * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
     *
     * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad,
     * padPosition, exponentSignAlwaysShown, roundingIncrement.
     *
     * <li><b>3</b>: ICU 2.2. Adds currency object.
     *
     * </ul>
     *
     * @serial
     */
    private int serialVersionOnStream = currentSerialVersion;

    // ----------------------------------------------------------------------
    // CONSTANTS
    // ----------------------------------------------------------------------

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted before the prefix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_BEFORE_PREFIX = 0;

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted after the prefix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_AFTER_PREFIX = 1;

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted before the suffix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_AFTER_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_BEFORE_SUFFIX = 2;

    /**
     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
     * specify pad characters inserted after the suffix.
     *
     * @see #setPadPosition
     * @see #getPadPosition
     * @see #PAD_BEFORE_PREFIX
     * @see #PAD_AFTER_PREFIX
     * @see #PAD_BEFORE_SUFFIX
     * @stable ICU 2.0
     */
    public static final int PAD_AFTER_SUFFIX = 3;

    // Constants for characters used in programmatic (unlocalized) patterns.
    static final char PATTERN_ZERO_DIGIT = '0';
    static final char PATTERN_ONE_DIGIT = '1';
    static final char PATTERN_TWO_DIGIT = '2';
    static final char PATTERN_THREE_DIGIT = '3';
    static final char PATTERN_FOUR_DIGIT = '4';
    static final char PATTERN_FIVE_DIGIT = '5';
    static final char PATTERN_SIX_DIGIT = '6';
    static final char PATTERN_SEVEN_DIGIT = '7';
    static final char PATTERN_EIGHT_DIGIT = '8';
    static final char PATTERN_NINE_DIGIT = '9';
    static final char PATTERN_GROUPING_SEPARATOR = ',';
    static final char PATTERN_DECIMAL_SEPARATOR = '.';
    static final char PATTERN_DIGIT = '#';
    static final char PATTERN_SIGNIFICANT_DIGIT = '@';
    static final char PATTERN_EXPONENT = 'E';
    static final char PATTERN_PLUS_SIGN = '+';

    // Affix
    private static final char PATTERN_PER_MILLE = '\u2030';
    private static final char PATTERN_PERCENT = '%';
    static final char PATTERN_PAD_ESCAPE = '*';
    /**
     * Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
     */
    private static final char PATTERN_MINUS = '-';

    // Other
    private static final char PATTERN_SEPARATOR = ';';

    // Pad escape is package private to allow access by DecimalFormatSymbols.
    // Also plus sign. Also exponent.

    /**
     * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in
     * patterns and substitued with either the currency symbol, or if it is doubled, with
     * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then
     * the decimal separator is replaced with the monetary decimal separator.
     *
     * The CURRENCY_SIGN is not localized.
     */
    private static final char CURRENCY_SIGN = '\u00A4';

    private static final char QUOTE = '\'';

    /**
     * Upper limit on integer and fraction digits for a Java double [Richard/GCL]
     */
    static final int DOUBLE_INTEGER_DIGITS = 309;
    static final int DOUBLE_FRACTION_DIGITS = 340;

    /**
     * When someone turns on scientific mode, we assume that more than this number of
     * digits is due to flipping from some other mode that didn't restrict the maximum,
     * and so we force 1 integer digit. We don't bother to track and see if someone is
     * using exponential notation with more than this number, it wouldn't make sense
     * anyway, and this is just to make sure that someone turning on scientific mode with
     * default settings doesn't end up with lots of zeroes.
     */
    static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;

    // Proclaim JDK 1.1 serial compatibility.
    private static final long serialVersionUID = 864413376551465018L;

    private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>();

    // The following are used in currency format

    // -- triple currency sign char array
    // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
    // -- triple currency sign string
    // private static final String tripleCurrencyStr = new String(tripleCurrencySign);
    //
    // -- default currency plural pattern char array
    // private static final char[] defaultCurrencyPluralPatternChar =
    //   {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
    // -- default currency plural pattern string
    // private static final String defaultCurrencyPluralPattern =
    //     new String(defaultCurrencyPluralPatternChar);

    // pattern used in this formatter
    private String formatPattern = "";
    // style is only valid when decimal formatter is constructed by
    // DecimalFormat(pattern, decimalFormatSymbol, style)
    private int style = NumberFormat.NUMBERSTYLE;
    /**
     * Represents whether this is a currency format, and which currency format style. 0:
     * not currency format type; 1: currency style -- symbol name, such as "$" for US
     * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style
     * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for
     * "3.00 US Dollars".
     */
    private int currencySignCount = 0;

    /**
     * For parsing purposes, we need to remember all prefix patterns and suffix patterns
     * of every currency format pattern, including the pattern of the default currency
     * style, ISO currency style, and plural currency style. The patterns are set through
     * applyPattern. The following are used to represent the affix patterns in currency
     * plural formats.
     */
    private static final class AffixForCurrency {
        // negative prefix pattern
        private String negPrefixPatternForCurrency = null;
        // negative suffix pattern
        private String negSuffixPatternForCurrency = null;
        // positive prefix pattern
        private String posPrefixPatternForCurrency = null;
        // positive suffix pattern
        private String posSuffixPatternForCurrency = null;
        private final int patternType;

        public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix,
                                String posSuffix, int type) {
            negPrefixPatternForCurrency = negPrefix;
            negSuffixPatternForCurrency = negSuffix;
            posPrefixPatternForCurrency = posPrefix;
            posSuffixPatternForCurrency = posSuffix;
            patternType = type;
        }

        public String getNegPrefix() {
            return negPrefixPatternForCurrency;
        }

        public String getNegSuffix() {
            return negSuffixPatternForCurrency;
        }

        public String getPosPrefix() {
            return posPrefixPatternForCurrency;
        }

        public String getPosSuffix() {
            return posSuffixPatternForCurrency;
        }

        public int getPatternType() {
            return patternType;
        }
    }

    // Affix pattern set for currency.  It is a set of AffixForCurrency, each element of
    // the set saves the negative prefix, negative suffix, positive prefix, and positive
    // suffix of a pattern.
    private transient Set<AffixForCurrency> affixPatternsForCurrency = null;

    // For currency parsing. Since currency parsing needs to parse against all currency
    // patterns, before the parsing, we need to set up the affix patterns for all currencies.
    private transient boolean isReadyForParsing = false;

    // Information needed for DecimalFormat to format/parse currency plural.
    private CurrencyPluralInfo currencyPluralInfo = null;

    /**
     * Unit is an immutable class for the textual representation of a unit, in
     * particular its prefix and suffix.
     *
     * @author rocketman
     *
     */
    static class Unit {
        private final String prefix;
        private final String suffix;

        public Unit(String prefix, String suffix) {
            this.prefix = prefix;
            this.suffix = suffix;
        }

        public void writeSuffix(StringBuffer toAppendTo) {
            toAppendTo.append(suffix);
        }

        public void writePrefix(StringBuffer toAppendTo) {
            toAppendTo.append(prefix);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof Unit)) {
                return false;
            }
            Unit other = (Unit) obj;
            return prefix.equals(other.prefix) && suffix.equals(other.suffix);
        }
    }

    static final Unit NULL_UNIT = new Unit("", "");
}

// eof
