/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.i18n.client;

import com.google.gwt.i18n.client.constants.NumberConstants;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Formats and parses numbers using locale-sensitive patterns.
 *
 * This class provides comprehensive and flexible support for a wide variety of
 * localized formats, including
 * <ul>
 * <li><b>Locale-specific symbols</b> such as decimal point, group separator,
 * digit representation, currency symbol, percent, and permill</li>
 * <li><b>Numeric variations</b> including integers ("123"), fixed-point
 * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and
 * currency amounts ("$123")</li>
 * <li><b>Predefined standard patterns</b> that can be used both for parsing
 * and formatting, including {@link #getDecimalFormat() decimal},
 * {@link #getCurrencyFormat() currency},
 * {@link #getPercentFormat() percentages}, and
 * {@link #getScientificFormat() scientific}</li>
 * <li><b>Custom patterns</b> and supporting features designed to make it
 * possible to parse and format numbers in any locale, including support for
 * Western, Arabic, and Indic digits</li>
 * </ul>
 *
 * <h3>Patterns</h3>
 * <p>
 * Formatting and parsing are based on customizable patterns that can include a
 * combination of literal characters and special characters that act as
 * placeholders and are replaced by their localized counterparts. 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 '<code>#</code>' character is replaced by a localized digit.
 * </p>
 *
 * <p>
 * Often the replacement character is the same as the pattern character. In the
 * U.S. locale, for example, the '<code>,</code>' grouping character is
 * replaced by the same character '<code>,</code>'. However, the replacement
 * is still actually happening, and in a different locale, the grouping
 * character may change to a different character, such as '<code>.</code>'.
 * 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>
 *
 * <p>
 * The characters listed below are used in patterns. Localized symbols use the
 * corresponding characters taken from corresponding locale symbol collection,
 * which can be found in the properties files residing in the
 * <code><nobr>com.google.gwt.i18n.client.constants</nobr></code>. 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>
 *
 * <table>
 * <tr>
 * <th>Symbol</th>
 * <th>Location</th>
 * <th>Localized?</th>
 * <th>Meaning</th>
 * </tr>
 *
 * <tr>
 * <td><code>0</code></td>
 * <td>Number</td>
 * <td>Yes</td>
 * <td>Digit</td>
 * </tr>
 *
 * <tr>
 * <td><code>#</code></td>
 * <td>Number</td>
 * <td>Yes</td>
 * <td>Digit, zero shows as absent</td>
 * </tr>
 *
 * <tr>
 * <td><code>.</code></td>
 * <td>Number</td>
 * <td>Yes</td>
 * <td>Decimal separator or monetary decimal separator</td>
 * </tr>
 *
 * <tr>
 * <td><code>-</code></td>
 * <td>Number</td>
 * <td>Yes</td>
 * <td>Minus sign</td>
 * </tr>
 *
 * <tr>
 * <td><code>,</code></td>
 * <td>Number</td>
 * <td>Yes</td>
 * <td>Grouping separator</td>
 * </tr>
 *
 * <tr>
 * <td><code>E</code></td>
 * <td>Number</td>
 * <td>Yes</td>
 * <td>Separates mantissa and exponent in scientific notation; need not be
 * quoted in prefix or suffix</td>
 * </tr>
 *
 * <tr>
 * <td><code>;</code></td>
 * <td>Subpattern boundary</td>
 * <td>Yes</td>
 * <td>Separates positive and negative subpatterns</td>
 * </tr>
 *
 * <tr>
 * <td><code>%</code></td>
 * <td>Prefix or suffix</td>
 * <td>Yes</td>
 * <td>Multiply by 100 and show as percentage</td>
 * </tr>
 *
 * <tr>
 * <td><nobr><code>\u2030</code> (\u005Cu2030)</nobr></td>
 * <td>Prefix or suffix</td>
 * <td>Yes</td>
 * <td>Multiply by 1000 and show as per mille</td>
 * </tr>
 *
 * <tr>
 * <td><nobr><code>\u00A4</code> (\u005Cu00A4)</nobr></td>
 * <td>Prefix or suffix</td>
 * <td>No</td>
 * <td>Currency sign, replaced by currency symbol; if doubled, replaced by
 * international currency symbol; if present in a pattern, the monetary decimal
 * separator is used instead of the decimal separator</td>
 * </tr>
 *
 * <tr>
 * <td><code>'</code></td>
 * <td>Prefix or suffix</td>
 * <td>No</td>
 * <td>Used to quote special characters in a prefix or suffix; for example,
 * <code>"'#'#"</code> formats <code>123</code> to <code>"#123"</code>;
 * to create a single quote itself, use two in succession, such as
 * <code>"# o''clock"</code></td>
 * </tr>
 *
 * </table>
 *
 * <p>
 * A <code>NumberFormat</code> pattern contains a postive and negative
 * subpattern separated by a semicolon, such as
 * <code>"#,##0.00;(#,##0.00)"</code>. 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, <code>"0.00"</code> alone is equivalent to
 * <code>"0.00;-0.00"</code>. 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 <code>"#,##0.0#;(#)"</code> has precisely the
 * same result as <code>"#,##0.0#;(#,##0.0#)"</code>.
 * </p>
 *
 * <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, the decimal separator and thousands separator should
 * be distinct characters, or parsing will be impossible.
 * </p>
 *
 * <p>
 * The grouping separator 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 grouping size is the
 * number of digits between the grouping separators, such as 3 for "100,000,000"
 * or 4 for "1 0000 0000".
 * </p>
 *
 * <h3>Pattern Grammar (BNF)</h3>
 * <p>
 * The pattern itself uses the following grammar:
 * </p>
 *
 * <table>
 * <tr>
 * <td>pattern</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">subpattern ('<code>;</code>'
 * subpattern)?</td>
 * </tr>
 * <tr>
 * <td>subpattern</td>
 * <td>:=</td>
 * <td>prefix? number exponent? suffix?</td>
 * </tr>
 * <tr>
 * <td>number</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">(integer ('<code>.</code>' fraction)?) |
 * sigDigits</td>
 * </tr>
 * <tr>
 * <td>prefix</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>\u005Cu0000</code>'..'<code>\u005CuFFFD</code>' -
 * specialCharacters</td>
 * </tr>
 * <tr>
 * <td>suffix</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>\u005Cu0000</code>'..'<code>\u005CuFFFD</code>' -
 * specialCharacters</td>
 * </tr>
 * <tr>
 * <td>integer</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>#</code>'* '<code>0</code>'*'<code>0</code>'</td>
 * </tr>
 * <tr>
 * <td>fraction</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>0</code>'* '<code>#</code>'*</td>
 * </tr>
 * <tr>
 * <td>sigDigits</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>#</code>'* '<code>@</code>''<code>@</code>'* '<code>#</code>'*</td>
 * </tr>
 * <tr>
 * <td>exponent</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>E</code>' '<code>+</code>'? '<code>0</code>'* '<code>0</code>'</td>
 * </tr>
 * <tr>
 * <td>padSpec</td>
 * <td>:=</td>
 * <td style="white-space: nowrap">'<code>*</code>' padChar</td>
 * </tr>
 * <tr>
 * <td>padChar</td>
 * <td>:=</td>
 * <td>'<code>\u005Cu0000</code>'..'<code>\u005CuFFFD</code>' - quote</td>
 * </tr>
 * </table>
 *
 * <p>
 * Notation:
 * </p>
 *
 * <table>
 * <tr>
 * <td>X*</td>
 * <td style="white-space: nowrap">0 or more instances of X</td>
 * </tr>
 *
 * <tr>
 * <td>X?</td>
 * <td style="white-space: nowrap">0 or 1 instances of X</td>
 * </tr>
 *
 * <tr>
 * <td>X|Y</td>
 * <td style="white-space: nowrap">either X or Y</td>
 * </tr>
 *
 * <tr>
 * <td>C..D</td>
 * <td style="white-space: nowrap">any character from C up to D, inclusive</td>
 * </tr>
 *
 * <tr>
 * <td>S-T</td>
 * <td style="white-space: nowrap">characters in S, except those in T</td>
 * </tr>
 * </table>
 *
 * <p>
 * The first subpattern is for positive numbers. The second (optional)
 * subpattern is for negative numbers.
 * </p>
 *
 *  <h3>Example</h3> {@example com.google.gwt.examples.NumberFormatExample}
 *
 *
 */
public class NumberFormat {

  // Sets of constants as defined for the current locale from CLDR.
  protected static final NumberConstants localizedNumberConstants = LocaleInfo.getCurrentLocale().getNumberConstants();

  /**
   * Current NumberConstants interface to use, see
   * {@link #setForcedLatinDigits(boolean)} for changing it.
   */
  protected static NumberConstants defaultNumberConstants = localizedNumberConstants;

  // Cached instances of standard formatters.
  private static NumberFormat cachedCurrencyFormat;
  private static NumberFormat cachedDecimalFormat;
  private static NumberFormat cachedPercentFormat;
  private static NumberFormat cachedScientificFormat;

  // Number constants mapped to use latin digits/separators.
  private static NumberConstants latinNumberConstants = null;

  // Localized characters for dot and comma in number patterns, used to produce
  // the latin mapping for arbitrary locales.  Any separator not in either of
  // these strings will be mapped to non-breaking space (U+00A0).
  private static final String LOCALIZED_COMMA_EQUIVALENTS = ",\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64";
  private static final String LOCALIZED_DOT_EQUIVALENTS = ".\u2024\u3002\uFE12\uFE52\uFF0E\uFF61";

  // Constants for characters used in programmatic (unlocalized) patterns.
  private static final char CURRENCY_SIGN = '\u00A4';
  private static final char PATTERN_DECIMAL_SEPARATOR = '.';
  private static final char PATTERN_DIGIT = '#';
  private static final char PATTERN_EXPONENT = 'E';
  private static final char PATTERN_GROUPING_SEPARATOR = ',';
  private static final char PATTERN_MINUS = '-';
  private static final char PATTERN_PER_MILLE = '\u2030';
  private static final char PATTERN_PERCENT = '%';
  private static final char PATTERN_SEPARATOR = ';';
  private static final char PATTERN_ZERO_DIGIT = '0';

  private static final char QUOTE = '\'';

  /**
   * Returns true if all new NumberFormat instances will use latin digits and
   * related characters rather than the localized ones.
   */
  public static boolean forcedLatinDigits() {
    return defaultNumberConstants != localizedNumberConstants;
  }

  /**
   * Provides the standard currency format for the default locale.
   *
   * @return a <code>NumberFormat</code> capable of producing and consuming
   *         currency format for the default locale
   */
  public static NumberFormat getCurrencyFormat() {
    if (cachedCurrencyFormat == null) {
      cachedCurrencyFormat = new NumberFormat(
          defaultNumberConstants.currencyPattern(), CurrencyList.get().getDefault(), false);
    }
    return cachedCurrencyFormat;
  }

  /**
   * Provides the standard currency format for the default locale using a
   * specified currency.
   *
   * @param currencyData currency data to use
   * @return a <code>NumberFormat</code> capable of producing and consuming
   *         currency format for the default locale
   */
  public static NumberFormat getCurrencyFormat(CurrencyData currencyData) {
    return new NumberFormat(defaultNumberConstants.currencyPattern(),
        currencyData, false);
  }

  /**
   * Provides the standard currency format for the default locale using a
   * specified currency.
   *
   * @param currencyCode valid currency code, as defined in
   *     com.google.gwt.i18n.client.constants.CurrencyCodeMapConstants.properties
   * @return a <code>NumberFormat</code> capable of producing and consuming
   *         currency format for the default locale
   * @throws IllegalArgumentException if the currency code is unknown
   */
  public static NumberFormat getCurrencyFormat(String currencyCode) {
    // TODO(jat): consider caching values per currency code.
    return new NumberFormat(defaultNumberConstants.currencyPattern(),
        lookupCurrency(currencyCode), false);
  }

  /**
   * Provides the standard decimal format for the default locale.
   *
   * @return a <code>NumberFormat</code> capable of producing and consuming
   *         decimal format for the default locale
   */
  public static NumberFormat getDecimalFormat() {
    if (cachedDecimalFormat == null) {
      cachedDecimalFormat = new NumberFormat(
          defaultNumberConstants.decimalPattern(),
          CurrencyList.get().getDefault(), false);
    }
    return cachedDecimalFormat;
  }

  /**
   * Gets a <code>NumberFormat</code> instance for the default locale using
   * the specified pattern and the default currencyCode.
   *
   * @param pattern pattern for this formatter
   * @return a NumberFormat instance
   * @throws IllegalArgumentException if the specified pattern is invalid
   */
  public static NumberFormat getFormat(String pattern) {
    return new NumberFormat(pattern, CurrencyList.get().getDefault(), true);
  }

  /**
   * Gets a custom <code>NumberFormat</code> instance for the default locale
   * using the specified pattern and currency code.
   *
   * @param pattern pattern for this formatter
   * @param currencyData currency data
   * @return a NumberFormat instance
   * @throws IllegalArgumentException if the specified pattern is invalid
   */
  public static NumberFormat getFormat(String pattern,
      CurrencyData currencyData) {
    return new NumberFormat(pattern, currencyData, true);
  }

  /**
   * Gets a custom <code>NumberFormat</code> instance for the default locale
   * using the specified pattern and currency code.
   *
   * @param pattern pattern for this formatter
   * @param currencyCode international currency code
   * @return a NumberFormat instance
   * @throws IllegalArgumentException if the specified pattern is invalid
   *     or the currency code is unknown
   */
  public static NumberFormat getFormat(String pattern, String currencyCode) {
    return new NumberFormat(pattern, lookupCurrency(currencyCode), true);
  }

  /**
   * Provides the standard percent format for the default locale.
   *
   * @return a <code>NumberFormat</code> capable of producing and consuming
   *         percent format for the default locale
   */
  public static NumberFormat getPercentFormat() {
    if (cachedPercentFormat == null) {
      cachedPercentFormat = new NumberFormat(
          defaultNumberConstants.percentPattern(),
          CurrencyList.get().getDefault(), false);
    }
    return cachedPercentFormat;
  }

  /**
   * Provides the standard scientific format for the default locale.
   *
   * @return a <code>NumberFormat</code> capable of producing and consuming
   *         scientific format for the default locale
   */
  public static NumberFormat getScientificFormat() {
    if (cachedScientificFormat == null) {
      cachedScientificFormat = new NumberFormat(
          defaultNumberConstants.scientificPattern(),
          CurrencyList.get().getDefault(), false);
    }
    return cachedScientificFormat;
  }

  /**
   * Specify whether all new NumberFormat instances will use latin digits
   * and related characters rather than the localized ones.
   *
   * @param useLatinDigits true if latin digits/etc should be used, false if
   *    localized digits/etc should be used.
   */
  public static void setForcedLatinDigits(boolean useLatinDigits) {
    // Invalidate cached formats if changing
    if (useLatinDigits != forcedLatinDigits()) {
      cachedCurrencyFormat = null;
      cachedDecimalFormat = null;
      cachedPercentFormat = null;
      cachedScientificFormat = null;
    }
    if (useLatinDigits) {
      if (latinNumberConstants == null) {
        latinNumberConstants = createLatinNumberConstants(
            localizedNumberConstants);
      }
      defaultNumberConstants = latinNumberConstants;
    } else {
      defaultNumberConstants = localizedNumberConstants;
    }
  }

  /**
   * Create a delocalized NumberConstants instance from a localized one.
   *
   * @param orig localized NumberConstants instance
   * @return NumberConstants instance using latin digits/etc
   */
  protected static NumberConstants createLatinNumberConstants(
      final NumberConstants orig) {
    final String groupingSeparator = remapSeparator(
        orig.groupingSeparator());
    final String decimalSeparator = remapSeparator(
        orig.decimalSeparator());
    final String monetaryGroupingSeparator = remapSeparator(
        orig.monetaryGroupingSeparator());
    final String monetarySeparator = remapSeparator(
        orig.monetarySeparator());
    return new NumberConstants() {
      public String currencyPattern() {
        return orig.currencyPattern();
      }

      public String decimalPattern() {
        return orig.decimalPattern();
      }

      public String decimalSeparator() {
        return decimalSeparator;
      }

      public String defCurrencyCode() {
        return orig.defCurrencyCode();
      }

      public String exponentialSymbol() {
        return orig.exponentialSymbol();
      }

      public String groupingSeparator() {
        return groupingSeparator;
      }

      public String infinity() {
        return orig.infinity();
      }

      public String minusSign() {
        return orig.minusSign();
      }

      public String monetaryGroupingSeparator() {
        return monetaryGroupingSeparator;
      }

      public String monetarySeparator() {
        return monetarySeparator;
      }

      public String notANumber() {
        return orig.notANumber();
      }

      public String percent() {
        return orig.percent();
      }

      public String percentPattern() {
        return orig.percentPattern();
      }

      public String perMill() {
        return orig.perMill();
      }

      public String plusSign() {
        return orig.plusSign();
      }

      public String scientificPattern() {
        return orig.scientificPattern();
      }

      public String zeroDigit() {
        return "0";
      }
    };
  }

  /**
   * Remap a localized separator to an equivalent latin one.
   *
   * @param separator
   * @return delocalized separator character
   */
  protected static String remapSeparator(String separator) {
    char ch = separator.length() > 0 ? separator.charAt(0) : 0xFFFF;
    if (LOCALIZED_DOT_EQUIVALENTS.indexOf(ch) >= 0) {
      return ".";
    }
    if (LOCALIZED_COMMA_EQUIVALENTS.indexOf(ch) >= 0) {
      return ",";
    }
    return "\u00A0";
  }

  /**
   * Appends a scaled string representation to a buffer, returning the scale
   * (which is the number of places to the right of the end of the string the
   * decimal point should be moved -- i.e., 3.5 would be added to the buffer
   * as "35" and a returned scale of -1).
   *
   * @param buf
   * @param val
   * @return scale to apply to the result
   */
  // @VisibleForTesting
  static int toScaledString(StringBuilder buf, double val) {
    int startLen = buf.length();
    buf.append(toPrecision(val, 20));
    int scale = 0;

    // remove exponent if present, adjusting scale
    int expIdx = buf.indexOf("e", startLen);
    if (expIdx < 0) {
      expIdx = buf.indexOf("E", startLen);
    }
    if (expIdx >= 0) {
      int expDigits = expIdx + 1;
      if (expDigits < buf.length() && buf.charAt(expDigits) == '+') {
        ++expDigits;
      }
      if (expDigits < buf.length()) {
        scale = Integer.parseInt(buf.substring(expDigits));
      }
      buf.delete(expIdx, buf.length());
    }

    // remove decimal point if present, adjusting scale
    int dot = buf.indexOf(".", startLen);
    if (dot >= 0) {
      buf.deleteCharAt(dot);
      scale -= buf.length() - dot;
    }
    return scale;
  }

  /**
   * Lookup a currency code.
   *
   * @param currencyCode ISO4217 currency code
   * @return a CurrencyData instance
   * @throws IllegalArgumentException if the currency code is unknown
   */
  private static CurrencyData lookupCurrency(String currencyCode) {
    CurrencyData currencyData = CurrencyList.get().lookup(currencyCode);
    if (currencyData == null) {
      throw new IllegalArgumentException("Currency code " + currencyCode
          + " is unkown in locale "
          + LocaleInfo.getCurrentLocale().getLocaleName());
    }
    return currencyData;
  }

  /**
   * Convert a double to a string with {@code digits} precision.  The resulting
   * string may still be in exponential notation.
   *
   * @param d double value
   * @param digits number of digits of precision to include
   * @return non-localized string representation of {@code d}
   */
  private static native String toPrecision(double d, int digits) /*-{
    return d.toPrecision(digits);
  }-*/;

  /**
   * The currency code.
   */
  private final String currencyCode;

  /**
   * Currency symbol to use.
   */
  private final String currencySymbol;

  /**
   * Forces the decimal separator to always appear in a formatted number.
   */
  private boolean decimalSeparatorAlwaysShown = false;

  /**
   * The number of digits between grouping separators in the integer portion of
   * a number.
   */
  private int groupingSize = 3;

  private boolean isCurrencyFormat = false;

  private int maximumFractionDigits = 3; // invariant, >= minFractionDigits.

  private int maximumIntegerDigits = 40;
  private int minExponentDigits;
  private int minimumFractionDigits = 0;
  private int minimumIntegerDigits = 1;

  // The multiplier for use in percent, per mille, etc.
  private int multiplier = 1;

  private String negativePrefix = "-";

  private String negativeSuffix = "";

  // Locale specific symbol collection.
  private final NumberConstants numberConstants;

  // The pattern to use for formatting and parsing.
  private final String pattern;

  private String positivePrefix = "";

  private String positiveSuffix = "";

  // True to force the use of exponential (i.e. scientific) notation.
  private boolean useExponentialNotation = false;

  /**
   * Holds the current exponent during one call to
   * {@link #format(boolean, StringBuilder, int)}.
   */
  private transient int exponent;

  /**
   * Holds the current decimal position during one call to
   * {@link #format(boolean, StringBuilder, int)}.
   */
  private transient int decimalPosition;

  /**
   * Holds the current digits length during one call to
   * {@link #format(boolean, StringBuilder, int)}.
   */
  private transient int digitsLength;

  /**
   * Constructs a format object based on the specified settings.
   *
   * @param numberConstants the locale-specific number constants to use for this
   *          format -- **NOTE** subclasses passing their own instance here
   *          should pay attention to {@link #forcedLatinDigits()} and remap
   *          localized symbols using
   *          {@link #createLatinNumberConstants(NumberConstants)}
   * @param pattern pattern that specify how number should be formatted
   * @param cdata currency data that should be used
   * @param userSuppliedPattern true if the pattern was supplied by the user
   */
  protected NumberFormat(NumberConstants numberConstants, String pattern, CurrencyData cdata,
      boolean userSuppliedPattern) {
    if (cdata == null) {
      throw new IllegalArgumentException("Unknown currency code");
    }
    this.numberConstants = numberConstants;
    this.pattern = pattern;
    currencyCode = cdata.getCurrencyCode();
    currencySymbol = cdata.getCurrencySymbol();

    // TODO: handle per-currency flags, such as symbol prefix/suffix and spacing
    parsePattern(this.pattern);
    if (!userSuppliedPattern && isCurrencyFormat) {
      minimumFractionDigits = cdata.getDefaultFractionDigits();
      maximumFractionDigits = minimumFractionDigits;
    }
  }

  /**
   * Constructs a format object for the default locale based on the specified
   * settings.
   *
   * @param pattern pattern that specify how number should be formatted
   * @param cdata currency data that should be used
   * @param userSuppliedPattern true if the pattern was supplied by the user
   */
  protected NumberFormat(String pattern, CurrencyData cdata, boolean userSuppliedPattern) {
    this(defaultNumberConstants, pattern, cdata, userSuppliedPattern);
  }

  /**
   * This method formats a double to produce a string.
   *
   * @param number The double to format
   * @return the formatted number string
   */
  public String format(double number) {
    if (Double.isNaN(number)) {
      return numberConstants.notANumber();
    }
    boolean isNegative = ((number < 0.0)
        || (number == 0.0 && 1 / number < 0.0));
    if (isNegative) {
      number = -number;
    }
    StringBuilder buf = new StringBuilder();
    if (Double.isInfinite(number)) {
      buf.append(isNegative ? negativePrefix : positivePrefix);
      buf.append(numberConstants.infinity());
      buf.append(isNegative ? negativeSuffix : positiveSuffix);
      return buf.toString();
    }
    number *= multiplier;
    int scale = toScaledString(buf, number);

    // pre-round value to deal with .15 being represented as .149999... etc
    // check at 3 more digits than will be required in the output
    int preRound = buf.length() + scale + maximumFractionDigits + 3;
    if (preRound > 0 && preRound < buf.length()
        && buf.charAt(preRound) == '9') {
      propagateCarry(buf, preRound - 1);
      scale += buf.length() - preRound;
      buf.delete(preRound, buf.length());
    }

    format(isNegative, buf, scale);
    return buf.toString();
  }

  /**
   * This method formats a Number to produce a string.
   * <p>
   * Any {@link Number} which is not a {@link BigDecimal}, {@link BigInteger},
   * or {@link Long} instance is formatted as a {@code double} value.
   *
   * @param number The Number instance to format
   * @return the formatted number string
   */
  public String format(Number number) {
    if (number instanceof BigDecimal) {
      BigDecimal bigDec = (BigDecimal) number;
      boolean isNegative = bigDec.signum() < 0;
      if (isNegative) {
        bigDec = bigDec.negate();
      }
      bigDec = bigDec.multiply(BigDecimal.valueOf(multiplier));
      StringBuilder buf = new StringBuilder();
      buf.append(bigDec.unscaledValue().toString());
      format(isNegative, buf, -bigDec.scale());
      return buf.toString();
    } else if (number instanceof BigInteger) {
      BigInteger bigInt = (BigInteger) number;
      boolean isNegative = bigInt.signum() < 0;
      if (isNegative) {
        bigInt = bigInt.negate();
      }
      bigInt = bigInt.multiply(BigInteger.valueOf(multiplier));
      StringBuilder buf = new StringBuilder();
      buf.append(bigInt.toString());
      format(isNegative, buf, 0);
      return buf.toString();
    } else if (number instanceof Long) {
      return format(number.longValue(), 0);
    } else {
      return format(number.doubleValue());
    }
  }

  /**
   * Returns the pattern used by this number format.
   */
  public String getPattern() {
    return pattern;
  }

  /**
   * Parses text to produce a numeric value. A {@link NumberFormatException} is
   * thrown if either the text is empty or if the parse does not consume all
   * characters of the text.
   *
   * @param text the string being parsed
   * @return a double value representing the parsed number
   * @throws NumberFormatException if the entire text could not be converted
   *     into a double
   */
  public double parse(String text) throws NumberFormatException {
    int[] pos = {0};
    double result = parse(text, pos);
    if (pos[0] == 0 || pos[0] != text.length()) {
      throw new NumberFormatException(text);
    }
    return result;
  }

  /**
   * Parses text to produce a numeric value.
   *
   * <p>
   * The method attempts to parse text starting at the index given by pos. If
   * parsing succeeds, then the index of <code>pos</code> is updated to the
   * index after the last character used (parsing does not necessarily use all
   * characters up to the end of the string), and the parsed number is returned.
   * The updated <code>pos</code> can be used to indicate the starting point
   * for the next call to this method. If an error occurs, then the index of
   * <code>pos</code> is not changed.
   * </p>
   *
   * @param text the string to be parsed
   * @param inOutPos position to pass in and get back
   * @return a double value representing the parsed number
   * @throws NumberFormatException if the text segment could not be converted
   *     into a double
   */
  public double parse(String text, int[] inOutPos) throws NumberFormatException {
    double ret = 0.0;

    boolean gotPositivePrefix = text.startsWith(positivePrefix, inOutPos[0]);
    boolean gotNegativePrefix = text.startsWith(negativePrefix, inOutPos[0]);
    boolean gotPositiveSuffix = text.endsWith(positiveSuffix);
    boolean gotNegativeSuffix = text.endsWith(negativeSuffix);
    boolean gotPositive = gotPositivePrefix && gotPositiveSuffix;
    boolean gotNegative = gotNegativePrefix && gotNegativeSuffix;

    // Handle conflicts where we get both patterns, which usually
    // happens when one is a prefix of the other (such as the positive
    // pattern having empty prefix/suffixes).
    if (gotPositive && gotNegative) {
      if (positivePrefix.length() > negativePrefix.length()) {
        gotNegative = false;
      } else if (positivePrefix.length() < negativePrefix.length()) {
        gotPositive = false;
      } else if (positiveSuffix.length() > negativeSuffix.length()) {
        gotNegative = false;
      } else if (positiveSuffix.length() < negativeSuffix.length()) {
        gotPositive = false;
      } else {
        // can't tell patterns apart, must be positive
        gotNegative = false;
      }
    } else if (!gotPositive && !gotNegative) {
      throw new NumberFormatException(text
          + " does not have either positive or negative affixes");
    }

    // Contains just the value to parse, stripping any prefix or suffix
    String valueOnly = null;
    if (gotPositive) {
      inOutPos[0] += positivePrefix.length();
      valueOnly = text.substring(inOutPos[0],
          text.length() - positiveSuffix.length());
    } else {
      inOutPos[0] += negativePrefix.length();
      valueOnly = text.substring(inOutPos[0],
          text.length() - negativeSuffix.length());
    }

    // Process digits or special values, and find decimal position.
    if (valueOnly.equals(numberConstants.infinity())) {
      inOutPos[0] += numberConstants.infinity().length();
      ret = Double.POSITIVE_INFINITY;
    } else if (valueOnly.equals(numberConstants.notANumber())) {
      inOutPos[0] += numberConstants.notANumber().length();
      ret = Double.NaN;
    } else {
      int[] tempPos = {0};
      ret = parseNumber(valueOnly, tempPos);
      inOutPos[0] += tempPos[0];
    }

    // Check for suffix.
    if (gotPositive) {
      inOutPos[0] += positiveSuffix.length();
    } else if (gotNegative) {
      inOutPos[0] += negativeSuffix.length();
    }

    if (gotNegative) {
      ret = -ret;
    }

    return ret;
  }

  /**
   * Format a number with its significant digits already represented in string
   * form.  This is done so both double and BigInteger/Decimal formatting can
   * share code without requiring all users to pay the code size penalty for
   * BigDecimal/etc.
   * <p>
   * Example values passed in:
   * <ul>
   * <li>-13e2
   * <br>{@code isNegative=true, digits="13", scale=2}
   * <li>3.14158
   * <br>{@code isNegative=false, digits="314158", scale=-5}
   * <li>.0001
   * <br>{@code isNegative=false, digits="1" ("0001" would be ok), scale=-4}
   * </ul>
   *
   * @param isNegative true if the value to be formatted is negative
   * @param digits a StringBuilder containing just the significant digits in
   *     the value to be formatted, the formatted result will be left here
   * @param scale the number of places to the right the decimal point should
   *     be moved in the digit string -- negative means the value contains
   *     fractional digits
   */
  protected void format(boolean isNegative, StringBuilder digits, int scale) {
    char decimalSeparator;
    char groupingSeparator;
    if (isCurrencyFormat) {
      decimalSeparator = numberConstants.monetarySeparator().charAt(0);
      groupingSeparator = numberConstants.monetaryGroupingSeparator().charAt(0);
    } else {
      decimalSeparator = numberConstants.decimalSeparator().charAt(0);
      groupingSeparator = numberConstants.groupingSeparator().charAt(0);
    }

    // Set these transient fields, which will be adjusted/used by the routines
    // called in this method.
    exponent = 0;
    digitsLength = digits.length();
    decimalPosition = digitsLength + scale;

    boolean useExponent = this.useExponentialNotation;
    int currentGroupingSize = this.groupingSize;
    if (decimalPosition > 1024) {
      // force really large numbers to be in exponential form
      useExponent = true;
    }

    if (useExponent) {
      computeExponent(digits);
    }
    processLeadingZeros(digits);
    roundValue(digits);
    insertGroupingSeparators(digits, groupingSeparator, currentGroupingSize);
    adjustFractionDigits(digits);
    addZeroAndDecimal(digits, decimalSeparator);
    if (useExponent) {
      addExponent(digits);
      // the above call has invalidated digitsLength == digits.length()
    }
    char zeroChar = numberConstants.zeroDigit().charAt(0);
    if (zeroChar != '0') {
      localizeDigits(digits, zeroChar);
    }

    // add prefix/suffix
    digits.insert(0, isNegative ? negativePrefix : positivePrefix);
    digits.append(isNegative ? negativeSuffix : positiveSuffix);
  }

  /**
   * Parses text to produce a numeric value. A {@link NumberFormatException} is
   * thrown if either the text is empty or if the parse does not consume all
   * characters of the text.
   *
   * param text the string to be parsed
   * return a parsed number value, which may be a Double, BigInteger, or
   *     BigDecimal
   * throws NumberFormatException if the text segment could not be converted
   *     into a number
   */
//  public Number parseBig(String text) throws NumberFormatException {
//    // TODO(jat): implement
//    return Double.valueOf(parse(text));
//  }

  /**
   * Parses text to produce a numeric value.
   *
   * <p>
   * The method attempts to parse text starting at the index given by pos. If
   * parsing succeeds, then the index of <code>pos</code> is updated to the
   * index after the last character used (parsing does not necessarily use all
   * characters up to the end of the string), and the parsed number is returned.
   * The updated <code>pos</code> can be used to indicate the starting point
   * for the next call to this method. If an error occurs, then the index of
   * <code>pos</code> is not changed.
   * </p>
   *
   * param text the string to be parsed
   * pparam inOutPos position to pass in and get back
   * return a parsed number value, which may be a Double, BigInteger, or
   *     BigDecimal
   * throws NumberFormatException if the text segment could not be converted
   *     into a number
   */
//  public Number parseBig(String text, int[] inOutPos)
//      throws NumberFormatException {
//    // TODO(jat): implement
//    return Double.valueOf(parse(text, inOutPos));
//  }

  /**
   * Format a possibly scaled long value.
   *
   * @param value value to format
   * @param scale the number of places to the right the decimal point should
   *     be moved in the digit string -- negative means the value contains
   *     fractional digits
   * @return formatted value
   */
  protected String format(long value, int scale) {
    boolean isNegative = value < 0;
    if (isNegative) {
      value = -value;
    }
    value *= multiplier;
    StringBuilder buf = new StringBuilder();
    buf.append(String.valueOf(value));
    format(isNegative, buf, scale);
    return buf.toString();
  }

  /**
   * Returns the number of digits between grouping separators in the integer
   * portion of a number.
   */
  protected int getGroupingSize() {
    return groupingSize;
  }

  /**
   * Returns the prefix to use for negative values.
   */
  protected String getNegativePrefix() {
    return negativePrefix;
  }

  /**
   * Returns the suffix to use for negative values.
   */
  protected String getNegativeSuffix() {
    return negativeSuffix;
  }

  /**
   * Returns the NumberConstants instance for this formatter.
   */
  protected NumberConstants getNumberConstants() {
    return numberConstants;
  }

  /**
   * Returns the prefix to use for positive values.
   */
  protected String getPositivePrefix() {
    return positivePrefix;
  }

  /**
   * Returns the suffix to use for positive values.
   */
  protected String getPositiveSuffix() {
    return positiveSuffix;
  }

  /**
   * Returns true if the decimal separator should always be shown.
   */
  protected boolean isDecimalSeparatorAlwaysShown() {
    return decimalSeparatorAlwaysShown;
  }

  /**
   * Add exponent suffix.
   *
   * @param digits
   */
  private void addExponent(StringBuilder digits) {
    digits.append(numberConstants.exponentialSymbol());
    if (exponent < 0) {
      exponent = -exponent;
      digits.append(numberConstants.minusSign());
    }
    String exponentDigits = String.valueOf(exponent);
    for (int i = exponentDigits.length(); i < minExponentDigits; ++i) {
      digits.append('0');
    }
    digits.append(exponentDigits);
  }

  /**
   * @param digits
   * @param decimalSeparator
   */
  private void addZeroAndDecimal(StringBuilder digits, char decimalSeparator) {
    // add zero and decimal point if required
    if (digitsLength == 0) {
      digits.insert(0, '0');
      ++decimalPosition;
      ++digitsLength;
    }
    if (decimalPosition < digitsLength || decimalSeparatorAlwaysShown) {
      digits.insert(decimalPosition, decimalSeparator);
      ++digitsLength;
    }
  }

  /**
   * Adjust the fraction digits, adding trailing zeroes if necessary or removing
   * excess trailing zeroes.
   *
   * @param digits
   */
  private void adjustFractionDigits(StringBuilder digits) {
    // adjust fraction digits as required
    int requiredDigits = decimalPosition + minimumFractionDigits;
    if (digitsLength < requiredDigits) {
      // add trailing zeros
      while (digitsLength < requiredDigits) {
        digits.append('0');
        ++digitsLength;
      }
    } else {
      // remove excess trailing zeros
      int toRemove = decimalPosition + maximumFractionDigits;
      if (toRemove > digitsLength) {
        toRemove = digitsLength;
      }
      while (toRemove > requiredDigits
          && digits.charAt(toRemove - 1) == '0') {
        --toRemove;
      }
      if (toRemove < digitsLength) {
        digits.delete(toRemove, digitsLength);
        digitsLength = toRemove;
      }
    }
  }

  /**
   * Compute the exponent to use and adjust decimal position if we are using
   * exponential notation.
   *
   * @param digits
   */
  private void computeExponent(StringBuilder digits) {
    // always trim leading zeros
    int strip = 0;
    while (strip < digitsLength - 1 && digits.charAt(strip) == '0') {
      ++strip;
    }
    if (strip > 0) {
      digits.delete(0, strip);
      digitsLength -= strip;
      exponent -= strip;
    }

    // decimal should wind up between minimum & maximumIntegerDigits
    if (maximumIntegerDigits > minimumIntegerDigits
        && maximumIntegerDigits > 0) {
      // in this case, the exponent should be a multiple of
      // maximumIntegerDigits and 1 <= decimal <= maximumIntegerDigits
      exponent += decimalPosition - 1;
      int remainder = exponent % maximumIntegerDigits;
      if (remainder < 0) {
        remainder += maximumIntegerDigits;
      }
      decimalPosition = remainder + 1;
      exponent -= remainder;
    } else {
      exponent += decimalPosition - minimumIntegerDigits;
      decimalPosition = minimumIntegerDigits;
    }

    // special-case 0 to have an exponent of 0
    if (digitsLength == 1 && digits.charAt(0) == '0') {
      exponent = 0;
      decimalPosition = minimumIntegerDigits;
    }
  }

  /**
   * This method return the digit that represented by current character, it
   * could be either '0' to '9', or a locale specific digit.
   *
   * @param ch character that represents a digit
   * @return the digit value
   */
  private int getDigit(char ch) {
    if ('0' <= ch && ch <= '0' + 9) {
      return (ch - '0');
    } else {
      char zeroChar = numberConstants.zeroDigit().charAt(0);
      return ((zeroChar <= ch && ch <= zeroChar + 9) ? (ch - zeroChar) : -1);
    }
  }

  /**
   * Insert grouping separators if needed.
   *
   * @param digits
   * @param groupingSeparator
   * @param g
   */
  private void insertGroupingSeparators(StringBuilder digits,
      char groupingSeparator, int g) {
    if (g > 0) {
      for (int i = g; i < decimalPosition; i += g + 1) {
        digits.insert(decimalPosition - i, groupingSeparator);
        ++decimalPosition;
        ++digitsLength;
      }
    }
  }

  /**
   * Replace locale-independent digits with locale-specific ones.
   *
   * @param digits StringBuilder containing formatted number
   * @param zero locale-specific zero character -- the rest of the digits must
   *     be consecutive
   */
  private void localizeDigits(StringBuilder digits, char zero) {
    // don't use digitsLength since we may have added an exponent
    int n = digits.length();
    for (int i = 0; i < n; ++i) {
      char ch = digits.charAt(i);
      if (ch >= '0' && ch <= '9') {
        digits.setCharAt(i, (char) (ch - '0' + zero));
      }
    }
  }

  /**
   * This method parses affix part of pattern.
   *
   * @param pattern pattern string that need to be parsed
   * @param start start position to parse
   * @param affix store the parsed result
   * @param inNegativePattern true if we are parsing the negative pattern and
   *     therefore only care about the prefix and suffix
   * @return how many characters parsed
   */
  private int parseAffix(String pattern, int start, StringBuffer affix,
      boolean inNegativePattern) {
    affix.delete(0, affix.length());
    boolean inQuote = false;
    int len = pattern.length();

    for (int pos = start; pos < len; ++pos) {
      char ch = pattern.charAt(pos);
      if (ch == QUOTE) {
        if ((pos + 1) < len && pattern.charAt(pos + 1) == QUOTE) {
          ++pos;
          affix.append("'"); // 'don''t'
        } else {
          inQuote = !inQuote;
        }
        continue;
      }

      if (inQuote) {
        affix.append(ch);
      } else {
        switch (ch) {
          case PATTERN_DIGIT:
          case PATTERN_ZERO_DIGIT:
          case PATTERN_GROUPING_SEPARATOR:
          case PATTERN_DECIMAL_SEPARATOR:
          case PATTERN_SEPARATOR:
            return pos - start;
          case CURRENCY_SIGN:
            isCurrencyFormat = true;
            if ((pos + 1) < len && pattern.charAt(pos + 1) == CURRENCY_SIGN) {
              ++pos;
              affix.append(currencyCode);
            } else {
              affix.append(currencySymbol);
            }
            break;
          case PATTERN_PERCENT:
            if (!inNegativePattern) {
              if (multiplier != 1) {
                throw new IllegalArgumentException(
                    "Too many percent/per mille characters in pattern \""
                    + pattern + '"');
              }
              multiplier = 100;
            }
            affix.append(numberConstants.percent());
            break;
          case PATTERN_PER_MILLE:
            if (!inNegativePattern) {
              if (multiplier != 1) {
                throw new IllegalArgumentException(
                    "Too many percent/per mille characters in pattern \""
                    + pattern + '"');
              }
              multiplier = 1000;
            }
            affix.append(numberConstants.perMill());
            break;
          case PATTERN_MINUS:
            affix.append("-");
            break;
          default:
            affix.append(ch);
        }
      }
    }
    return len - start;
  }

  /**
   * This function parses a "localized" text into a <code>double</code>. It
   * needs to handle locale specific decimal, grouping, exponent and digit.
   *
   * @param text the text that need to be parsed
   * @param pos in/out parsing position. in case of failure, this shouldn't be
   *          changed
   * @return double value, could be 0.0 if nothing can be parsed
   */
  private double parseNumber(String text, int[] pos) {
    double ret;
    boolean sawDecimal = false;
    boolean sawExponent = false;
    boolean sawDigit = false;
    int scale = 1;
    String decimal = isCurrencyFormat ? numberConstants.monetarySeparator()
        : numberConstants.decimalSeparator();
    String grouping = isCurrencyFormat
        ? numberConstants.monetaryGroupingSeparator()
        : numberConstants.groupingSeparator();
    String exponentChar = numberConstants.exponentialSymbol();

    StringBuffer normalizedText = new StringBuffer();
    for (; pos[0] < text.length(); ++pos[0]) {
      char ch = text.charAt(pos[0]);
      int digit = getDigit(ch);
      if (digit >= 0 && digit <= 9) {
        normalizedText.append((char) (digit + '0'));
        sawDigit = true;
      } else if (ch == decimal.charAt(0)) {
        if (sawDecimal || sawExponent) {
          break;
        }
        normalizedText.append('.');
        sawDecimal = true;
      } else if (ch == grouping.charAt(0)) {
        if (sawDecimal || sawExponent) {
          break;
        }
        continue;
      } else if (ch == exponentChar.charAt(0)) {
        if (sawExponent) {
          break;
        }
        normalizedText.append('E');
        sawExponent = true;
      } else if (ch == '+' || ch == '-') {
        normalizedText.append(ch);
      } else if (ch == numberConstants.percent().charAt(0)) {
        if (scale != 1) {
          break;
        }
        scale = 100;
        if (sawDigit) {
          ++pos[0];
          break;
        }
      } else if (ch == numberConstants.perMill().charAt(0)) {
        if (scale != 1) {
          break;
        }
        scale = 1000;
        if (sawDigit) {
          ++pos[0];
          break;
        }
      } else {
        break;
      }
    }

    // parseDouble could throw NumberFormatException, rethrow with correct text.
    try {
      ret = Double.parseDouble(normalizedText.toString());
    } catch (NumberFormatException e) {
      throw new NumberFormatException(text);
    }
    ret = ret / scale;
    return ret;
  }

  /**
   * Method parses provided pattern, result is stored in member variables.
   *
   * @param pattern
   */
  private void parsePattern(String pattern) {
    int pos = 0;
    StringBuffer affix = new StringBuffer();

    pos += parseAffix(pattern, pos, affix, false);
    positivePrefix = affix.toString();
    pos += parseTrunk(pattern, pos, false);
    pos += parseAffix(pattern, pos, affix, false);
    positiveSuffix = affix.toString();

    if (pos < pattern.length() && pattern.charAt(pos) == PATTERN_SEPARATOR) {
      ++pos;
      pos += parseAffix(pattern, pos, affix, true);
      negativePrefix = affix.toString();
      // the negative pattern is only used for prefix/suffix
      pos += parseTrunk(pattern, pos, true);
      pos += parseAffix(pattern, pos, affix, true);
      negativeSuffix = affix.toString();
    } else {
      negativePrefix = numberConstants.minusSign() + positivePrefix;
      negativeSuffix = positiveSuffix;
    }
  }

  /**
   * This method parses the trunk part of a pattern.
   *
   * @param pattern pattern string that need to be parsed
   * @param start where parse started
   * @param ignorePattern true if we are only parsing this for length
   *     and correctness, such as in the negative portion of the pattern
   * @return how many characters parsed
   */
  private int parseTrunk(String pattern, int start, boolean ignorePattern) {
    int decimalPos = -1;
    int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
    byte groupingCount = -1;

    int len = pattern.length();
    int pos = start;
    boolean loop = true;
    for (; (pos < len) && loop; ++pos) {
      char ch = pattern.charAt(pos);
      switch (ch) {
        case PATTERN_DIGIT:
          if (zeroDigitCount > 0) {
            ++digitRightCount;
          } else {
            ++digitLeftCount;
          }
          if (groupingCount >= 0 && decimalPos < 0) {
            ++groupingCount;
          }
          break;
        case PATTERN_ZERO_DIGIT:
          if (digitRightCount > 0) {
            throw new IllegalArgumentException("Unexpected '0' in pattern \""
                + pattern + '"');
          }
          ++zeroDigitCount;
          if (groupingCount >= 0 && decimalPos < 0) {
            ++groupingCount;
          }
          break;
        case PATTERN_GROUPING_SEPARATOR:
          groupingCount = 0;
          break;
        case PATTERN_DECIMAL_SEPARATOR:
          if (decimalPos >= 0) {
            throw new IllegalArgumentException(
                "Multiple decimal separators in pattern \"" + pattern + '"');
          }
          decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
          break;
        case PATTERN_EXPONENT:
          if (!ignorePattern) {
            if (useExponentialNotation) {
              throw new IllegalArgumentException("Multiple exponential "
                  + "symbols in pattern \"" + pattern + '"');
            }
            useExponentialNotation = true;
            minExponentDigits = 0;
          }

          // Use lookahead to parse out the exponential part
          // of the pattern, then jump into phase 2.
          while ((pos + 1) < len
              && pattern.charAt(pos + 1) == PATTERN_ZERO_DIGIT) {
            ++pos;
            if (!ignorePattern) {
              ++minExponentDigits;
            }
          }

          if (!ignorePattern && (digitLeftCount + zeroDigitCount) < 1
              || minExponentDigits < 1) {
            throw new IllegalArgumentException("Malformed exponential "
                + "pattern \"" + pattern + '"');
          }
          loop = false;
          break;
        default:
          --pos;
          loop = false;
          break;
      }
    }

    if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
      // Handle "###.###" and "###." and ".###".
      int n = decimalPos;
      if (n == 0) { // Handle ".###"
        ++n;
      }
      digitRightCount = digitLeftCount - n;
      digitLeftCount = n - 1;
      zeroDigitCount = 1;
    }

    // Do syntax checking on the digits.
    if ((decimalPos < 0 && digitRightCount > 0)
        || (decimalPos >= 0 && (decimalPos < digitLeftCount || decimalPos > (digitLeftCount + zeroDigitCount)))
        || groupingCount == 0) {
      throw new IllegalArgumentException("Malformed pattern \"" + pattern + '"');
    }

    if (ignorePattern) {
      return pos - start;
    }

    int totalDigits = digitLeftCount + zeroDigitCount + digitRightCount;

    maximumFractionDigits = (decimalPos >= 0 ? (totalDigits - decimalPos) : 0);
    if (decimalPos >= 0) {
      minimumFractionDigits = digitLeftCount + zeroDigitCount - decimalPos;
      if (minimumFractionDigits < 0) {
        minimumFractionDigits = 0;
      }
    }

    /*
     * 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 : totalDigits;
    minimumIntegerDigits = effectiveDecimalPos - digitLeftCount;
    if (useExponentialNotation) {
      maximumIntegerDigits = digitLeftCount + minimumIntegerDigits;

      // In exponential display, integer part can't be empty.
      if (maximumFractionDigits == 0 && minimumIntegerDigits == 0) {
        minimumIntegerDigits = 1;
      }
    }

    this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
    decimalSeparatorAlwaysShown = (decimalPos == 0 || decimalPos == totalDigits);

    return pos - start;
  }

  /**
   * Remove excess leading zeros or add some if we don't have enough.
   *
   * @param digits
   */
  private void processLeadingZeros(StringBuilder digits) {
    // make sure we have enough trailing zeros
    if (decimalPosition > digitsLength) {
      while (digitsLength < decimalPosition) {
        digits.append('0');
        ++digitsLength;
      }
    }

    if (!useExponentialNotation) {
      // make sure we have the right number of leading zeros
      if (decimalPosition < minimumIntegerDigits) {
        // add leading zeros
        StringBuilder prefix = new StringBuilder();
        while (decimalPosition < minimumIntegerDigits) {
          prefix.append('0');
          ++decimalPosition;
          ++digitsLength;
        }
        digits.insert(0, prefix);
      } else if (decimalPosition > minimumIntegerDigits) {
        // trim excess leading zeros
        int strip = decimalPosition - minimumIntegerDigits;
        for (int i = 0; i < strip; ++i) {
          if (digits.charAt(i) != '0') {
            strip = i;
            break;
          }
        }
        if (strip > 0) {
          digits.delete(0, strip);
          digitsLength -= strip;
          decimalPosition -= strip;
        }
      }
    }
  }

  /**
   * Propagate a carry from incrementing the {@code i+1}'th digit.
   *
   * @param digits
   * @param i digit to start incrementing
   */
  private void propagateCarry(StringBuilder digits, int i) {
    boolean carry = true;
    while (carry && i >= 0) {
      char digit = digits.charAt(i);
      if (digit == '9') {
        // set this to zero and keep going
        digits.setCharAt(i--, '0');
      } else {
        digits.setCharAt(i, (char) (digit + 1));
        carry = false;
      }
    }
    if (carry) {
      // ran off the front, prepend a 1
      digits.insert(0, '1');
      ++decimalPosition;
      ++digitsLength;
    }
  }

  /**
   * Round the value at the requested place, propagating any carry backward.
   *
   * @param digits
   */
  private void roundValue(StringBuilder digits) {
    // TODO(jat): other rounding modes?
    if (digitsLength > decimalPosition + maximumFractionDigits
        && digits.charAt(decimalPosition + maximumFractionDigits) >= '5') {
      int i = decimalPosition + maximumFractionDigits - 1;
      propagateCarry(digits, i);
    }
  }
}
