17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 1996-2014, International Business Machines Corporation and    *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.                                                *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text;
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectInputStream;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectOutputStream;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.math.BigInteger;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.AttributedCharacterIterator;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.AttributedString;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ChoiceFormat;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.Format;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParsePosition;
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.ArrayList;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashSet;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Iterator;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set;
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUConfig;
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.PatternProps;
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Utility;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter;
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.math.BigDecimal;
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.math.MathContext;
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.FixedDecimal;
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Currency;
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Currency.CurrencyUsage;
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.CurrencyAmount;
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale;
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale.Category;
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * decimal numbers. It has a variety of features designed to make it possible to parse and
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format numbers in any locale, including support for Western, Arabic, or Indic digits.
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It also supports different flavors of numbers, including integers ("123"), fixed-point
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * easily localized.
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * directly, unless you know what you are doing, since the {@link NumberFormat} factory
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * customize the format object, do something like this:
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre>
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat f = NumberFormat.getInstance(loc);
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if (f instanceof DecimalFormat) {
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * }</pre></blockquote>
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><strong>Example Usage</strong>
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Print out a number using the localized number, currency, and percent
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format for each locale.
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre>
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Locale[] locales = NumberFormat.getAvailableLocales();
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * double myNumber = -1234.56;
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat format;
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for (int j=0; j<3; ++j) {
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     System.out.println("FORMAT");
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     for (int i = 0; i < locales.length; ++i) {
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         if (locales[i].getCountry().length() == 0) {
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *            // Skip language-only locales
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *            continue;
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         }
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         System.out.print(locales[i].getDisplayName());
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         switch (j) {
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         case 0:
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *             format = NumberFormat.getInstance(locales[i]); break;
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         case 1:
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *             format = NumberFormat.getCurrencyInstance(locales[i]); break;
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         default:
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *             format = NumberFormat.getPercentInstance(locales[i]); break;
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         }
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         try {
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *             // Assume format is a DecimalFormat
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *             System.out.print(": " + ((DecimalFormat) format).toPattern()
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *                              + " -> " + form.format(myNumber));
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         } catch (Exception e) {}
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         try {
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *             System.out.println(" -> " + format.parse(form.format(myNumber)));
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         } catch (ParseException e) {}
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     }
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * }</pre></blockquote>
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Another example use getInstance(style).<br/>
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Print out a number using the localized number, currency, percent,
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * scientific, integer, iso currency, and plural currency format for each locale.
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre>
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ULocale locale = new ULocale("en_US");
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * double myNumber = 1234.56;
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     NumberFormat format = NumberFormat.getInstance(locale, j);
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     try {
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         // Assume format is a DecimalFormat
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         System.out.print(": " + ((DecimalFormat) format).toPattern()
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *                          + " -> " + form.format(myNumber));
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     } catch (Exception e) {}
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     try {
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         System.out.println(" -> " + format.parse(form.format(myNumber)));
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     } catch (ParseException e) {}
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * }</pre></blockquote>
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Patterns</h4>
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * indirectly using other API methods which manipulate aspects of the pattern, such as the
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * minimum number of integer digits.  The symbols are stored in a {@link
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern and symbols are read from ICU's locale data.
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Special Pattern Characters</h4>
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Many characters in a pattern are taken literally; they are matched during parsing
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and output unchanged during formatting.  Special characters, on the other hand, stand
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for other characters, strings, or classes of characters.  For example, the '#'
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * character is replaced by a localized digit.  Often the replacement character is the
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * same as the pattern character; in the U.S. locale, the ',' grouping character is
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * replaced by ','.  However, the replacement is still happening, and if the symbols are
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * modified, the grouping character changes.  Some special characters affect the behavior
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the formatter by their presence; for example, if the percent character is seen, then
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the value is multiplied by 100 before being displayed.
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To insert a special character in a pattern as a literal, that is, without any
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * special meaning, the character must be quoted.  There are some exceptions to this which
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are noted below.
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The characters listed here are used in non-localized patterns.  Localized patterns
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use the corresponding characters taken from this formatter's {@link
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols} object instead, and these characters lose their special status.
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Two exceptions are the currency sign and quote, which are not localized.
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote>
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *  location, localized, and meaning.">
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr bgcolor="#ccccff">
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Symbol
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Location
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Localized?
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Meaning
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>0</code>
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Digit
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>1-9</code>
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>'1' through '9' indicate rounding.
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>@</code>
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>No
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Significant digit
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>#</code>
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Digit, zero shows as absent
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>.</code>
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Decimal separator or monetary decimal separator
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>-</code>
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Minus sign
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>,</code>
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Grouping separator
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>E</code>
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Number
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Separates mantissa and exponent in scientific notation.
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         <em>Need not be quoted in prefix or suffix.</em>
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>+</code>
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Exponent
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Prefix positive exponents with localized plus sign.
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         <em>Need not be quoted in prefix or suffix.</em>
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>;</code>
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Subpattern boundary
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Separates positive and negative subpatterns
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>%</code>
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Prefix or suffix
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Multiply by 100 and show as percentage
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>&#92;u2030</code>
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Prefix or suffix
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Multiply by 1000 and show as per mille
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Prefix or suffix
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>No
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Currency sign, replaced by currency symbol.  If
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         doubled, replaced by international currency symbol.
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         If tripled, replaced by currency plural names, for example,
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         "US dollar" or "US dollars" for America.
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         If present in a pattern, the monetary decimal separator
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         is used instead of the decimal separator.
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>'</code>
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Prefix or suffix
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>No
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Used to quote special characters in a prefix or suffix,
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         for example, <code>"'#'#"</code> formats 123 to
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         <code>"#123"</code>.  To create a single quote
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *         itself, use two in a row: <code>"# o''clock"</code>.
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>*</code>
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Prefix or suffix boundary
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Yes
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>Pad escape, precedes pad character
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </table>
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote>
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix.  If there is no explicit negative subpattern, the negative subpattern is the
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * only to specify the negative prefix and suffix; the number of digits, minimal digits,
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and other characteristics are ignored in the negative subpattern. That means that
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separators, decimal separators, etc. may be set to arbitrary values, and they will
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * appear properly during formatting.  However, care must be taken that the symbols and
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * strings do not conflict, or parsing will be unreliable.  For example, either the
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be able to distinguish positive from negative values.  Another example is that the
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * decimal separator and thousands separator should be distinct characters, or parsing
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be impossible.
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The <em>grouping separator</em> is a character that separates clusters of integer
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits to make large numbers more legible.  It commonly used for thousands, but in some
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0000". There are actually two different grouping sizes: One used for the least
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant integer digits, the <em>primary grouping size</em>, and one used for all
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others, the <em>secondary grouping size</em>.  In most locales these are the same, but
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sometimes they are different. For example, if the primary grouping interval is 3, and
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separators, the interval between the last one and the end of the integer defines the
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * primary grouping size, and the interval between the last two defines the secondary
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "##,#,###,####".
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that describes the problem.
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Pattern BNF</h4>
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre>
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern    := subpattern (';' subpattern)?
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * subpattern := prefix? number exponent? suffix?
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number     := (integer ('.' fraction)?) | sigDigits
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * integer    := '#'* '0'* '0'
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction   := '0'* '#'*
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sigDigits  := '#'* '@' '@'* '#'*
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exponent   := 'E' '+'? '0'* '0'
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padSpec    := '*' padChar
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * &#32;
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Notation:
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   X*       0 or more instances of X
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   X?       0 or 1 instances of X
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   X|Y      either X or Y
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   C..D     any character from C up to D, inclusive
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   S-T      characters in S, except those in T
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre>
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The first subpattern is for positive numbers. The second (optional)
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * subpattern is for negative numbers.
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Not indicated in the BNF syntax above:
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul>
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The grouping separator ',' can occur inside the integer and sigDigits
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * elements, between any two pattern characters of that element, as long as the integer or
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sigDigits element is not followed by the exponent element.
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Two grouping intervals are recognized: That between the decimal point and the first
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * grouping symbol, and that between the first and second grouping symbols. These
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * intervals are identical in most locales, but in some locales they differ. For example,
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the pattern &quot;#,##,###&quot; formats the number 123456789 as
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * &quot;12,34,56,789&quot;.
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * prefix, before the suffix, after the suffix, or not at all.
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * increment.
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul>
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Parsing</h4>
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits, as defined by {@link UCharacter#digit}.  In addition,
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>During parsing, grouping separators are ignored.
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>For currency parsing, the formatter is able to parse every currency style formats no
3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * matter which style the formatter is constructed with.  For example, a formatter
3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parse formats such as "USD1.00" and "3.00 US dollars".
3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>null</code> and leaves the parse position unchanged.  The convenience method
3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link #parse(String)} indicates parse failure by throwing a {@link
3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * java.text.ParseException}.
3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Parsing an extremely large or small absolute value (such as 1.0E10000 or 1.0E-10000)
3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * requires huge memory allocation for representing the parsed number. Such input may expose
3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a risk of DoS attacks. To prevent huge memory allocation triggered by such inputs,
3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> internally limits of maximum decimal digits to be 1000. Thus,
3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * an input string resulting more than 1000 digits in plain decimal representation (non-exponent)
3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be treated as either overflow (positive/negative infinite) or underflow (+0.0/-0.0).
3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Formatting</h4>
3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Formatting is guided by several parameters, all of which can be specified either
3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * using a pattern or using the API.  The following description applies to formats that do
3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</a>.
3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then only the least significant digits are shown.  For example, 1997 is
3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatted as "97" if the maximum integer digits is set to 2.
3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If the number of actual integer digits is less than the <em>minimum integer
3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"
3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if the minimum integer digits is set to 5.
3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For
3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This
3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * behavior can be changed by specifying a rounding increment and a rounding mode.
3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If the number of actual fraction digits is less than the <em>minimum fraction
3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as
3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "0.1250" if the mimimum fraction digits is set to 4.
3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul>
3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><strong>Special Values</strong>
3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>NaN</code> is represented as a single character, typically
3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>&#92;uFFFD</code>.  This character is determined by the {@link
3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols} object.  This is the only value for which the prefixes and
3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffixes are not used.
3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,
3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with the positive or negative prefixes and suffixes applied.  The infinity character is
3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * determined by the {@link DecimalFormatSymbols} object.
3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <a name="sci"><h4>Scientific Notation</h4></a>
3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.
3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or through the pattern.  In a pattern, the exponent character immediately followed by
4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats
4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the number 1234 as "1.234E3".
4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul>
4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The number of digit characters after the exponent character gives the minimum
4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exponent digit count.  There is no maximum.  Negative exponents are formatted using the
4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows
4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus
4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign
4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rather than '+'.)
4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The minimum number of integer digits is achieved by adjusting the exponent.
4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if
4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * there is no maximum number of integer digits.  If there is a maximum, then the minimum
4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number of integer digits is fixed at one.
4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The most common use of this is to generate <em>engineering notation</em>, in which the
4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted
4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * using "##0.####E0" as "12.345E3".
4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>When using scientific notation, the formatter controls the digit counts using
4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant digits logic.  The maximum number of significant digits limits the total
4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number of integer and fraction digits that will be shown in the mantissa; it does not
4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the
4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * section on significant digits for more details.
4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The number of significant digits shown is determined as follows: If
4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * shown is one, and the maximum number of significant digits shown is the sum of the
4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maximum integer digits.  If this sum is zero, then all significant digits are shown.
4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If areSignificantDigitsUsed() returns true, then the significant digit counts are
4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this
4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * case, the number of integer digits is fixed at one, and there is no exponent grouping.
4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Exponential patterns may not contain grouping separators.
4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul>
4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <a name="sigdig"><h4>Significant Digits</h4></a>
4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant digits counts, or (b) integer and fraction digit counts.  Integer and
4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digit counts are described above.  When a formatter is using significant
4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits counts, the number of integer and fraction digits is not specified directly, and
4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the formatter settings for these counts are ignored.  Instead, the formatter uses
4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * however many integer and fraction digits are required to display the specified number
4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of significant digits.  Examples:
4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote>
4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <table border=0 cellspacing=3 cellpadding=0>
4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr bgcolor="#ccccff">
4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Pattern
4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Minimum significant digits
4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Maximum significant digits
4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Number
4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <th align=left>Output of format()
4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>@@@</code>
4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>3
4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>3
4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>12345
4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>12300</code>
4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>@@@</code>
4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>3
4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>3
4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>0.12345
4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>0.123</code>
4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top>
4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>@@##</code>
4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>2
4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>4
4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>3.14159
4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>3.142</code>
4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   <tr valign=top bgcolor="#eeeeff">
4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>@@##</code>
4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>2
4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>4
4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td>1.23004
4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *     <td><code>1.23</code>
4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </table>
4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote>
4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul>
4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Significant digit counts may be expressed using patterns that specify a minimum and
4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maximum number of significant digits.  These are indicated by the <code>'@'</code> and
4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'#'</code> characters.  The minimum number of significant digits is the number of
4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'@'</code> characters.  The maximum number of significant digits is the number of
4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Trailing zero digits to the right of the decimal separator are suppressed after the
4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * minimum number of significant digits have been shown.  For example, the pattern
4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or
5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"@.###"</code> are disallowed.
5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum
5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant digits counts, but may be used to position grouping separators.  For
5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of two significant digits, and a grouping size of three.
5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In order to enable significant digits formatting, use a pattern containing the
5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'@'</code> pattern character.  Alternatively, call {@link
5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In order to disable significant digits formatting, use a pattern that does not
5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * contain the <code>'@'</code> pattern character. Alternatively, call {@link
5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The number of significant digits has no effect on parsing.
5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Significant digits may be used together with exponential notation. Such patterns
5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"0.0###E0"</code>.
5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * via the API, are ignored.  If significant digits are not in use, then the signficant
5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digit counts, as set via the API, are ignored.
5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul>
5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Padding</h4>
5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specific width.  Padding may be specified either through the API or through the pattern
5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * syntax.  In a pattern the pad escape character, followed by a single pad character,
5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * causes padding to be parsed and formatted.  The pad escape character is '*' in
5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * unlocalized patterns, and can be localized using {@link
5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats
5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul>
5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>When padding is in effect, the width of the positive subpattern, including prefix
5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and suffix, determines the format width.  For example, in the pattern <code>"* #0
5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * o''clock"</code>, the format width is 10.
5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Some parameters which usually do not matter have meaning when padding is used,
5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * because the pattern width is significant with padding.  In the pattern "*
5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect
5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the grouping size or maximum integer digits, but they do affect the format width.
5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Padding may be inserted at one of four locations: before the prefix, after the
5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * prefix, before the suffix, or after the suffix.  If padding is specified in any other
5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there
5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix.
5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pad escape is the pad character. This may be any character, including a special pattern
5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * character. That is, the pad escape <em>escapes</em> the following character. If there
5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is no character after the pad escape, then the pattern is illegal.
5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul>
5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>
5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <strong>Rounding</strong>
5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,
5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The
5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment may be specified through the API or in a pattern.  To specify a
5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"
5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of
5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0.05.
5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul>
5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Rounding only affects the string produced by formatting.  It does not affect
5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsing or change any numerical values.
5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * com.ibm.icu.math.BigDecimal} documentation for a description of the modes.  Rounding
5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * increments specified in patterns use the default mode, {@link
5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Some locales use rounding in their currency formats to reflect the smallest
5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency denomination.
5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * identically to digit '0'.
5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul>
5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Synchronization</h4>
5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should
6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not access one formatter concurrently.
6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see          java.text.Format
6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see          NumberFormat
6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author       Mark Davis
6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author       Alan Liu
6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0
6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class DecimalFormat extends NumberFormat {
6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Creates a DecimalFormat using the default pattern and symbols for the default
6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * internationalization is not the main concern.
6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>To obtain standard formats for a given locale, use the factory methods on
6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat such as getNumberInstance.  These factories will return the most
6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * appropriate sub-class of NumberFormat for a given locale.
6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getInstance
6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getNumberInstance
6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getCurrencyInstance
6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getPercentInstance
6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see Category#FORMAT
6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public DecimalFormat() {
6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale def = ULocale.getDefault(Category.FORMAT);
6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String pattern = getPattern(def, 0);
6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Always applyPattern after the symbols are set
6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.symbols = new DecimalFormatSymbols(def);
6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setCurrency(Currency.getInstance(def));
6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPatternWithoutExpandAffix(pattern, false);
6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            currencyPluralInfo = new CurrencyPluralInfo(def);
6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // the exact pattern is not known until the plural count is known.
6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // so, no need to expand affix now.
6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffixAdjustWidth(null);
6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Creates a DecimalFormat from the given pattern and the symbols for the default
6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when
6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * internationalization is not the main concern.
6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>To obtain standard formats for a given locale, use the factory methods on
6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat such as getNumberInstance.  These factories will return the most
6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * appropriate sub-class of NumberFormat for a given locale.
6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pattern A non-localized pattern string.
6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @throws IllegalArgumentException if the given pattern is invalid.
6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getInstance
6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getNumberInstance
6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getCurrencyInstance
6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getPercentInstance
6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see Category#FORMAT
6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public DecimalFormat(String pattern) {
6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Always applyPattern after the symbols are set
6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ULocale def = ULocale.getDefault(Category.FORMAT);
6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.symbols = new DecimalFormatSymbols(def);
6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setCurrency(Currency.getInstance(def));
6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPatternWithoutExpandAffix(pattern, false);
6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            currencyPluralInfo = new CurrencyPluralInfo(def);
6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffixAdjustWidth(null);
6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * when you need to completely customize the behavior of the format.
6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>To obtain standard formats for a given locale, use the factory methods on
6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * adjustments to a standard format, you can modify the format returned by a
6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat factory method.
6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pattern a non-localized pattern string
6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param symbols the set of symbols to be used
6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @exception IllegalArgumentException if the given pattern is invalid
6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getInstance
6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getNumberInstance
6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getCurrencyInstance
6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#getPercentInstance
6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols
6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        createFromPatternAndSymbols(pattern, symbols);
6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Always applyPattern after the symbols are set
6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        symbols = (DecimalFormatSymbols) inputSymbols.clone();
7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setCurrencyForSymbols();
7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPatternWithoutExpandAffix(pattern, false);
7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffixAdjustWidth(null);
7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Creates a DecimalFormat from the given pattern, symbols, information used for
7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency plural format, and format style. Use this constructor when you need to
7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * completely customize the behavior of the format.
7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>To obtain standard formats for a given locale, use the factory methods on
7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat such as getInstance or getCurrencyInstance.
7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>If you need only minor adjustments to a standard format, you can modify the
7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * format returned by a NumberFormat factory method using the setters.
7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>If you want to completely customize a decimal format, using your own
7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * DecimalFormatSymbols (such as group separators) and your own information for
7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency plural formatting (such as plural rule and currency plural patterns), you
7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * can use this constructor.
7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pattern a non-localized pattern string
7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param symbols the set of symbols to be used
7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param infoInput the information used for currency plural format, including
7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency plural patterns and plural rules.
7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param style the decimal formatting style, it is one of the following values:
7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         int style) {
7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CurrencyPluralInfo info = infoInput;
7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            info = (CurrencyPluralInfo) infoInput.clone();
7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        create(pattern, symbols, info, style);
7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info,
7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int inputStyle) {
7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            createFromPatternAndSymbols(pattern, inputSymbols);
7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Always applyPattern after the symbols are set
7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            symbols = (DecimalFormatSymbols) inputSymbols.clone();
7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            currencyPluralInfo = info;
7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // the pattern used in format is not fixed until formatting, in which, the
7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // number is known and will be used to pick the right pattern based on plural
7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // count.  Here, set the pattern as the pattern of plural count == "other".
7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // For most locale, the patterns are probably the same for all plural
7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // count. If not, the right pattern need to be re-applied during format.
7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String currencyPluralPatternForOther =
7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                currencyPluralInfo.getCurrencyPluralPattern("other");
7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false);
7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setCurrencyForSymbols();
7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        style = inputStyle;
7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Creates a DecimalFormat for currency plural format from the given pattern, symbols,
7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * and style.
7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CurrencyPluralInfo info = null;
7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            info = new CurrencyPluralInfo(inputSymbols.getULocale());
7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        create(pattern, inputSymbols, info, style);
7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@inheritDoc}
7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return format(number, result, fieldPosition, false);
7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // See if number is negative.
7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // usage: isNegative(multiply(numberToBeFormatted));
7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean isNegative(double number) {
7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Detecting whether a double is negative is easy with the exception of the value
7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // -0.0. This is a double which has a zero mantissa (and exponent), but a negative
7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // sign bit. It is semantically distinct from a zero with a positive sign bit, and
7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // this distinction is important to certain kinds of computations. However, it's a
7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you
7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by
7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (number < 0.0) || (number == 0.0 && 1 / number < 0.0);
7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Rounds the number and strips of the negative sign.
8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // usage: round(multiply(numberToBeFormatted))
8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private double round(double number) {
8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean isNegative = isNegative(number);
8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isNegative)
8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = -number;
8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Apply rounding after multiplier
8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingDouble > 0.0) {
8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // number = roundingDouble
8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //    * round(number / roundingDouble, roundingMode, isNegative);
8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return round(
8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                number, roundingDouble, roundingDoubleReciprocal, roundingMode,
8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                isNegative);
8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return number;
8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Multiplies given number by multipler (if there is one) returning the new
8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // number. If there is no multiplier, returns the number passed in unchanged.
8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private double multiply(double number) {
8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (multiplier != 1) {
8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return number * multiplier;
8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return number;
8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // [Spark/CDL] The actual method to format number. If boolean value
8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // parseAttr == true, then attribute information will be recorded.
8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition,
8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                boolean parseAttr) {
8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fieldPosition.setBeginIndex(0);
8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fieldPosition.setEndIndex(0);
8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (Double.isNaN(number)) {
8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append(symbols.getNaN());
8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // [Spark/CDL] Add attribute for NaN here.
8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // result.append(symbols.getNaN());
8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (parseAttr) {
8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(),
8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             result.length());
8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addPadding(result, fieldPosition, 0, 0);
8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Do this BEFORE checking to see if value is negative or infinite and
8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // before rounding.
8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        number = multiply(number);
8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean isNegative = isNegative(number);
8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        number = round(number);
8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (Double.isInfinite(number)) {
8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int prefixLen = appendAffix(result, isNegative, true, parseAttr);
8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // [Spark/CDL] Add attribute for infinity here.
8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append(symbols.getInfinity());
8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (parseAttr) {
8767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(),
8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             result.length());
8787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int suffixLen = appendAffix(result, isNegative, false, parseAttr);
8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addPadding(result, fieldPosition, prefixLen, suffixLen);
8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return result;
8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int precision = precision(false);
8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // This is to fix rounding for scientific notation. See ticket:10542.
8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // This code should go away when a permanent fix is done for ticket:9931.
8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //
8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // This block of code only executes for scientific notation so it will not interfere with the
8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // previous fix in {@link #resetActualRounding} for fixed decimal numbers.
8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Moreover this code only runs when there is rounding to be done (precision > 0) and when the
8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // rounding mode is something other than ROUND_HALF_EVEN.
9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // This block of code does the correct rounding of number in advance so that it will fit into
9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // the number of digits indicated by precision. In this way, we avoid using the default
9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // ROUND_HALF_EVEN behavior of DigitList. For example, if number = 0.003016 and roundingMode =
9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // ROUND_DOWN and precision = 3 then after this code executes, number = 0.00301 (3 significant digits)
9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (useExponentialNotation && precision > 0 && number != 0.0 && roundingMode != BigDecimal.ROUND_HALF_EVEN) {
9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           int log10RoundingIncr = 1 - precision + (int) Math.floor(Math.log10(Math.abs(number)));
9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           double roundingIncReciprocal = 0.0;
9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           double roundingInc = 0.0;
9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           if (log10RoundingIncr < 0) {
9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert               roundingIncReciprocal =
9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                       BigDecimal.ONE.movePointRight(-log10RoundingIncr).doubleValue();
9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           } else {
9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert               roundingInc =
9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                       BigDecimal.ONE.movePointRight(log10RoundingIncr).doubleValue();
9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           }
9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           number = DecimalFormat.round(number, roundingInc, roundingIncReciprocal, roundingMode, isNegative);
9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // End fix for ticket:10542
9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // At this point we are guaranteed a nonnegative finite
9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // number.
9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized (digitList) {
9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitList.set(number, precision, !useExponentialNotation &&
9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          !areSignificantDigitsUsed());
9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(number, result, fieldPosition, isNegative, false, parseAttr);
9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This is a special function used by the CompactDecimalFormat subclass.
9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * It completes only the rounding portion of the formatting and returns
9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the resulting double. CompactDecimalFormat uses the result to compute
9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the plural form to use.
9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param number The number to format.
9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return The number rounded to the correct number of significant digits
9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * with negative sign stripped off.
9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    double adjustNumberAsInFormatting(double number) {
9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (Double.isNaN(number)) {
9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return number;
9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        number = round(multiply(number));
9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (Double.isInfinite(number)) {
9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return number;
9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return toDigitList(number).getDouble();
9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    DigitList toDigitList(double number) {
9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DigitList result = new DigitList();
9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.set(number, precision(false), false);
9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      * This is a special function used by the CompactDecimalFormat subclass
9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      * to determine if the number to be formatted is negative.
9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      *
9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      * @param number The number to format.
9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      * @return True if number is negative.
9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      * @internal
9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      * @deprecated This API is ICU internal only.
9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      */
9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     @Deprecated
9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     boolean isNumberNegative(double number) {
9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         if (Double.isNaN(number)) {
9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             return false;
9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         }
9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         return isNegative(multiply(number));
9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     }
9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Round a double value to the nearest multiple of the given rounding increment,
9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * according to the given mode. This is equivalent to rounding value/roundingInc to
9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the nearest integer, according to the given mode, and returning that integer *
9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * roundingInc. Note this is changed from the version in 2.4, since division of
9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * doubles have inaccuracies. jitterbug 1871.
9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param number
9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            the absolute value of the number to be rounded
9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param roundingInc
9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            the rounding increment
9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param roundingIncReciprocal
9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            if non-zero, is the reciprocal of rounding inc.
9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param mode
9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            a BigDecimal rounding mode
9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param isNegative
9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            true if the number to be rounded is negative
9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the absolute value of the rounded result
9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static double round(double number, double roundingInc, double roundingIncReciprocal,
9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                int mode, boolean isNegative) {
9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number *
9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            roundingIncReciprocal;
10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // do the absolute cases first
10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch (mode) {
10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case BigDecimal.ROUND_CEILING:
10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case BigDecimal.ROUND_FLOOR:
10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case BigDecimal.ROUND_DOWN:
10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            div = (Math.floor(div + epsilon));
10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case BigDecimal.ROUND_UP:
10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            div = (Math.ceil(div - epsilon));
10157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case BigDecimal.ROUND_UNNECESSARY:
10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (div != Math.floor(div)) {
10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new ArithmeticException("Rounding necessary");
10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return number;
10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        default:
10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Handle complex cases, where the choice depends on the closer value.
10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // We figure out the distances to the two possible values, ceiling and floor.
10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // We then go for the diff that is smaller.  Only if they are equal does the
10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // mode matter.
10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            double ceil = Math.ceil(div);
10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            double ceildiff = ceil - div; // (ceil * roundingInc) - number;
10317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            double floor = Math.floor(div);
10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            double floordiff = div - floor; // number - (floor * roundingInc);
10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Note that the diff values were those mapped back to the "normal" space by
10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // using the roundingInc. I don't have access to the original author of the
10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // code but suspect that that was to produce better result in edge cases
10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // because of machine precision, rather than simply using the difference
10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // between, say, ceil and div.  However, it didn't work in all cases. Am
10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // trying instead using an epsilon value.
10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch (mode) {
10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case BigDecimal.ROUND_HALF_EVEN:
10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // We should be able to just return Math.rint(a), but this
10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // doesn't work in some VMs.
10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // if one is smaller than the other, take the corresponding side
10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (floordiff + epsilon < ceildiff) {
10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    div = floor;
10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (ceildiff + epsilon < floordiff) {
10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    div = ceil;
10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else { // they are equal, so we want to round to whichever is even
10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    double testFloor = floor / 2;
10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
10547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
10557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case BigDecimal.ROUND_HALF_DOWN:
10567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
10577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
10587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case BigDecimal.ROUND_HALF_UP:
10597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
10607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
10617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            default:
10627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                throw new IllegalArgumentException("Invalid rounding mode: " + mode);
10637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
10647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
10657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal;
10667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return number;
10677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
10687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static double epsilon = 0.00000000001;
10707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
10727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
10737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
10747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
10757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
10767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
10777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return format(number, result, fieldPosition, false);
10787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
10797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition,
10817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                boolean parseAttr) {
10827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fieldPosition.setBeginIndex(0);
10837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        fieldPosition.setEndIndex(0);
10847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If we are to do rounding, we need to move into the BigDecimal
10867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // domain in order to do divide/multiply correctly.
10877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (actualRoundingIncrementICU != null) {
10887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return format(BigDecimal.valueOf(number), result, fieldPosition);
10897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
10907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean isNegative = (number < 0);
10927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isNegative)
10937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = -number;
10947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
10957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // In general, long values always represent real finite numbers, so we don't have
10967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // to check for +/- Infinity or NaN. However, there is one case we have to be
10977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE
10987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // outside the legal range. We check for this before multiplying, and if it
10997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // happens we use BigInteger instead.
11007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (multiplier != 1) {
11017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean tooBig = false;
11027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (number < 0) { // This can only happen if number == Long.MIN_VALUE
11037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                long cutoff = Long.MIN_VALUE / multiplier;
11047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
11057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
11067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                long cutoff = Long.MAX_VALUE / multiplier;
11077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                tooBig = (number > cutoff);
11087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
11097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (tooBig) {
11107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // [Spark/CDL] Use
11117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // format_BigInteger_StringBuffer_FieldPosition_boolean instead
11127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // parseAttr is used to judge whether to synthesize attributes.
11137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return format(BigInteger.valueOf(isNegative ? -number : number), result,
11147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                              fieldPosition, parseAttr);
11157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
11167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        number *= multiplier;
11197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized (digitList) {
11207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitList.set(number, precision(true));
11217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
11227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
11247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
11267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Formats a BigInteger number.
11277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
11287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
11297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
11307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
11317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StringBuffer format(BigInteger number, StringBuffer result,
11327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                               FieldPosition fieldPosition) {
11337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return format(number, result, fieldPosition, false);
11347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
11357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition,
11377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                boolean parseAttr) {
11387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If we are to do rounding, we need to move into the BigDecimal
11397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // domain in order to do divide/multiply correctly.
11407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (actualRoundingIncrementICU != null) {
11417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return format(new BigDecimal(number), result, fieldPosition);
11427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (multiplier != 1) {
11457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = number.multiply(BigInteger.valueOf(multiplier));
11467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // At this point we are guaranteed a nonnegative finite
11497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // number.
11507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized (digitList) {
11517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitList.set(number, precision(true));
11527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
11537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             parseAttr);
11547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
11567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
11587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Formats a BigDecimal number.
11597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
11607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
11617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
11627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
11637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
11647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                               FieldPosition fieldPosition) {
11657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return format(number, result, fieldPosition, false);
11667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
11677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer format(java.math.BigDecimal number, StringBuffer result,
11697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                FieldPosition fieldPosition,
11707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean parseAttr) {
11717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (multiplier != 1) {
11727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
11737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (actualRoundingIncrement != null) {
11767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = number.divide(actualRoundingIncrement, 0, roundingMode).multiply(actualRoundingIncrement);
11777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized (digitList) {
11807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitList.set(number, precision(false), !useExponentialNotation &&
11817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          !areSignificantDigitsUsed());
11827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
11837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             false, parseAttr);
11847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
11867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
11887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Formats a BigDecimal number.
11897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
11907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
11917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
11927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
11937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public StringBuffer format(BigDecimal number, StringBuffer result,
11947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                               FieldPosition fieldPosition) {
11957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         // This method is just a copy of the corresponding java.math.BigDecimal method
11967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         // for now. It isn't very efficient since it must create a conversion object to
11977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         // do math on the rounding increment. In the future we may try to clean this up,
11987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         // or even better, limit our support to just one flavor of BigDecimal.
11997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (multiplier != 1) {
12007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
12017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (actualRoundingIncrementICU != null) {
12047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            number = number.divide(actualRoundingIncrementICU, 0, roundingMode)
12057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                .multiply(actualRoundingIncrementICU, mathContext);
12067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized (digitList) {
12097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitList.set(number, precision(false), !useExponentialNotation &&
12107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          !areSignificantDigitsUsed());
12117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
12127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             false, false);
12137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
12157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
12177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns true if a grouping separator belongs at the given position, based on whether
12187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * grouping is in use and the values of the primary and secondary grouping interval.
12197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
12207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pos the number of integer digits to the right of the current position. Zero
12217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * indicates the position after the rightmost integer digit.
12227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if a grouping character belongs at the current position.
12237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
12247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean isGroupingPosition(int pos) {
12257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean result = false;
12267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
12277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if ((groupingSize2 > 0) && (pos > groupingSize)) {
12287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = ((pos - groupingSize) % groupingSize2) == 0;
12297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
12307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result = pos % groupingSize == 0;
12317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
12327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
12347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
12357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
12377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Return the number of fraction digits to display, or the total
12387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * number of digits for significant digit formats and exponential
12397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * formats.
12407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
12417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int precision(boolean isIntegral) {
12427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (areSignificantDigitsUsed()) {
12437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getMaximumSignificantDigits();
12447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (useExponentialNotation) {
12457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return getMinimumIntegerDigits() + getMaximumFractionDigits();
12467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
12477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return isIntegral ? 0 : getMaximumFractionDigits();
12487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
12507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition,
12527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
12537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
12547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // compute the plural category from the digitList plus other settings
12557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(currencyPluralInfo.select(getFixedDecimal(number)),
12567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             result, fieldPosition, isNegative,
12577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             isInteger, parseAttr);
12587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
12597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
12607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
12627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
12647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This is ugly, but don't see a better way to do it without major restructuring of the code.
12657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
12667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*package*/ FixedDecimal getFixedDecimal(double number) {
12677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // get the visible fractions and the number of fraction digits.
12687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert       return getFixedDecimal(number, digitList);
12697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
12707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
12717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    FixedDecimal getFixedDecimal(double number, DigitList dl) {
12727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int fractionalDigitsInDigitList = dl.count - dl.decimalAt;
12737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int v;
12747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        long f;
12757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int maxFractionalDigits;
12767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int minFractionalDigits;
12777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (useSignificantDigits) {
12787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            maxFractionalDigits = maxSignificantDigits - dl.decimalAt;
12797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            minFractionalDigits = minSignificantDigits - dl.decimalAt;
12807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (minFractionalDigits < 0) {
12817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                minFractionalDigits = 0;
12827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
12837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (maxFractionalDigits < 0) {
12847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxFractionalDigits = 0;
12857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
12867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
12877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            maxFractionalDigits = getMaximumFractionDigits();
12887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            minFractionalDigits = getMinimumFractionDigits();
12897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        v = fractionalDigitsInDigitList;
12917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (v < minFractionalDigits) {
12927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            v = minFractionalDigits;
12937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (v > maxFractionalDigits) {
12947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            v = maxFractionalDigits;
12957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
12967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        f = 0;
12977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (v > 0) {
12987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = Math.max(0, dl.decimalAt); i < dl.count; ++i) {
12997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                f *= 10;
13007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                f += (dl.digits[i] - '0');
13017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
13027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = v; i < fractionalDigitsInDigitList; ++i) {
13037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                f *= 10;
13047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
13057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return new FixedDecimal(number, v, f);
13077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
13087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition,
13107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                   boolean isNegative,
13117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean isInteger, boolean parseAttr) {
13127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
13137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // compute the plural category from the digitList plus other settings
13147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(currencyPluralInfo.select(getFixedDecimal(number)),
13157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             result, fieldPosition, isNegative,
13167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             isInteger, parseAttr);
13177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
13187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
13197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
13217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition,
13237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean isNegative, boolean isInteger, boolean parseAttr) {
13247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // There are 2 ways to activate currency plural format: by applying a pattern with
13257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // 3 currency sign directly, or by instantiate a decimal formatter using
13267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // PLURALCURRENCYSTYLE.  For both cases, the number of currency sign in the
13277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // pattern is 3.  Even if the number of currency sign in the pattern is 3, it does
13287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // not mean we need to reset the pattern.  For 1st case, we do not need to reset
13297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // pattern.  For 2nd case, we might need to reset pattern, if the default pattern
13307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // (corresponding to plural count 'other') we use is different from the pattern
13317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // based on 'pluralCount'.
13327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //
13337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // style is only valid when decimal formatter is constructed through
13347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // DecimalFormat(pattern, symbol, style)
13357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
13367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
13377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
13387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (formatPattern.equals(currencyPluralPattern) == false) {
13397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                applyPatternWithoutExpandAffix(currencyPluralPattern, false);
13407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
13417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Expand the affix to the right name according to the plural rule.  This is only
13437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // used for currency plural formatting.  Currency plural name is not a fixed
13447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // static one, it is a dynamic name based on the currency plural count.  So, the
13457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // affixes need to be expanded here.  For other cases, the affix is a static one
13467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // based on pattern alone, and it is already expanded during applying pattern, or
13477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // setDecimalFormatSymbols, or setCurrency.
13487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expandAffixAdjustWidth(pluralCount);
13497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
13507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
13517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
13537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Complete the formatting of a finite number. On entry, the
13547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * digitList must be filled in with the correct digits.
13557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
13567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,
13577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                   boolean isNegative, boolean isInteger, boolean parseAttr) {
13587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // NOTE: This isn't required anymore because DigitList takes care of this.
13597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //
13607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // // The negative of the exponent represents the number of leading // zeros
13617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g.,
13627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction
13637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits, then we have an underflow // for the printed representation. We
13647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // recognize this here and set // the DigitList representation to zero in this
13657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // situation.
13667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //
13677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // if (-digitList.decimalAt >= getMaximumFractionDigits())
13687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // {
13697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digitList.count = 0;
13707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // }
13717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as
13757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // zero. This allows sensible computations and preserves relations such as
13767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // signum(1/x) = signum(x), where x is +Infinity or -Infinity.  Prior to this fix,
13777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // we always formatted zero values as if they were positive. Liu 7/6/98.
13787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (digitList.isZero()) {
13797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitList.decimalAt = 0; // Normalize
13807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int prefixLen = appendAffix(result, isNegative, true, parseAttr);
13837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (useExponentialNotation) {
13857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            subformatExponential(result, fieldPosition, parseAttr);
13867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
13877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            subformatFixed(result, fieldPosition, isInteger, parseAttr);
13887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int suffixLen = appendAffix(result, isNegative, false, parseAttr);
13917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        addPadding(result, fieldPosition, prefixLen, suffixLen);
13937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result;
13947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
13957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
13967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void subformatFixed(StringBuffer result,
13977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            FieldPosition fieldPosition,
13987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean isInteger,
13997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean parseAttr) {
14007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char [] digits = symbols.getDigitsLocal();
14017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char grouping = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
14037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                symbols.getGroupingSeparator(): symbols.getMonetaryGroupingSeparator();
14047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
14057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
14067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean useSigDig = areSignificantDigitsUsed();
14077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int maxIntDig = getMaximumIntegerDigits();
14087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int minIntDig = getMinimumIntegerDigits();
14097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i;
14107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Record the integer start index.
14117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int intBegin = result.length();
14127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Record field information for caller.
14137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
14147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(result.length());
14157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
14167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(result.length());
14177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        long fractionalDigits = 0;
14197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int fractionalDigitsCount = 0;
14207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean recordFractionDigits = false;
14217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int sigCount = 0;
14237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int minSigDig = getMinimumSignificantDigits();
14247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int maxSigDig = getMaximumSignificantDigits();
14257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!useSigDig) {
14267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            minSigDig = 0;
14277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            maxSigDig = Integer.MAX_VALUE;
14287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Output the integer portion. Here 'count' is the total number of integer
14317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits we will display, including both leading zeros required to satisfy
14327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // getMinimumIntegerDigits, and actual digits present in the number.
14337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig;
14347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
14357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            count = digitList.decimalAt;
14367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Handle the case where getMaximumIntegerDigits() is smaller than the real
14397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // number of integer digits. If this is so, we output the least significant
14407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // max integer digits. For example, the value 1997 printed with 2 max integer
14417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits is just "97".
14427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int digitIndex = 0; // Index into digitList.fDigits[]
14447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (count > maxIntDig && maxIntDig >= 0) {
14457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            count = maxIntDig;
14467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digitIndex = digitList.decimalAt - count;
14477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int sizeBeforeIntegerPart = result.length();
14507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = count - 1; i >= 0; --i) {
14517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (i < digitList.decimalAt && digitIndex < digitList.count
14527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && sigCount < maxSigDig) {
14537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Output a real digit
14547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(digits[digitList.getDigitValue(digitIndex++)]);
14557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ++sigCount;
14567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
14577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Output a zero (leading or trailing)
14587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(digits[0]);
14597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (sigCount > 0) {
14607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++sigCount;
14617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
14627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
14637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Output grouping separator if necessary.
14657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (isGroupingPosition(i)) {
14667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(grouping);
14677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // [Spark/CDL] Add grouping separator attribute here.
14687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (parseAttr) {
14697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Length of grouping separator is 1.
14707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
14717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
14727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
14737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Record field information for caller.
14767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
14777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(result.length());
14787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
14797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(result.length());
14807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // This handles the special case of formatting 0. For zero only, we count the
14837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // zero to the left of the decimal point as one signficant digit. Ordinarily we
14847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // do not count any leading 0's as significant. If the number we are formatting
14857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // is not zero, then either sigCount or digits.getCount() will be non-zero.
14867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (sigCount == 0 && digitList.count == 0) {
14877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          sigCount = 1;
14887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Determine whether or not there are any printable fractional digits. If
14917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // we've used up the digits we know there aren't.
14927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean fractionPresent = (!isInteger && digitIndex < digitList.count)
14937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
14947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
14957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If there is no fraction present, and we haven't printed any integer digits,
14967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // then print a zero. Otherwise we won't print _any_ digits, and we won't be
14977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // able to parse this string.
14987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
14997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append(digits[0]);
15007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Add attribute for integer part.
15017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parseAttr) {
15027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.INTEGER, intBegin, result.length());
15037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Output the decimal separator if we always do so.
15057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (decimalSeparatorAlwaysShown || fractionPresent) {
15067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
15077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
15087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append(decimal);
15107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
15117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
15127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // [Spark/CDL] Add attribute for decimal separator
15147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (parseAttr) {
15157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length());
15167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Record field information for caller.
15207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
15217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(result.length());
15227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
15237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(result.length());
15247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Record the begin index of fraction part.
15277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int fracBegin = result.length();
15287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        recordFractionDigits = fieldPosition instanceof UFieldPosition;
15297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
15317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (useSigDig && (sigCount == maxSigDig ||
15327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          (sigCount >= minSigDig && digitIndex == digitList.count))) {
15337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            count = 0;
15347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < count; ++i) {
15367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Here is where we escape from the loop. We escape if we've output the
15377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // maximum fraction digits (specified in the for expression above). We
15387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // also stop when we've output the minimum digits and either: we have an
15397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // integer, so there is no fractional stuff to display, or we're out of
15407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // significant digits.
15417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!useSigDig && i >= getMinimumFractionDigits() &&
15427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                (isInteger || digitIndex >= digitList.count)) {
15437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
15447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Output leading fractional zeros. These are zeros that come after the
15477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // decimal but before any significant digits. These are only output if
15487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // abs(number being formatted) < 1.0.
15497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (-1 - i > (digitList.decimalAt - 1)) {
15507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(digits[0]);
15517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (recordFractionDigits) {
15527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++fractionalDigitsCount;
15537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fractionalDigits *= 10;
15547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
15557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
15567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Output a digit, if we have any precision left, or a zero if we
15597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // don't. We don't want to output noise digits.
15607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!isInteger && digitIndex < digitList.count) {
15617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte digit = digitList.getDigitValue(digitIndex++);
15627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(digits[digit]);
15637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (recordFractionDigits) {
15647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++fractionalDigitsCount;
15657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fractionalDigits *= 10;
15667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fractionalDigits += digit;
15677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
15687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
15697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(digits[0]);
15707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (recordFractionDigits) {
15717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++fractionalDigitsCount;
15727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fractionalDigits *= 10;
15737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
15747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // If we reach the maximum number of significant digits, or if we output
15777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // all the real digits and reach the minimum, then we are done.
15787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ++sigCount;
15797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (useSigDig && (sigCount == maxSigDig ||
15807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                              (digitIndex == digitList.count && sigCount >= minSigDig))) {
15817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
15827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Record field information for caller.
15867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
15877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(result.length());
15887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
15897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(result.length());
15907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (recordFractionDigits) {
15927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
15937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
15957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Add attribute information if necessary.
15967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
15977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.FRACTION, fracBegin, result.length());
15987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
16007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void subformatExponential(StringBuffer result,
16027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            FieldPosition fieldPosition,
16037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean parseAttr) {
16047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char [] digits = symbols.getDigitsLocal();
16057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
16067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
16077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean useSigDig = areSignificantDigitsUsed();
16087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int maxIntDig = getMaximumIntegerDigits();
16097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int minIntDig = getMinimumIntegerDigits();
16107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i;
16117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Record field information for caller.
16127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
16137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(result.length());
16147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(-1);
16157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
16167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(-1);
16177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
16187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(result.length());
16197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(-1);
16207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
16217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setBeginIndex(-1);
16227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
16237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL]
16267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // the begin index of integer part
16277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // the end index of integer part
16287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // the begin index of fractional part
16297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int intBegin = result.length();
16307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int intEnd = -1;
16317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int fracBegin = -1;
16327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int minFracDig = 0;
16337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (useSigDig) {
16347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            maxIntDig = minIntDig = 1;
16357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            minFracDig = getMinimumSignificantDigits() - 1;
16367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
16377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            minFracDig = getMinimumFractionDigits();
16387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
16397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxIntDig = 1;
16407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (maxIntDig < minIntDig) {
16417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    maxIntDig = minIntDig;
16427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
16437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
16447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (maxIntDig > minIntDig) {
16457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                minIntDig = 1;
16467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
16477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
16487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        long fractionalDigits = 0;
16497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int fractionalDigitsCount = 0;
16507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean recordFractionDigits = false;
16517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Minimum integer digits are handled in exponential format by adjusting the
16537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".
16547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Maximum integer digits are interpreted as indicating the repeating
16567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // range. This is useful for engineering notation, in which the exponent is
16577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer
16587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits is "12.34e-3".  If maximum integer digits are defined and are larger
16597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // than minimum integer digits, then minimum integer digits are ignored.
16607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int exponent = digitList.decimalAt;
16627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (maxIntDig > 1 && maxIntDig != minIntDig) {
16637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // A exponent increment is defined; adjust to it.
16647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1;
16657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent *= maxIntDig;
16667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
16677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // No exponent increment is defined; use minimum integer digits.
16687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // If none is specified, as in "#E0", generate 1 integer digit.
16697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1;
16707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
16717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // We now output a minimum number of digits, and more if there are more
16737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits, up to the maximum number of digits. We place the decimal point
16747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // after the "integer" digits, which are the first (decimalAt - exponent)
16757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits.
16767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int minimumDigits = minIntDig + minFracDig;
16777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // The number of integer digits is handled specially if the number
16787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // is zero, since then there may be no digits.
16797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent;
16807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int totalDigits = digitList.count;
16817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (minimumDigits > totalDigits)
16827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            totalDigits = minimumDigits;
16837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (integerDigits > totalDigits)
16847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            totalDigits = integerDigits;
16857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < totalDigits; ++i) {
16877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (i == integerDigits) {
16887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Record field information for caller.
16897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
16907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fieldPosition.setEndIndex(result.length());
16917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
16927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fieldPosition.setEndIndex(result.length());
16937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
16947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
16957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // [Spark/CDL] Add attribute for integer part
16967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (parseAttr) {
16977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    intEnd = result.length();
16987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    addAttribute(Field.INTEGER, intBegin, result.length());
16997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
17007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(decimal);
17017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // [Spark/CDL] Add attribute for decimal separator
17027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (parseAttr) {
17037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Length of decimal separator is 1.
17047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int decimalSeparatorBegin = result.length() - 1;
17057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin,
17067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 result.length());
17077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fracBegin = result.length();
17087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
17097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Record field information for caller.
17107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
17117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fieldPosition.setBeginIndex(result.length());
17127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
17137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fieldPosition.setBeginIndex(result.length());
17147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
17157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                recordFractionDigits = fieldPosition instanceof UFieldPosition;
17167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte digit = (i < digitList.count) ? digitList.getDigitValue(i) : (byte)0;
17197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append(digits[digit]);
17207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (recordFractionDigits) {
17217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ++fractionalDigitsCount;
17227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fractionalDigits *= 10;
17237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fractionalDigits += digit;
17247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
17287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (digitList.isZero() && (totalDigits == 0)) {
17297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append(digits[0]);
17307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Record field information
17337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
17347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getEndIndex() < 0) {
17357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
17367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
17387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getBeginIndex() < 0) {
17397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
17407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(result.length());
17427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
17437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getEndIndex() < 0) {
17447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setEndIndex(result.length());
17457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
17477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fieldPosition.getBeginIndex() < 0) {
17487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                fieldPosition.setBeginIndex(result.length());
17497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fieldPosition.setEndIndex(result.length());
17517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (recordFractionDigits) {
17537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
17547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Calcuate the end index of integer part and fractional
17577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // part if they are not properly processed yet.
17587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parseAttr) {
17597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (intEnd < 0) {
17607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.INTEGER, intBegin, result.length());
17617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (fracBegin > 0) {
17637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.FRACTION, fracBegin, result.length());
17647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // The exponent is output using the pattern-specified minimum exponent
17687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // digits. There is no maximum limit to the exponent digits, since truncating
17697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // the exponent would result in an unacceptable inaccuracy.
17707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        result.append(symbols.getExponentSeparator());
17717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] For exponent symbol, add an attribute.
17727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parseAttr) {
17737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.EXPONENT_SYMBOL, result.length() -
17747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         symbols.getExponentSeparator().length(), result.length());
17757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // For zero values, we force the exponent to zero. We must do this here, and
17777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // not earlier, because the value is used to determine integer digit count
17787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // above.
17797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (digitList.isZero())
17807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent = 0;
17817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean negativeExponent = exponent < 0;
17837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (negativeExponent) {
17847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent = -exponent;
17853937b302ef4bb23600d398d228736895b6bbb314Travis Keep            result.append(symbols.getMinusString());
17867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // [Spark/CDL] If exponent has sign, then add an exponent sign
17877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // attribute.
17887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (parseAttr) {
17897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Length of exponent sign is 1.
17907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
17917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (exponentSignAlwaysShown) {
17933937b302ef4bb23600d398d228736895b6bbb314Travis Keep            result.append(symbols.getPlusString());
17947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // [Spark/CDL] Add an plus sign attribute.
17957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (parseAttr) {
17967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Length of exponent sign is 1.
17977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int expSignBegin = result.length() - 1;
17987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length());
17997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
18007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
18017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int expBegin = result.length();
18027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        digitList.set(exponent);
18037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        {
18047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int expDig = minExponentDigits;
18057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (useExponentialNotation && expDig < 1) {
18067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                expDig = 1;
18077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
18087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (i = digitList.decimalAt; i < expDig; ++i)
18097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(digits[0]);
18107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
18117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (i = 0; i < digitList.decimalAt; ++i) {
18127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            result.append((i < digitList.count) ? digits[digitList.getDigitValue(i)]
18137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          : digits[0]);
18147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
18157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Add attribute for exponent part.
18167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parseAttr) {
18177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.EXPONENT, expBegin, result.length());
18187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
18197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
18207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
18217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen,
18227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                  int suffixLen) {
18237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0) {
18247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int len = formatWidth - result.length();
18257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (len > 0) {
18267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                char[] padding = new char[len];
18277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (int i = 0; i < len; ++i) {
18287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    padding[i] = pad;
18297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
18307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                switch (padPosition) {
18317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PAD_AFTER_PREFIX:
18327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.insert(prefixLen, padding);
18337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
18347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PAD_BEFORE_PREFIX:
18357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.insert(0, padding);
18367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
18377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PAD_BEFORE_SUFFIX:
18387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.insert(result.length() - suffixLen, padding);
18397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
18407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PAD_AFTER_SUFFIX:
18417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(padding);
18427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
18437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
18447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) {
18457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
18467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
18477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
18487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
18497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
18507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
18517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
18527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
18537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Parses the given string, returning a <code>Number</code> object to represent the
18547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * parsed value. <code>Double</code> objects are returned to represent non-integral
18557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * values which cannot be stored in a <code>BigDecimal</code>. These are
18567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
18577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * false (the default), all other values are returned as <code>Long</code>,
18587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
18597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
18607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
18617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
18627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param text the string to be parsed
18637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param parsePosition defines the position where parsing is to begin, and upon
18647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * return, the position where parsing left off. If the position has not changed upon
18657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * return, then parsing failed.
18667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return a <code>Number</code> object with the parsed value or
18677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>null</code> if the parse failed
18687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
18697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
18707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
18717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Number parse(String text, ParsePosition parsePosition) {
18727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (Number) parse(text, parsePosition, null);
18737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
18747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
18757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
18767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
18777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * this method will attempt to parse a generic currency name, searching for a match of
18787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * this object's locale's currency display names, or for a 3-letter ISO currency
18797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * code. This method will fail if this format is not a currency format, that is, if it
18807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
18817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
18827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param text the text to parse
18837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pos input-output position; on input, the position within text to match; must
18847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *  have 0 <= pos.getIndex() < text.length(); on output, the position after the last
18857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *  matched character. If the parse fails, the position in unchanged upon output.
18867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return a CurrencyAmount, or null upon failure
18877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 49
18887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
18897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
18907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) {
18917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Currency[] currency = new Currency[1];
18927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (CurrencyAmount) parse(text.toString(), pos, currency);
18937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
18947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
18957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
18967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Parses the given text as either a Number or a CurrencyAmount.
18977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
18987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param text the string to parse
18997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param parsePosition input-output position; on input, the position within text to
19007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after
19017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the last matched character. If the parse fails, the position in unchanged upon
19027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * output.
19037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param currency if non-null, a CurrencyAmount is parsed and returned; otherwise a
19047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Number is parsed and returned
19057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return a Number or CurrencyAmount or null
19067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
19077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private Object parse(String text, ParsePosition parsePosition, Currency[] currency) {
19087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int backup;
19097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i = backup = parsePosition.getIndex();
19107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Handle NaN as a special case:
19127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Skip padding characters, if around prefix
19147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0 &&
19157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {
19167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            i = skipPadding(text, i);
19177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
19187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) {
19197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            i += symbols.getNaN().length();
19207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Skip padding characters, if around suffix
19217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
19227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    padPosition == PAD_AFTER_SUFFIX)) {
19237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                i = skipPadding(text, i);
19247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
19257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setIndex(i);
19267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new Double(Double.NaN);
19277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
19287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // NaN parse failed; start over
19307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        i = backup;
19317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean[] status = new boolean[STATUS_LENGTH];
19337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
19347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!parseForCurrency(text, parsePosition, currency, status)) {
19357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
19367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
19377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
19387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!subparse(text, parsePosition, digitList, status, currency, negPrefixPattern,
19397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          negSuffixPattern, posPrefixPattern, posSuffixPattern,
19407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          false, Currency.SYMBOL_NAME)) {
19417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                parsePosition.setIndex(backup);
19427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return null;
19437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
19447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
19457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Number n = null;
19477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Handle infinity
19497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (status[STATUS_INFINITE]) {
19507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY :
19517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                           Double.NEGATIVE_INFINITY);
19527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
19537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Handle underflow
19557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        else if (status[STATUS_UNDERFLOW]) {
19567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
19577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
19587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Handle -0.0
19607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
19617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            n = new Double("-0.0");
19627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
19637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        else {
19657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Do as much of the multiplier conversion as possible without
19667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // losing accuracy.
19677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mult = multiplier; // Don't modify this.multiplier
19687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (mult % 10 == 0) {
19697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                --digitList.decimalAt;
19707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                mult /= 10;
19717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
19727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
19737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Handle integral values
19747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
19757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // hack quick long
19767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (digitList.decimalAt < 12) { // quick check for long
19777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    long l = 0;
19787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (digitList.count > 0) {
19797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int nx = 0;
19807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        while (nx < digitList.count) {
19817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            l = l * 10 + (char) digitList.digits[nx++] - '0';
19827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
19837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        while (nx++ < digitList.decimalAt) {
19847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            l *= 10;
19857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
19867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!status[STATUS_POSITIVE]) {
19877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            l = -l;
19887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
19897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
19907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    n = Long.valueOf(l);
19917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
19927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
19937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    n = (big.bitLength() < 64) ? (Number) Long.valueOf(big.longValue()) : (Number) big;
19947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
19957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
19967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Handle non-integral values or the case where parseBigDecimal is set
19977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            else {
19987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
19997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                n = big;
20007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (mult != 1) {
20017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    n = big.divide(BigDecimal.valueOf(mult), mathContext);
20027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
20037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
20047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
20057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
20067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Assemble into CurrencyAmount if necessary
20077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (currency != null) ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n;
20087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
20097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
20107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean parseForCurrency(String text, ParsePosition parsePosition,
20117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Currency[] currency, boolean[] status) {
20127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int origPos = parsePosition.getIndex();
20137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!isReadyForParsing) {
20147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int savedCurrencySignCount = currencySignCount;
20157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setupCurrencyAffixForAllPatterns();
20167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // reset pattern back
20177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
20187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                applyPatternWithoutExpandAffix(formatPattern, false);
20197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
20207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                applyPattern(formatPattern, false);
20217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
20227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            isReadyForParsing = true;
20237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
20247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int maxPosIndex = origPos;
20257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int maxErrorPos = -1;
20267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean[] savedStatus = null;
20277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // First, parse against current pattern.
20287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Since current pattern could be set by applyPattern(),
20297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // it could be an arbitrary pattern, and it may not be the one
20307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // defined in current locale.
20317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean[] tmpStatus = new boolean[STATUS_LENGTH];
20327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ParsePosition tmpPos = new ParsePosition(origPos);
20337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DigitList tmpDigitList = new DigitList();
20347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean found;
20357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
20367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
20377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
20387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             true, Currency.LONG_NAME);
20397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
20407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
20417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
20427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             true, Currency.SYMBOL_NAME);
20437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
20447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (found) {
20457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (tmpPos.getIndex() > maxPosIndex) {
20467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxPosIndex = tmpPos.getIndex();
20477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                savedStatus = tmpStatus;
20487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digitList = tmpDigitList;
20497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
20507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
20517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            maxErrorPos = tmpPos.getErrorIndex();
20527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
20537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Then, parse against affix patterns.  Those are currency patterns and currency
20547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // plural patterns defined in the locale.
20557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (AffixForCurrency affix : affixPatternsForCurrency) {
20567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            tmpStatus = new boolean[STATUS_LENGTH];
20577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            tmpPos = new ParsePosition(origPos);
20587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            tmpDigitList = new DigitList();
20597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
20607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                      affix.getNegPrefix(), affix.getNegSuffix(),
20617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                      affix.getPosPrefix(), affix.getPosSuffix(),
20627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                      true, affix.getPatternType());
20637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (result) {
20647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                found = true;
20657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (tmpPos.getIndex() > maxPosIndex) {
20667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    maxPosIndex = tmpPos.getIndex();
20677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    savedStatus = tmpStatus;
20687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    digitList = tmpDigitList;
20697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
20707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
20717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex()
20727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    : maxErrorPos;
20737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
20747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
20757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Finally, parse against simple affix to find the match.  For example, in
20767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // TestMonster suite, if the to-be-parsed text is "-\u00A40,00".
20777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // complexAffixCompare will not find match, since there is no ISO code matches
20787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // "\u00A4", and the parse stops at "\u00A4".  We will just use simple affix
20797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // comparison (look for exact match) to pass it.
20807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //
20817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // TODO: We should parse against simple affix first when
20827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // output currency is not requested. After the complex currency
20837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // parsing implementation was introduced, the default currency
20847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // instance parsing slowed down because of the new code flow.
20857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // I filed #10312 - Yoshito
20867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        tmpStatus = new boolean[STATUS_LENGTH];
20877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        tmpPos = new ParsePosition(origPos);
20887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        tmpDigitList = new DigitList();
20897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
20907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Disable complex currency parsing and try it again.
20917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency,
20927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                  negativePrefix, negativeSuffix, positivePrefix, positiveSuffix,
20937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                  false /* disable complex currency parsing */, Currency.SYMBOL_NAME);
20947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (result) {
20957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (tmpPos.getIndex() > maxPosIndex) {
20967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxPosIndex = tmpPos.getIndex();
20977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                savedStatus = tmpStatus;
20987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digitList = tmpDigitList;
20997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
21007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            found = true;
21017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
21027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() :
21037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxErrorPos;
21047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
21057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!found) {
21077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // parsePosition.setIndex(origPos);
21087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setErrorIndex(maxErrorPos);
21097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
21107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setIndex(maxPosIndex);
21117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setErrorIndex(-1);
21127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int index = 0; index < STATUS_LENGTH; ++index) {
21137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                status[index] = savedStatus[index];
21147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
21157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
21167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return found;
21177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
21187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and
21207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // currency plural pattern (CurrencyUnitPatterns).
21217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void setupCurrencyAffixForAllPatterns() {
21227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencyPluralInfo == null) {
21237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
21247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
21257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        affixPatternsForCurrency = new HashSet<AffixForCurrency>();
21267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // save the current pattern, since it will be changed by
21287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // applyPatternWithoutExpandAffix
21297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String savedFormatPattern = formatPattern;
21307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so,
21327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // only need to save one of them.  Here, chose onlyApplyPatternWithoutExpandAffix
21337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // without saving the actualy pattern in 'pattern' data member.  TODO: is it uloc?
21347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPatternWithoutExpandAffix(getPattern(symbols.getULocale(), NumberFormat.CURRENCYSTYLE),
21357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                       false);
21367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        AffixForCurrency affixes = new AffixForCurrency(
21377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
21387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Currency.SYMBOL_NAME);
21397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        affixPatternsForCurrency.add(affixes);
21407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // add plural pattern
21427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Iterator<String> iter = currencyPluralInfo.pluralPatternIterator();
21437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Set<String> currencyUnitPatternSet = new HashSet<String>();
21447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (iter.hasNext()) {
21457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String pluralCount = iter.next();
21467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
21477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (currencyPattern != null &&
21487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                currencyUnitPatternSet.contains(currencyPattern) == false) {
21497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                currencyUnitPatternSet.add(currencyPattern);
21507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                applyPatternWithoutExpandAffix(currencyPattern, false);
21517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern,
21527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                               posSuffixPattern, Currency.LONG_NAME);
21537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                affixPatternsForCurrency.add(affixes);
21547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
21557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
21567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // reset pattern back
21577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatPattern = savedFormatPattern;
21587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
21597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // currency formatting style options
21617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int CURRENCY_SIGN_COUNT_ZERO = 0;
21627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
21637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
21647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;
21657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int STATUS_INFINITE = 0;
21677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int STATUS_POSITIVE = 1;
21687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int STATUS_UNDERFLOW = 2;
21697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final int STATUS_LENGTH = 3;
21707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final UnicodeSet dotEquivalents = new UnicodeSet(
21727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]"
21737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x002E, 0x002E,
21747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x2024, 0x2024,
21757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x3002, 0x3002,
21767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE12, 0xFE12,
21777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE52, 0xFE52,
21787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF0E, 0xFF0E,
21797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF61, 0xFF61).freeze();
21807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final UnicodeSet commaEquivalents = new UnicodeSet(
21827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]"
21837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x002C, 0x002C,
21847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x060C, 0x060C,
21857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x066B, 0x066B,
21867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x3001, 0x3001,
21877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE10, 0xFE11,
21887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE50, 0xFE51,
21897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF0C, 0xFF0C,
21907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF64, 0xFF64).freeze();
21917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
21927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//    private static final UnicodeSet otherGroupingSeparators = new UnicodeSet(
21937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
21947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x0020, 0x0020,
21957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x0027, 0x0027,
21967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x00A0, 0x00A0,
21977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x066C, 0x066C,
21987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x2000, 0x200A,
21997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x2018, 0x2019,
22007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x202F, 0x202F,
22017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x205F, 0x205F,
22027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x3000, 0x3000,
22037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0xFF07, 0xFF07).freeze();
22047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final UnicodeSet strictDotEquivalents = new UnicodeSet(
22067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //"[.\u2024\uFE52\uFF0E\uFF61]"
22077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x002E, 0x002E,
22087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x2024, 0x2024,
22097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE52, 0xFE52,
22107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF0E, 0xFF0E,
22117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF61, 0xFF61).freeze();
22127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final UnicodeSet strictCommaEquivalents = new UnicodeSet(
22147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //"[,\u066B\uFE10\uFE50\uFF0C]"
22157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x002C, 0x002C,
22167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0x066B, 0x066B,
22177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE10, 0xFE10,
22187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFE50, 0xFE50,
22197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0xFF0C, 0xFF0C).freeze();
22207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//    private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet(
22227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
22237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x0020, 0x0020,
22247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x0027, 0x0027,
22257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x00A0, 0x00A0,
22267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x066C, 0x066C,
22277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x2000, 0x200A,
22287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x2018, 0x2019,
22297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x202F, 0x202F,
22307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x205F, 0x205F,
22317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0x3000, 0x3000,
22327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//            0xFF07, 0xFF07).freeze();
22337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final UnicodeSet defaultGroupingSeparators =
22357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // new UnicodeSet(dotEquivalents).addAll(commaEquivalents)
22367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //     .addAll(otherGroupingSeparators).freeze();
22377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        new UnicodeSet(
22387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x0020, 0x0020,
22397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x0027, 0x0027,
22407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x002C, 0x002C,
22417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x002E, 0x002E,
22427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x00A0, 0x00A0,
22437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x060C, 0x060C,
22447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x066B, 0x066C,
22457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2000, 0x200A,
22467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2018, 0x2019,
22477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2024, 0x2024,
22487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x202F, 0x202F,
22497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x205F, 0x205F,
22507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x3000, 0x3002,
22517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE10, 0xFE12,
22527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE50, 0xFE52,
22537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF07, 0xFF07,
22547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF0C, 0xFF0C,
22557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF0E, 0xFF0E,
22567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF61, 0xFF61,
22577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF64, 0xFF64).freeze();
22587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final UnicodeSet strictDefaultGroupingSeparators =
22607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents)
22617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //     .addAll(strictOtherGroupingSeparators).freeze();
22627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        new UnicodeSet(
22637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x0020, 0x0020,
22647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x0027, 0x0027,
22657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x002C, 0x002C,
22667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x002E, 0x002E,
22677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x00A0, 0x00A0,
22687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x066B, 0x066C,
22697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2000, 0x200A,
22707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2018, 0x2019,
22717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2024, 0x2024,
22727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x202F, 0x202F,
22737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x205F, 0x205F,
22747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x3000, 0x3000,
22757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE10, 0xFE10,
22767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE50, 0xFE50,
22777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE52, 0xFE52,
22787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF07, 0xFF07,
22797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF0C, 0xFF0C,
22807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF0E, 0xFF0E,
22817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF61, 0xFF61).freeze();
22827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final UnicodeSet minusSigns =
22847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        new UnicodeSet(
22857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x002D, 0x002D,
22867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x207B, 0x207B,
22877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x208B, 0x208B,
22887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2212, 0x2212,
22897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2796, 0x2796,
22907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE63, 0xFE63,
22917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF0D, 0xFF0D).freeze();
22927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final UnicodeSet plusSigns =
22947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            new UnicodeSet(
22957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x002B, 0x002B,
22967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x207A, 0x207A,
22977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x208A, 0x208A,
22987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0x2795, 0x2795,
22997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFB29, 0xFB29,
23007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFE62, 0xFE62,
23017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                0xFF0B, 0xFF0B).freeze();
23027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // equivalent grouping and decimal support
23047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final boolean skipExtendedSeparatorParsing = ICUConfig.get(
23057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        "com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
23067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        .equals("true");
23077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // allow control of requiring a matching decimal point when parsing
23097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    boolean parseRequireDecimalPoint = false;
23107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // When parsing a number with big exponential value, it requires to transform the
23127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // value into a string representation to construct BigInteger instance.  We want to
23137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // set the maximum size because it can easily trigger OutOfMemoryException.
23147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // PARSE_MAX_EXPONENT is currently set to 1000 (See getParseMaxDigits()),
23157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // which is much bigger than MAX_VALUE of Double ( See the problem reported by ticket#5698
23167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int PARSE_MAX_EXPONENT = 1000;
23177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
23197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Parses the given text into a number. The text is parsed beginning at parsePosition,
23207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * until an unparseable character is seen.
23217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
23227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param text the string to parse.
23237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param parsePosition the position at which to being parsing. Upon return, the first
23247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * unparseable character.
23257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param digits the DigitList to set to the parsed value.
23267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param status Upon return contains boolean status flags indicating whether the
23277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * value was infinite and whether it was positive.
23287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param currency return value for parsed currency, for generic currency parsing
23297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * mode, or null for normal parsing. In generic currency parsing mode, any currency is
23307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * parsed, not just the currency that this formatter is set to.
23317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param negPrefix negative prefix pattern
23327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param negSuffix negative suffix pattern
23337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param posPrefix positive prefix pattern
23347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param negSuffix negative suffix pattern
23357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param complexCurrencyParsing whether it is complex currency parsing or not.
23367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param type type of currency to parse against, LONG_NAME only or not.
23377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
23387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final boolean subparse(
23397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String text, ParsePosition parsePosition, DigitList digits,
23407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix,
23417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String posSuffix, boolean parseComplexCurrency, int type) {
23427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int position = parsePosition.getIndex();
23447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int oldStart = parsePosition.getIndex();
23457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Match padding before prefix
23477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
23487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position = skipPadding(text, position);
23497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
23507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Match positive and negative prefixes; prefer longest match.
23527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int posMatch = compareAffix(text, position, false, true, posPrefix, parseComplexCurrency, type, currency);
23537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int negMatch = compareAffix(text, position, true, true, negPrefix, parseComplexCurrency, type, currency);
23547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (posMatch >= 0 && negMatch >= 0) {
23557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (posMatch > negMatch) {
23567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                negMatch = -1;
23577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (negMatch > posMatch) {
23587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                posMatch = -1;
23597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
23607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
23617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (posMatch >= 0) {
23627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position += posMatch;
23637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (negMatch >= 0) {
23647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position += negMatch;
23657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
23667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setErrorIndex(position);
23677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
23687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
23697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Match padding after prefix
23717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
23727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position = skipPadding(text, position);
23737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
23747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // process digits or Inf, find decimal position
23767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        status[STATUS_INFINITE] = false;
23777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (text.regionMatches(position, symbols.getInfinity(), 0,
23787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                              symbols.getInfinity().length())) {
23797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position += symbols.getInfinity().length();
23807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            status[STATUS_INFINITE] = true;
23817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
23827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // We now have a string of digits, possibly with grouping symbols, and decimal
23837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // points. We want to process these into a DigitList.  We don't want to put a
23847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // bunch of leading zeros into the DigitList though, so we keep track of the
23857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // location of the decimal point, put only significant digits into the
23867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // DigitList, and adjust the exponent as needed.
23877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digits.decimalAt = digits.count = 0;
23897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char [] digitSymbols = symbols.getDigitsLocal();
23907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char decimal = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
23917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
23927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char grouping = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
23937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    symbols.getGroupingSeparator() : symbols.getMonetaryGroupingSeparator();
23947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
23957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String exponentSep = symbols.getExponentSeparator();
23967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean sawDecimal = false;
23977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean sawGrouping = false;
23987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean sawExponent = false;
23997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean sawDigit = false;
24007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            long exponent = 0; // Set to the exponent value, if any
24017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int digit = 0;
24027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // strict parsing
24047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean strictParse = isParseStrict();
24057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean strictFail = false; // did we exit with a strict parse failure?
24067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int lastGroup = -1; // where did we last see a grouping separator?
24077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int digitStart = position; // where did the digit start?
24087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
24097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
24117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                getEquivalentDecimals(decimal, strictParse);
24127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
24137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators);
24147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // We have to track digitCount ourselves, because digits.count will pin when
24167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // the maximum allowable digits is reached.
24177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int digitCount = 0;
24187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int backup = -1;
24207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int ch;
24217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (; position < text.length(); position += UTF16.getCharCount(ch)) {
24227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ch = UTF16.charAt(text,position);
24237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // We recognize all digit ranges, not only the Latin digit range
24267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // '0'..'9'. We do so by using the UCharacter.digit() method, which
24277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // converts a valid Unicode digit to the range 0..9.
24287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                //
24297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // The character 'ch' may be a digit. If so, place its value from 0 to 9
24307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // in 'digit'. First try using the locale digit, which may or MAY NOT be a
24317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // standard Unicode digit range. If this fails, try using the standard
24327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Unicode digit ranges by calling UCharacter.digit(). If this also fails,
24337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // digit will have a value outside the range 0..9.
24347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digit = ch - digitSymbols[0];
24357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (digit < 0 || digit > 9)
24367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    digit = UCharacter.digit(ch, 10);
24377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (digit < 0 || digit > 9) {
24387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for ( digit = 0 ; digit < 10 ; digit++) {
24397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ( ch == digitSymbols[digit] )
24407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
24417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
24427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
24437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (digit == 0) {
24477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Cancel out backup setting (see grouping handler below)
24487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (strictParse && backup != -1) {
24497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // comma followed by digit, so group before comma is a secondary
24507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // group. If there was a group separator before that, the group
24517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // must == the secondary group length, else it can be <= the the
24527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // secondary group length.
24537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
24547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
24557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            strictFail = true;
24567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
24577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
24587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        lastGroup = backup;
24597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
24607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    backup = -1; // Do this BEFORE continue statement below!!!
24617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sawDigit = true;
24627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Handle leading zeros
24647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (digits.count == 0) {
24657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!sawDecimal) {
24667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Ignore leading zeros in integer part of number.
24677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
24687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
24697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // If we have seen the decimal, but no significant digits yet,
24717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // then we account for leading zeros by decrementing the
24727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // digits.decimalAt into negative values.
24737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        --digits.decimalAt;
24747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
24757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ++digitCount;
24767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        digits.append((char) (digit + '0'));
24777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
24787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
24797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                {
24807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (strictParse) {
24817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (backup != -1) {
24827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
24837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
24847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                strictFail = true;
24857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
24867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
24877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            lastGroup = backup;
24887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
24897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
24907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sawDigit = true;
24927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++digitCount;
24937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    digits.append((char) (digit + '0'));
24947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
24957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Cancel out backup setting (see grouping handler below)
24967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    backup = -1;
24977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (ch == decimal) {
24987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (strictParse) {
24997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (backup != -1 ||
25007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
25017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            strictFail = true;
25027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // If we're only parsing integers, or if we ALREADY saw the decimal,
25067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // then don't parse this one.
25077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (isParseIntegerOnly() || sawDecimal) {
25087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
25097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    digits.decimalAt = digitCount; // Not digits.count!
25117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sawDecimal = true;
25127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (isGroupingUsed() && ch == grouping) {
25137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (sawDecimal) {
25147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
25157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (strictParse) {
25177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((!sawDigit || backup != -1)) {
25187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // leading group, or two group separators in a row
25197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            strictFail = true;
25207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Ignore grouping characters, if we are using them, but require that
25247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // they be followed by a digit. Otherwise we backup and reprocess
25257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // them.
25267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    backup = position;
25277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sawGrouping = true;
25287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (!sawDecimal && decimalEquiv.contains(ch)) {
25297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (strictParse) {
25307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (backup != -1 ||
25317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
25327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            strictFail = true;
25337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // If we're only parsing integers, then don't parse this one.
25377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (isParseIntegerOnly())
25387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
25397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    digits.decimalAt = digitCount; // Not digits.count!
25407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
25417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Once we see a decimal separator character, we only accept that
25427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // decimal separator character from then on.
25437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    decimal = (char) ch;
25447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sawDecimal = true;
25457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(ch)) {
25467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (sawDecimal) {
25477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
25487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (strictParse) {
25507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((!sawDigit || backup != -1)) {
25517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // leading group, or two group separators in a row
25527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            strictFail = true;
25537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Once we see a grouping character, we only accept that grouping
25577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // character from then on.
25587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    grouping = (char) ch;
25597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
25607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Ignore grouping characters, if we are using them, but require that
25617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // they be followed by a digit. Otherwise we backup and reprocess
25627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // them.
25637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    backup = position;
25647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sawGrouping = true;
25657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (!sawExponent && text.regionMatches(true, position, exponentSep, 0, exponentSep.length())) {
25667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Parse sign, if present
25677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    boolean negExp = false;
25687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int pos = position + exponentSep.length();
25697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (pos < text.length()) {
25707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ch = UTF16.charAt(text,pos);
25717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (ch == symbols.getPlusSign()) {
25727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++pos;
25737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else if (ch == symbols.getMinusSign()) {
25747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++pos;
25757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            negExp = true;
25767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
25797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    DigitList exponentDigits = new DigitList();
25807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    exponentDigits.count = 0;
25817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    while (pos < text.length()) {
25827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        digit = UTF16.charAt(text,pos) - digitSymbols[0];
25837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (digit < 0 || digit > 9) {
25847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
25857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Should update reassign the value of 'ch' in the code: digit
25867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // = Character.digit(ch, 10); [Richard/GCL]
25877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            digit = UCharacter.digit(UTF16.charAt(text,pos), 10);
25887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (digit >= 0 && digit <= 9) {
25907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            exponentDigits.append((char) (digit + '0'));
25917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            pos += UTF16.getCharCount(UTF16.charAt(text,pos));
25927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
25937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
25977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (exponentDigits.count > 0) {
25987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // defer strict parse until we know we have a bona-fide exponent
25997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (strictParse) {
26007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (backup != -1 || lastGroup != -1) {
26017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                strictFail = true;
26027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
26037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
26047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
26057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Quick overflow check for exponential part.  Actual limit check
26077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // will be done later in this code.
26087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
26097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (negExp) {
26107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // set underflow flag
26117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                status[STATUS_UNDERFLOW] = true;
26127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
26137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // set infinite flag
26147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                status[STATUS_INFINITE] = true;
26157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
26167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
26177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            exponentDigits.decimalAt = exponentDigits.count;
26187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            exponent = exponentDigits.getLong();
26197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (negExp) {
26207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                exponent = -exponent;
26217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
26227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
26237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        position = pos; // Advance past the exponent
26247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        sawExponent = true;
26257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
26267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break; // Whether we fail or succeed, we exit this loop
26287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
26297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
26307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
26317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(digits.decimalAt == 0 && isDecimalPatternMatchRequired()) {
26347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if(this.formatPattern.indexOf(decimal) != -1) {
26357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    parsePosition.setIndex(oldStart);
26367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    parsePosition.setErrorIndex(position);
26377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return false;
26387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
26397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (backup != -1)
26427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                position = backup;
26437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // If there was no decimal point we have an integer
26457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!sawDecimal)
26467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digits.decimalAt = digitCount; // Not digits.count!
26477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // check for strict parse errors
26497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (strictParse && !sawDecimal) {
26507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1) {
26517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    strictFail = true;
26527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
26537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (strictFail) {
26557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // only set with strictParse and a leading zero error leading zeros are an
26567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // error with strict parsing except immediately before nondigit (except
26577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // group separator followed by digit), or end of text.
26587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                parsePosition.setIndex(oldStart);
26607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                parsePosition.setErrorIndex(position);
26617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return false;
26627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Adjust for exponent, if any
26657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent += digits.decimalAt;
26667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (exponent < -getParseMaxDigits()) {
26677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                status[STATUS_UNDERFLOW] = true;
26687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (exponent > getParseMaxDigits()) {
26697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                status[STATUS_INFINITE] = true;
26707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
26717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digits.decimalAt = (int) exponent;
26727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // If none of the text string was recognized. For example, parse "x" with
26757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // pattern "#0.00" (return index and error index both 0) parse "$" with
26767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // pattern "$#0.00". (return index 0 and error index 1).
26777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!sawDigit && digitCount == 0) {
26787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                parsePosition.setIndex(oldStart);
26797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                parsePosition.setErrorIndex(oldStart);
26807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return false;
26817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
26837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Match padding before suffix
26857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
26867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position = skipPadding(text, position);
26877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
26887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Match positive and negative suffixes; prefer longest match.
26907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (posMatch >= 0) {
26917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            posMatch = compareAffix(text, position, false, false, posSuffix, parseComplexCurrency, type, currency);
26927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
26937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (negMatch >= 0) {
26947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negMatch = compareAffix(text, position, true, false, negSuffix, parseComplexCurrency, type, currency);
26957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
26967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (posMatch >= 0 && negMatch >= 0) {
26977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (posMatch > negMatch) {
26987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                negMatch = -1;
26997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (negMatch > posMatch) {
27007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                posMatch = -1;
27017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
27027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Fail if neither or both
27057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if ((posMatch >= 0) == (negMatch >= 0)) {
27067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setErrorIndex(position);
27077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
27087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        position += (posMatch >= 0 ? posMatch : negMatch);
27117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Match padding after suffix
27137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
27147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            position = skipPadding(text, position);
27157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        parsePosition.setIndex(position);
27187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        status[STATUS_POSITIVE] = (posMatch >= 0);
27207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parsePosition.getIndex() == oldStart) {
27227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            parsePosition.setErrorIndex(position);
27237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
27247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return true;
27267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
27277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Utility method used to count the number of codepoints
27297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int countCodePoints(String str,int start, int end) {
27307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int count = 0;
27317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int index = start;
27327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while ( index < end ) {
27337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            count++;
27347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            index += UTF16.getCharCount(UTF16.charAt(str, index));
27357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return count;
27377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
27387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
27397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns a set of characters equivalent to the given desimal separator used for
27407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * parsing number.  This method may return an empty set.
27417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
27427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) {
27437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UnicodeSet equivSet = UnicodeSet.EMPTY;
27447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (strictParse) {
27457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (strictDotEquivalents.contains(decimal)) {
27467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                equivSet = strictDotEquivalents;
27477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (strictCommaEquivalents.contains(decimal)) {
27487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                equivSet = strictCommaEquivalents;
27497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
27507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
27517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (dotEquivalents.contains(decimal)) {
27527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                equivSet = dotEquivalents;
27537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (commaEquivalents.contains(decimal)) {
27547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                equivSet = commaEquivalents;
27557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
27567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return equivSet;
27587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
27597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
27617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Starting at position, advance past a run of pad characters, if any. Return the
27627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * index of the first character after position that is not a pad character. Result is
27637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * >= position.
27647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
27657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final int skipPadding(String text, int position) {
27667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (position < text.length() && text.charAt(position) == pad) {
27677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ++position;
27687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return position;
27707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
27717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
27727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
27737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the length matched by the given affix, or -1 if none. Runs of white space
27747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * in the affix, match runs of white space in the input. Pattern white space and input
27757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * white space are determined differently; see code.
27767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
27777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param text input text
27787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pos offset into input at which to begin matching
27797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param isNegative
27807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param isPrefix
27817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param affixPat affix pattern used for currency affix comparison
27827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param copmplexCurrencyParsing whether it is currency parsing or not
27837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param type compare against currency type, LONG_NAME only or not.
27847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param currency return value for parsed currency, for generic currency parsing
27857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * mode, or null for normal parsing.  In generic currency parsing mode, any currency
27867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is parsed, not just the currency that this formatter is set to.
27877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return length of input that matches, or -1 if match failure
27887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
27897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix,
27907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             String affixPat, boolean complexCurrencyParsing, int type, Currency[] currency) {
27917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currency != null || currencyChoice != null || (currencySignCount != CURRENCY_SIGN_COUNT_ZERO && complexCurrencyParsing)) {
27927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return compareComplexAffix(affixPat, text, pos, type, currency);
27937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isPrefix) {
27957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos);
27967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
27977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos);
27987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
27997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
28037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Check for bidi marks: LRM, RLM, ALM
28047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
28057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static boolean isBidiMark(int c) {
28067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (c==0x200E || c==0x200F || c==0x061C);
28077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
28107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Remove bidi marks from affix
28117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
28127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static String trimMarksFromAffix(String affix) {
28137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean hasBidiMark = false;
28147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int idx = 0;
28157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (; idx < affix.length(); idx++) {
28167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (isBidiMark(affix.charAt(idx))) {
28177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                hasBidiMark = true;
28187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
28197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
28207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!hasBidiMark) {
28227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return affix;
28237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuilder buf = new StringBuilder();
28267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        buf.append(affix, 0, idx);
28277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        idx++;  // skip the first Bidi mark
28287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (; idx < affix.length(); idx++) {
28297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char c = affix.charAt(idx);
28307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!isBidiMark(c)) {
28317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buf.append(c);
28327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
28337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return buf.toString();
28367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
28397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Return the length matched by the given affix, or -1 if none. Runs of white space in
28407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the affix, match runs of white space in the input. Pattern white space and input
28417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * white space are determined differently; see code.
28427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
28437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param affix pattern string, taken as a literal
28447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param input input text
28457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pos offset into input at which to begin matching
28467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return length of input that matches, or -1 if match failure
28477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
28487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int compareSimpleAffix(String affix, String input, int pos) {
28497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int start = pos;
28507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Affixes here might consist of sign, currency symbol and related spacing, etc.
28517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // For more efficiency we should keep lazily-created trimmed affixes around in
28527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // instance variables instead of trimming each time they are used (the next step).
28537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String trimmedAffix = (affix.length() > 1)? trimMarksFromAffix(affix): affix;
28547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < trimmedAffix.length();) {
28557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int c = UTF16.charAt(trimmedAffix, i);
28567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int len = UTF16.getCharCount(c);
28577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (PatternProps.isWhiteSpace(c)) {
28587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // We may have a pattern like: \u200F and input text like: \u200F Note
28597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // that U+200F and U+0020 are Pattern_White_Space but only U+0020 is
28607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // UWhiteSpace. So we have to first do a direct match of the run of RULE
28617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // whitespace in the pattern, then match any extra characters.
28627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean literalMatch = false;
28637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                while (pos < input.length()) {
28647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int ic = UTF16.charAt(input, pos);
28657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (ic == c) {
28667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        literalMatch = true;
28677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i += len;
28687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        pos += len;
28697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (i == trimmedAffix.length()) {
28707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
28717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
28727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        c = UTF16.charAt(trimmedAffix, i);
28737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        len = UTF16.getCharCount(c);
28747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!PatternProps.isWhiteSpace(c)) {
28757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
28767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
28777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (isBidiMark(ic)) {
28787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        pos++; // just skip over this input text
28797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
28807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
28817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
28827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
28837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Advance over run in trimmedAffix
28857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                i = skipPatternWhiteSpace(trimmedAffix, i);
28867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
28877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Advance over run in input text. Must see at least one white space char
28887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // in input, unless we've already matched some characters literally.
28897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int s = pos;
28907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                pos = skipUWhiteSpace(input, pos);
28917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (pos == s && !literalMatch) {
28927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return -1;
28937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
28947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // If we skip UWhiteSpace in the input text, we need to skip it in the
28957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // pattern.  Otherwise, the previous lines may have skipped over text
28967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // (such as U+00A0) that is also in the trimmedAffix.
28977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                i = skipUWhiteSpace(trimmedAffix, i);
28987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
28997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean match = false;
29007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                while (pos < input.length()) {
29017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int ic = UTF16.charAt(input, pos);
29027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!match && equalWithSignCompatibility(ic, c)) {
29037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i += len;
29047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        pos += len;
29057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        match = true;
29067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (isBidiMark(ic)) {
29077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        pos++; // just skip over this input text
29087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
29097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
29107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
29117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
29127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!match) {
29137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return -1;
29147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
29157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
29167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos - start;
29187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
29197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
29207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static boolean equalWithSignCompatibility(int lhs, int rhs) {
29217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return lhs == rhs
29227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || (minusSigns.contains(lhs) && minusSigns.contains(rhs))
29237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || (plusSigns.contains(lhs) && plusSigns.contains(rhs));
29247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
29257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
29267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
29277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Skips over a run of zero or more Pattern_White_Space characters at pos in text.
29287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
29297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int skipPatternWhiteSpace(String text, int pos) {
29307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (pos < text.length()) {
29317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int c = UTF16.charAt(text, pos);
29327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!PatternProps.isWhiteSpace(c)) {
29337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
29347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
29357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pos += UTF16.getCharCount(c);
29367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos;
29387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
29397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
29407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
29417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Skips over a run of zero or more isUWhiteSpace() characters at pos in text.
29427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
29437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int skipUWhiteSpace(String text, int pos) {
29447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (pos < text.length()) {
29457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int c = UTF16.charAt(text, pos);
29467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!UCharacter.isUWhiteSpace(c)) {
29477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
29487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
29497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pos += UTF16.getCharCount(c);
29507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos;
29527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
29537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
29547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     /**
29557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Skips over a run of zero or more bidi marks at pos in text.
29567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
29577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int skipBidiMarks(String text, int pos) {
29587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (pos < text.length()) {
29597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int c = UTF16.charAt(text, pos);
29607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!isBidiMark(c)) {
29617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
29627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
29637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pos += UTF16.getCharCount(c);
29647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos;
29667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
29677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
29687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert   /**
29697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the length matched by the given affix, or -1 if none.
29707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
29717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param affixPat pattern string
29727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param text input text
29737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pos offset into input at which to begin matching
29747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param type parse against currency type, LONG_NAME only or not.
29757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param currency return value for parsed currency, for generic
29767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency parsing mode, or null for normal parsing.  In generic
29777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency parsing mode, any currency is parsed, not just the
29787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency that this formatter is set to.
29797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return position after the matched text, or -1 if match failure
29807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
29817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int compareComplexAffix(String affixPat, String text, int pos, int type,
29827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    Currency[] currency) {
29837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int start = pos;
29847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < affixPat.length() && pos >= 0;) {
29857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char c = affixPat.charAt(i++);
29867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (c == QUOTE) {
29877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (;;) {
29887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int j = affixPat.indexOf(QUOTE, i);
29897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (j == i) {
29907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        pos = match(text, pos, QUOTE);
29917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i = j + 1;
29927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
29937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (j > i) {
29947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        pos = match(text, pos, affixPat.substring(i, j));
29957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i = j + 1;
29967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) {
29977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            pos = match(text, pos, QUOTE);
29987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++i;
29997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // loop again
30007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
30017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
30027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
30037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
30047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Unterminated quote; should be caught by apply
30057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // pattern.
30067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        throw new RuntimeException();
30077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
30087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
30097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
30107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
30117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch (c) {
30137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case CURRENCY_SIGN:
30147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // since the currency names in choice format is saved the same way as
30157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // other currency names, do not need to do currency choice parsing here.
30167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // the general currency parsing parse against all names, including names
30177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // in choice format.  assert(currency != null || (getCurrency() != null &&
30187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // currencyChoice != null));
30197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
30207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (intl) {
30217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++i;
30227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
30237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
30247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (plural) {
30257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++i;
30267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    intl = false;
30277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
30287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Parse generic currency -- anything for which we have a display name, or
30297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // any 3-letter ISO code.  Try to parse display name for our locale; first
30307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // determine our locale.  TODO: use locale in CurrencyPluralInfo
30317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ULocale uloc = getLocale(ULocale.VALID_LOCALE);
30327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (uloc == null) {
30337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // applyPattern has been called; use the symbols
30347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    uloc = symbols.getLocale(ULocale.VALID_LOCALE);
30357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
30367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Delegate parse of display name => ISO code to Currency
30377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ParsePosition ppos = new ParsePosition(pos);
30387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // using Currency.parse to handle mixed style parsing.
30397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String iso = Currency.parse(uloc, text, type, ppos);
30407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // If parse succeeds, populate currency[0]
30427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (iso != null) {
30437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (currency != null) {
30447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        currency[0] = Currency.getInstance(iso);
30457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
30467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // The formatter is currency-style but the client has not requested
30477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // the value of the parsed currency. In this case, if that value does
30487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // not match the formatter's current value, then the parse fails.
30497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        Currency effectiveCurr = getEffectiveCurrency();
30507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (iso.compareTo(effectiveCurr.getCurrencyCode()) != 0) {
30517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            pos = -1;
30527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
30537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
30547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
30557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    pos = ppos.getIndex();
30567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
30577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    pos = -1;
30587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
30597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
30607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case PATTERN_PERCENT:
30617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c = symbols.getPercent();
30627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
30637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case PATTERN_PER_MILLE:
30647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c = symbols.getPerMill();
30657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
30667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case PATTERN_MINUS:
30677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c = symbols.getMinusSign();
30687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
30697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
30707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pos = match(text, pos, c);
30717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (PatternProps.isWhiteSpace(c)) {
30727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                i = skipPatternWhiteSpace(affixPat, i);
30737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
30747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
30757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos - start;
30777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
30787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
30807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Matches a single character at text[pos] and return the index of the next character
30817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * upon success. Return -1 on failure. If ch is a Pattern_White_Space then match a run of
30827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * white space in text.
30837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
30847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int match(String text, int pos, int ch) {
30857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (pos < 0 || pos >= text.length()) {
30867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return -1;
30877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
30887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        pos = skipBidiMarks(text, pos);
30897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (PatternProps.isWhiteSpace(ch)) {
30907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Advance over run of white space in input text
30917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Must see at least one white space char in input
30927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int s = pos;
30937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pos = skipPatternWhiteSpace(text, pos);
30947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (pos == s) {
30957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return -1;
30967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
30977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return pos;
30987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
30997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (pos >= text.length() || UTF16.charAt(text, pos) != ch) {
31007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return -1;
31017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
31027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        pos = skipBidiMarks(text, pos + UTF16.getCharCount(ch));
31037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos;
31047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
31057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
31077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Matches a string at text[pos] and return the index of the next character upon
31087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * success. Return -1 on failure. Match a run of white space in str with a run of
31097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * white space in text.
31107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
31117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int match(String text, int pos, String str) {
31127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < str.length() && pos >= 0;) {
31137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int ch = UTF16.charAt(str, i);
31147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            i += UTF16.getCharCount(ch);
31157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pos = match(text, pos, ch);
31167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (PatternProps.isWhiteSpace(ch)) {
31177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                i = skipPatternWhiteSpace(str, i);
31187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
31197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
31207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pos;
31217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
31227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
31247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns a copy of the decimal format symbols used by this format.
31257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
31267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return desired DecimalFormatSymbols
31277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols
31287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
31297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
31307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public DecimalFormatSymbols getDecimalFormatSymbols() {
31317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
31327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // don't allow multiple references
31337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (DecimalFormatSymbols) symbols.clone();
31347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception foo) {
31357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null; // should never happen
31367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
31377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
31387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
31407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the decimal format symbols used by this format. The format uses a copy of the
31417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * provided symbols.
31427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
31437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newSymbols desired DecimalFormatSymbols
31447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols
31457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
31467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
31477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
31487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        symbols = (DecimalFormatSymbols) newSymbols.clone();
31497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setCurrencyForSymbols();
31507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expandAffixes(null);
31517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
31527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
31547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Update the currency object to match the symbols. This method is used only when the
31557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * caller has passed in a symbols object that may not be the default object for its
31567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * locale.
31577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
31587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void setCurrencyForSymbols() {
31597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Bug 4212072 Update the affix strings according to symbols in order to keep the
31617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // affix strings up to date.  [Richard/GCL]
31627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // With the introduction of the Currency object, the currency symbols in the DFS
31647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // object are ignored. For backward compatibility, we check any explicitly set DFS
31657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // object. If it is a default symbols object for its locale, we change the
31667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // currency object to one for that locale. If it is custom, we set the currency to
31677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // null.
31687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getULocale());
31697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())
31717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && symbols.getInternationalCurrencySymbol()
31727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                       .equals(def.getInternationalCurrencySymbol())) {
31737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setCurrency(Currency.getInstance(symbols.getULocale()));
31747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
31757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setCurrency(null);
31767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
31777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
31787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
31807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the positive prefix.
31817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
31827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: +123, $123, sFr123
31837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the prefix
31847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
31857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
31867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getPositivePrefix() {
31877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return positivePrefix;
31887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
31897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
31907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
31917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the positive prefix.
31927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
31937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: +123, $123, sFr123
31947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue the prefix
31957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
31967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
31977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setPositivePrefix(String newValue) {
31987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        positivePrefix = newValue;
31997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        posPrefixPattern = null;
32007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the negative prefix.
32047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
32067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the prefix
32087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getNegativePrefix() {
32117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return negativePrefix;
32127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the negative prefix.
32167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: -123, ($123) (with negative suffix), sFr-123
32187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue the prefix
32197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setNegativePrefix(String newValue) {
32227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        negativePrefix = newValue;
32237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        negPrefixPattern = null;
32247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the positive suffix.
32287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Example: 123%
32307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the suffix
32327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getPositiveSuffix() {
32357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return positiveSuffix;
32367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the positive suffix.
32407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Example: 123%
32427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue the suffix
32437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setPositiveSuffix(String newValue) {
32467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        positiveSuffix = newValue;
32477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        posSuffixPattern = null;
32487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the negative suffix.
32527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: -123%, ($123) (with positive suffixes)
32547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the suffix
32567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String getNegativeSuffix() {
32597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return negativeSuffix;
32607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the positive suffix.
32647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: 123%
32667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue the suffix
32677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setNegativeSuffix(String newValue) {
32707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        negativeSuffix = newValue;
32717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        negSuffixPattern = null;
32727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
32767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
32777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
32787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 1000.
32797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
32817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the multiplier
32837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
32857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getMultiplier() {
32867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return multiplier;
32877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
32887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
32897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
32907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
32917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
32927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
32937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 1000.
32947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
32967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
32977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue the multiplier
32987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
32997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
33007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMultiplier(int newValue) {
33017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (newValue == 0) {
33027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Bad multiplier: " + newValue);
33037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
33047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        multiplier = newValue;
33057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
33067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
33077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
33087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the rounding increment.
33097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
33107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return A positive rounding increment, or <code>null</code> if a custom rounding
33117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * increment is not in effect.
33127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingIncrement
33137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingMode
33147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingMode
33157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
33167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
33177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public java.math.BigDecimal getRoundingIncrement() {
33187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingIncrementICU == null)
33197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
33207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return roundingIncrementICU.toBigDecimal();
33217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
33227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
33237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
33247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers
33257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * will be rounded to the number of digits displayed.
33267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
33277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue A positive rounding increment, or <code>null</code> or
33287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigDecimal(0.0)</code> to use the default rounding increment.
33297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
33307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingIncrement
33317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingMode
33327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingMode
33337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
33347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
33357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setRoundingIncrement(java.math.BigDecimal newValue) {
33367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (newValue == null) {
33377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setRoundingIncrement((BigDecimal) null);
33387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
33397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setRoundingIncrement(new BigDecimal(newValue));
33407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
33417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
33427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
33437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
33447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers
33457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * will be rounded to the number of digits displayed.
33467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
33477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue A positive rounding increment, or <code>null</code> or
33487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigDecimal(0.0)</code> to use the default rounding increment.
33497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
33507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingIncrement
33517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingMode
33527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingMode
33537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.6
33547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
33557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setRoundingIncrement(BigDecimal newValue) {
33567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO);
33577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (i < 0) {
33587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Illegal rounding increment");
33597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
33607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (i == 0) {
33617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInternalRoundingIncrement(null);
33627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
33637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInternalRoundingIncrement(newValue);
33647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
33657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        resetActualRounding();
33667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
33677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
33687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
33697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers
33707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * will be rounded to the number of digits displayed.
33717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
33727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue A positive rounding increment, or 0.0 to use the default
33737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * rounding increment.
33747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
33757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingIncrement
33767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingMode
33777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingMode
33787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
33797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
33807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setRoundingIncrement(double newValue) {
33817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (newValue < 0.0) {
33827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Illegal rounding increment");
33837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
33847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (newValue == 0.0d) {
33857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInternalRoundingIncrement((BigDecimal) null);
33867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
33877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Should use BigDecimal#valueOf(double) instead of constructor
33887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // to avoid the double precision problem.
33897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInternalRoundingIncrement(BigDecimal.valueOf(newValue));
33907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
33917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        resetActualRounding();
33927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
33937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
33947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
33957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the rounding mode.
33967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
33977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
33987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
33997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingIncrement
34007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingIncrement
34017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingMode
34027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see java.math.BigDecimal
34037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
34047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
34057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
34067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getRoundingMode() {
34077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return roundingMode;
34087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
34097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
34107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
34117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the rounding mode. This has no effect unless the rounding increment is greater
34127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * than zero.
34137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
34147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
34157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
34167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
34177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setRoundingIncrement
34187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingIncrement
34197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getRoundingMode
34207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see java.math.BigDecimal
34217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
34227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
34237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
34247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setRoundingMode(int roundingMode) {
34257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
34267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);
34277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
34287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
34297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.roundingMode = roundingMode;
34307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        resetActualRounding();
34317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
34327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
34337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
34347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the width to which the output of <code>format()</code> is padded. The width is
34357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * counted in 16-bit code units.
34367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
34377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the format width, or zero if no padding is in effect
34387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setFormatWidth
34397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadCharacter
34407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadCharacter
34417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
34427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
34437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
34447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
34457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getFormatWidth() {
34467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return formatWidth;
34477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
34487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
34497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
34507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the width to which the output of <code>format()</code> is
34517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * padded. The width is counted in 16-bit code units.  This method
34527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * also controls whether padding is enabled.
34537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
34547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param width the width to which to pad the result of
34557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>format()</code>, or zero to disable padding
34567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @exception IllegalArgumentException if <code>width</code> is < 0
34577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getFormatWidth
34587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadCharacter
34597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadCharacter
34607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
34617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
34627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
34637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
34647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setFormatWidth(int width) {
34657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (width < 0) {
34667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Illegal format width");
34677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
34687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatWidth = width;
34697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
34707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
34717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
34727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the character used to pad to the format width. The default is ' '.
34737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
34747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the pad character
34757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setFormatWidth
34767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getFormatWidth
34777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadCharacter
34787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
34797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
34807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
34817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
34827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public char getPadCharacter() {
34837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return pad;
34847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
34857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
34867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
34877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the character used to pad to the format width. If padding is not
34887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * enabled, then this will take effect if padding is later enabled.
34897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
34907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param padChar the pad character
34917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setFormatWidth
34927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getFormatWidth
34937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadCharacter
34947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
34957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
34967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
34977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
34987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setPadCharacter(char padChar) {
34997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        pad = padChar;
35007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
35017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
35027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
35037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the position at which padding will take place. This is the location at
35047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * which padding will be inserted if the result of <code>format()</code> is shorter
35057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * than the format width.
35067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
35077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
35087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
35097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         <code>PAD_AFTER_SUFFIX</code>.
35107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setFormatWidth
35117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getFormatWidth
35127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadCharacter
35137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadCharacter
35147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
35157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_PREFIX
35167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_PREFIX
35177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_SUFFIX
35187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_SUFFIX
35197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
35207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
35217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getPadPosition() {
35227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return padPosition;
35237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
35247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
35257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
35267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the position at which padding will take place. This is the location at
35277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * which padding will be inserted if the result of <code>format()</code> is shorter
35287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * than the format width. This has no effect unless padding is enabled.
35297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
35307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
35317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
35327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>PAD_AFTER_SUFFIX</code>.
35337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @exception IllegalArgumentException if the pad position in unrecognized
35347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setFormatWidth
35357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getFormatWidth
35367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadCharacter
35377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadCharacter
35387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
35397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_PREFIX
35407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_PREFIX
35417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_SUFFIX
35427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_SUFFIX
35437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
35447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
35457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setPadPosition(int padPos) {
35467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
35477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Illegal pad position");
35487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
35497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        padPosition = padPos;
35507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
35517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
35527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
35537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns whether or not scientific notation is used.
35547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
35557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if this object formats and parses scientific notation
35567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setScientificNotation
35577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMinimumExponentDigits
35587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setMinimumExponentDigits
35597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isExponentSignAlwaysShown
35607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setExponentSignAlwaysShown
35617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
35627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
35637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isScientificNotation() {
35647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return useExponentialNotation;
35657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
35667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
35677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
35687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets whether or not scientific notation is used. When scientific notation is
35697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * used, the effective maximum number of integer digits is <= 8. If the maximum number
35707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * of integer digits is set to more than 8, the effective maximum will be 1. This
35717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * allows this call to generate a 'default' scientific number format without
35727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * additional changes.
35737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
35747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param useScientific true if this object formats and parses scientific notation
35757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isScientificNotation
35767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMinimumExponentDigits
35777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setMinimumExponentDigits
35787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isExponentSignAlwaysShown
35797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setExponentSignAlwaysShown
35807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
35817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
35827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setScientificNotation(boolean useScientific) {
35837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        useExponentialNotation = useScientific;
35847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
35857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
35867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
35877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the minimum exponent digits that will be shown.
35887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
35897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the minimum exponent digits that will be shown
35907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setScientificNotation
35917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isScientificNotation
35927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setMinimumExponentDigits
35937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isExponentSignAlwaysShown
35947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setExponentSignAlwaysShown
35957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
35967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
35977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public byte getMinimumExponentDigits() {
35987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return minExponentDigits;
35997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
36007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
36017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
36027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the minimum exponent digits that will be shown. This has no effect
36037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * unless scientific notation is in use.
36047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
36057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param minExpDig a value >= 1 indicating the fewest exponent
36067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * digits that will be shown
36077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @exception IllegalArgumentException if <code>minExpDig</code> < 1
36087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setScientificNotation
36097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isScientificNotation
36107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMinimumExponentDigits
36117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isExponentSignAlwaysShown
36127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setExponentSignAlwaysShown
36137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
36147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
36157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMinimumExponentDigits(byte minExpDig) {
36167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (minExpDig < 1) {
36177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("Exponent digits must be >= 1");
36187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
36197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        minExponentDigits = minExpDig;
36207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
36217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
36227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
36237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns whether the exponent sign is always shown.
36247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
36257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if the exponent is always prefixed with either the localized minus
36267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * sign or the localized plus sign, false if only negative exponents are prefixed with
36277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the localized minus sign.
36287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setScientificNotation
36297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isScientificNotation
36307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setMinimumExponentDigits
36317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMinimumExponentDigits
36327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setExponentSignAlwaysShown
36337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
36347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
36357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isExponentSignAlwaysShown() {
36367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return exponentSignAlwaysShown;
36377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
36387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
36397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
36407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets whether the exponent sign is always shown. This has no effect unless
36417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * scientific notation is in use.
36427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
36437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param expSignAlways true if the exponent is always prefixed with either the
36447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * localized minus sign or the localized plus sign, false if only negative exponents
36457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * are prefixed with the localized minus sign.
36467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setScientificNotation
36477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isScientificNotation
36487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setMinimumExponentDigits
36497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMinimumExponentDigits
36507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isExponentSignAlwaysShown
36517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
36527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
36537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setExponentSignAlwaysShown(boolean expSignAlways) {
36547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        exponentSignAlwaysShown = expSignAlways;
36557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
36567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
36577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
36587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the grouping size. Grouping size is the number of digits between grouping
36597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * separators in the integer portion of a number. For example, in the number
36607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * "123,456.78", the grouping size is 3.
36617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
36627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setGroupingSize
36637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#isGroupingUsed
36647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols#getGroupingSeparator
36657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
36667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
36677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getGroupingSize() {
36687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return groupingSize;
36697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
36707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
36717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
36727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the grouping size. Grouping size is the number of digits between grouping
36737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * separators in the integer portion of a number. For example, in the number
36747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * "123,456.78", the grouping size is 3.
36757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
36767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getGroupingSize
36777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#setGroupingUsed
36787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols#setGroupingSeparator
36797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
36807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
36817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setGroupingSize(int newValue) {
36827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        groupingSize = (byte) newValue;
36837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
36847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
36857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
36867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the secondary grouping size. In some locales one grouping interval
36877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is used for the least significant integer digits (the primary grouping size), and
36887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * another is used for all others (the secondary grouping size). A formatter
36897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * supporting a secondary grouping size will return a positive integer unequal to the
36907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
36917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the primary grouping size is 4, and the secondary grouping size is 2, then the
36927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
36937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
36947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the secondary grouping size, or a value less than one if there is none
36957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setSecondaryGroupingSize
36967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#isGroupingUsed
36977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols#getGroupingSeparator
36987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
36997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getSecondaryGroupingSize() {
37017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return groupingSize2;
37027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the secondary grouping size. If set to a value less than 1, then
37067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * secondary grouping is turned off, and the primary grouping size is used for all
37077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * intervals, not just the least significant.
37087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
37097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getSecondaryGroupingSize
37107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#setGroupingUsed
37117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols#setGroupingSeparator
37127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
37137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setSecondaryGroupingSize(int newValue) {
37157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        groupingSize2 = (byte) newValue;
37167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the MathContext used by this format.
37207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
37217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return desired MathContext
37227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMathContext
37237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
37247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public MathContext getMathContextICU() {
37267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return mathContext;
37277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the MathContext used by this format.
37317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
37327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return desired MathContext
37337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMathContext
37347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
37357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public java.math.MathContext getMathContext() {
37377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
37387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // don't allow multiple references
37397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(),
37407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
37417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception foo) {
37427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null; // should never happen
37437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
37447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the MathContext used by this format.
37487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
37497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue desired MathContext
37507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMathContext
37517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
37527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMathContextICU(MathContext newValue) {
37547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        mathContext = newValue;
37557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the MathContext used by this format.
37597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
37607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newValue desired MathContext
37617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMathContext
37627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
37637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMathContext(java.math.MathContext newValue) {
37657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false,
37667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                      (newValue.getRoundingMode()).ordinal());
37677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the behavior of the decimal separator with integers. (The decimal
37717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 ->
37727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 12345.; OFF: 12345 -> 12345
37737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
37747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
37757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isDecimalSeparatorAlwaysShown() {
37777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return decimalSeparatorAlwaysShown;
37787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
37797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * When decimal match is not required, the input does not have to
37827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * contain a decimal mark when there is a decimal mark specified in the
37837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * pattern.
37847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param value true if input must contain a match to decimal mark in pattern
37857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Default is false.
37867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @draft ICU 54
37877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @provisional This API might change or be removed in a future release.
37887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
37897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     public void setDecimalPatternMatchRequired(boolean value) {
37907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         parseRequireDecimalPoint = value;
37917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     }
37927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
37937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
37947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns whether the input to parsing must contain a decimal mark if there
37957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is a decimal mark in the pattern.
37967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if input must contain a match to decimal mark in pattern
37977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @draft ICU 54
37987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @provisional This API might change or be removed in a future release.
37997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
38007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isDecimalPatternMatchRequired() {
38017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return parseRequireDecimalPoint;
38027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
38037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
38067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the behavior of the decimal separator with integers. (The decimal separator
38077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * will always appear with decimals.)
38087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
38097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>This only affects formatting, and only where there might be no digits after the
38107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This
38117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is independent of parsing. If you want parsing to stop at the decimal point, use
38127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * setParseIntegerOnly.
38137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
38147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>
38157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
38167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
38177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
38187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
38197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
38207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        decimalSeparatorAlwaysShown = newValue;
38217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
38227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
38247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might
38257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * return null if the decimal format is not a plural type currency decimal
38267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * format. Plural type currency decimal format means either the pattern in the decimal
38277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * format contains 3 currency signs, or the decimal format is initialized with
38287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * PLURALCURRENCYSTYLE.
38297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
38307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return desired CurrencyPluralInfo
38317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see CurrencyPluralInfo
38327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
38337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
38347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CurrencyPluralInfo getCurrencyPluralInfo() {
38357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
38367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // don't allow multiple references
38377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return currencyPluralInfo == null ? null :
38387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                (CurrencyPluralInfo) currencyPluralInfo.clone();
38397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception foo) {
38407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null; // should never happen
38417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
38427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
38437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
38457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of
38467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the provided information.
38477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
38487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newInfo desired CurrencyPluralInfo
38497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see CurrencyPluralInfo
38507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 4.2
38517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
38527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
38537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
38547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        isReadyForParsing = false;
38557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
38567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
38587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Overrides clone.
38597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
38607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
38617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
38627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Object clone() {
38637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        try {
38647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            DecimalFormat other = (DecimalFormat) super.clone();
38657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            other.symbols = (DecimalFormatSymbols) symbols.clone();
38667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            other.digitList = new DigitList(); // fix for JB#5358
38677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (currencyPluralInfo != null) {
38687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
38697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
38707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            other.attributes = new ArrayList<FieldPosition>(); // #9240
38717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            other.currencyUsage = currencyUsage;
38727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // TODO: We need to figure out whether we share a single copy of DigitList by
38747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // multiple cloned copies.  format/subformat are designed to use a single
38757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // instance, but parse/subparse implementation is not.
38767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return other;
38777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } catch (Exception e) {
38787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalStateException();
38797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
38807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
38817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
38837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Overrides equals.
38847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
38857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
38867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
38877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean equals(Object obj) {
38887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (obj == null)
38897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
38907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!super.equals(obj))
38917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false; // super does class check
38927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
38937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        DecimalFormat other = (DecimalFormat) obj;
38947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Add the comparison of the four new added fields ,they are posPrefixPattern,
38957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL]
38967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // following are added to accomodate changes for currency plural format.
38977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return currencySignCount == other.currencySignCount
38987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && (style != NumberFormat.PLURALCURRENCYSTYLE ||
38997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    equals(posPrefixPattern, other.posPrefixPattern)
39007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && equals(posSuffixPattern, other.posSuffixPattern)
39017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && equals(negPrefixPattern, other.negPrefixPattern)
39027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && equals(negSuffixPattern, other.negSuffixPattern))
39037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && multiplier == other.multiplier
39047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && groupingSize == other.groupingSize
39057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && groupingSize2 == other.groupingSize2
39067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
39077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && useExponentialNotation == other.useExponentialNotation
39087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
39097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && useSignificantDigits == other.useSignificantDigits
39107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
39117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        && maxSignificantDigits == other.maxSignificantDigits)
39127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && symbols.equals(other.symbols)
39137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo)
39147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && currencyUsage.equals(other.currencyUsage);
39157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
39167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
39177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // method to unquote the strings and compare
39187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean equals(String pat1, String pat2) {
39197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (pat1 == null || pat2 == null) {
39207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (pat1 == null && pat2 == null);
39217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
39227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // fast path
39237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (pat1.equals(pat2)) {
39247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
39257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
39267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return unquote(pat1).equals(unquote(pat2));
39277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
39287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
39297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String unquote(String pat) {
39307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuilder buf = new StringBuilder(pat.length());
39317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i = 0;
39327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (i < pat.length()) {
39337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char ch = pat.charAt(i++);
39347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (ch != QUOTE) {
39357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buf.append(ch);
39367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
39377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
39387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return buf.toString();
39397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
39407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
39417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // protected void handleToString(StringBuffer buf) {
39427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
39437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("positivePrefix: '" + positivePrefix + "'\n");
39447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
39457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
39467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("negPrefixPattern: '" +
39477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //     com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
39487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("negativePrefix: '" +
39497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //     com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
39507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
39517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
39527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("multiplier: '" + multiplier + "'\n");
39537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("groupingSize: '" + groupingSize + "'\n");
39547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("groupingSize2: '" + groupingSize2 + "'\n");
39557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
39567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
39577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
39587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
39597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
39607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
39617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // buf.append("symbols: '" + symbols + "'");
39627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // }
39637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
39647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
39657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Overrides hashCode.
39667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
39677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
39687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
39697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int hashCode() {
39707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return super.hashCode() * 37 + positivePrefix.hashCode();
39717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // just enough fields for a reasonable distribution
39727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
39737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
39747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
39757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Synthesizes a pattern string that represents the current state of this Format
39767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * object.
39777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
39787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #applyPattern
39797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
39807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
39817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String toPattern() {
39827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
39837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // the prefix or suffix pattern might not be defined yet, so they can not be
39847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // synthesized, instead, get them directly.  but it might not be the actual
39857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // pattern used in formatting.  the actual pattern used in formatting depends
39867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // on the formatted number's plural count.
39877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return formatPattern;
39887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
39897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return toPattern(false);
39907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
39917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
39927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
39937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Synthesizes a localized pattern string that represents the current state of this
39947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Format object.
39957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
39967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #applyPattern
39977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
39987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
39997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String toLocalizedPattern() {
40007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (style == NumberFormat.PLURALCURRENCYSTYLE) {
40017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return formatPattern;
40027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
40037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return toPattern(true);
40047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
40057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
40067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
40077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Expands the affix pattern strings into the expanded affix strings. If any affix
40087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * pattern string is null, do not expand it. This method should be called any time the
40097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * symbols or the affix patterns change in order to keep the expanded affix strings up
40107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * to date. This method also will be called before formatting if format currency
40117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * plural names, since the plural name is not a static one, it is based on the
40127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency plural count, the affix will be known only after the currency plural count
40137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is know. In which case, the parameter 'pluralCount' will be a non-null currency
40147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * plural count. In all other cases, the 'pluralCount' is null, which means it is not
40157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * needed.
40167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
40177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Bug 4212072 [Richard/GCL]
40187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void expandAffixes(String pluralCount) {
40197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // expandAffix() will set currencyChoice to a non-null value if
40207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // appropriate AND if it is null.
40217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        currencyChoice = null;
40227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
40237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Reuse one StringBuffer for better performance
40247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer buffer = new StringBuffer();
40257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (posPrefixPattern != null) {
40267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffix(posPrefixPattern, pluralCount, buffer, false);
40277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            positivePrefix = buffer.toString();
40287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
40297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (posSuffixPattern != null) {
40307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffix(posSuffixPattern, pluralCount, buffer, false);
40317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            positiveSuffix = buffer.toString();
40327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
40337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (negPrefixPattern != null) {
40347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffix(negPrefixPattern, pluralCount, buffer, false);
40357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negativePrefix = buffer.toString();
40367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
40377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (negSuffixPattern != null) {
40387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffix(negSuffixPattern, pluralCount, buffer, false);
40397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negativeSuffix = buffer.toString();
40407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
40417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
40427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
40437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
40447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Expands an affix pattern into an affix string. All characters in the pattern are
40457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * literal unless bracketed by QUOTEs. The following characters outside QUOTE are
40467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
40477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international
40487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural
40497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * long names, such as "US Dollars". Any other character outside QUOTE represents
40507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * itself. Quoted text must be well-formed.
40517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
40527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This method is used in two distinct ways. First, it is used to expand the stored
40537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * affix patterns into actual affixes. For this usage, doFormat must be false. Second,
40547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * it is used to expand the stored affix patterns given a specific number (doFormat ==
40557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * true), for those rare cases in which a currency format references a ChoiceFormat
40567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * (e.g., en_IN display name for INR). The number itself is taken from digitList.
40577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
40587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * When used in the first way, this method has a side effect: It sets currencyChoice
40597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * to a ChoiceFormat object, if the currency's display name in this locale is a
40607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to
40617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * start with.
40627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
40637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pattern the non-null, possibly empty pattern
40647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param pluralCount the plural count. It is only used for currency plural format. In
40657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * which case, it is the plural count of the currency amount. For example, in en_US,
40667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * it is the singular "one", or the plural "other". For all other cases, it is null,
40677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * and is not being used.
40687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param buffer a scratch StringBuffer; its contents will be lost
40697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param doFormat if false, then the pattern will be expanded, and if a currency
40707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * symbol is encountered that expands to a ChoiceFormat, the currencyChoice member
40717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * variable will be initialized if it is null. If doFormat is true, then it is assumed
40727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * that the currencyChoice has been created, and it will be used to format the value
40737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * in digitList.
40747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
40757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Bug 4212072 [Richard/GCL]
40767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void expandAffix(String pattern, String pluralCount, StringBuffer buffer,
40777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             boolean doFormat) {
40787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        buffer.setLength(0);
40797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < pattern.length();) {
40807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char c = pattern.charAt(i++);
40817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (c == QUOTE) {
40827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (;;) {
40837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int j = pattern.indexOf(QUOTE, i);
40847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (j == i) {
40857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        buffer.append(QUOTE);
40867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i = j + 1;
40877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
40887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (j > i) {
40897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        buffer.append(pattern.substring(i, j));
40907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        i = j + 1;
40917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (i < pattern.length() && pattern.charAt(i) == QUOTE) {
40927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer.append(QUOTE);
40937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++i;
40947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // loop again
40957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
40967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
40977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
40987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
40997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Unterminated quote; should be caught by apply
41007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // pattern.
41017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        throw new RuntimeException();
41027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
41037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
41047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
41057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
41067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
41077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch (c) {
41087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case CURRENCY_SIGN:
41097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // As of ICU 2.2 we use the currency object, and ignore the currency
41107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // symbols in the DFS, unless we have a null currency object. This occurs
41117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // if resurrecting a pre-2.2 object or if the user sets a custom DFS.
41127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN;
41137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean plural = false;
41147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (intl) {
41157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++i;
41167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) {
41177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        plural = true;
41187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        intl = false;
41197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ++i;
41207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
41217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
41227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String s = null;
41237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                Currency currency = getCurrency();
41247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (currency != null) {
41257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // plural name is only needed when pluralCount != null, which means
41267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // when formatting currency plural names.  For other cases,
41277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // pluralCount == null, and plural names are not needed.
41287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (plural && pluralCount != null) {
41297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        boolean isChoiceFormat[] = new boolean[1];
41307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,
41317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                             pluralCount, isChoiceFormat);
41327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (!intl) {
41337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        boolean isChoiceFormat[] = new boolean[1];
41347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME,
41357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                             isChoiceFormat);
41367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (isChoiceFormat[0]) {
41377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Two modes here: If doFormat is false, we set up
41387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // currencyChoice. If doFormat is true, we use the previously
41397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // created currencyChoice to format the value in digitList.
41407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (!doFormat) {
41417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // If the currency is handled by a ChoiceFormat, then
41427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // we're not going to use the expanded
41437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // patterns. Instantiate the ChoiceFormat and return.
41447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (currencyChoice == null) {
41457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    currencyChoice = new ChoiceFormat(s);
41467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
41477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // We could almost return null or "" here, since the
41487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // expanded affixes are almost not used at all in this
41497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // situation. However, one method -- toPattern() -- still
41507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // does use the expanded affixes, in order to set up a
41517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // padding pattern. We use the CURRENCY_SIGN as a
41527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // placeholder.
41537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                s = String.valueOf(CURRENCY_SIGN);
41547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
41557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                FieldPosition pos = new FieldPosition(0); // ignored
41567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                currencyChoice.format(digitList.getDouble(), buffer, pos);
41577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                continue;
41587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
41597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
41607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
41617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        s = currency.getCurrencyCode();
41627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
41637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
41647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    s = intl ? symbols.getInternationalCurrencySymbol() :
41657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        symbols.getCurrencySymbol();
41667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
41677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buffer.append(s);
41687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
41697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case PATTERN_PERCENT:
41707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c = symbols.getPercent();
41717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
41727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case PATTERN_PER_MILLE:
41737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c = symbols.getPerMill();
41747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
41757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case PATTERN_MINUS:
41767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String minusString = symbols.getMinusString();
41777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buffer.append(minusString);
41787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                continue;
41797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
41807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            buffer.append(c);
41817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
41827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
41837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
41847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
41857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Append an affix to the given StringBuffer.
41867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
41877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param buf
41887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            buffer to append to
41897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param isNegative
41907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param isPrefix
41917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
41927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,
41937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            boolean parseAttr) {
41947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencyChoice != null) {
41957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String affixPat = null;
41967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (isPrefix) {
41977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
41987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
41997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
42007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
42017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StringBuffer affixBuf = new StringBuffer();
42027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            expandAffix(affixPat, null, affixBuf, true);
42037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            buf.append(affixBuf);
42047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return affixBuf.length();
42057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
42067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String affix = null;
42087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isPrefix) {
42097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            affix = isNegative ? negativePrefix : positivePrefix;
42107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
42117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            affix = isNegative ? negativeSuffix : positiveSuffix;
42127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
42137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
42147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (parseAttr) {
42157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int offset = affix.indexOf(symbols.getCurrencySymbol());
42167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (-1 == offset) {
42177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                offset = affix.indexOf(symbols.getPercent());
42187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (-1 == offset) {
42197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    offset = 0;
42207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
42217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
42227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length());
42237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
42247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        buf.append(affix);
42257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return affix.length();
42267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
42277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
42297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * [Spark/CDL] This is a newly added method, used to add attributes for prefix and
42307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * suffix.
42317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
42327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void formatAffix2Attribute(String affix, int begin, int end) {
42337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // [Spark/CDL] It is the invoker's responsibility to ensure that, before the
42347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // invocation of this method, attributes is not null.  if( attributes == null )
42357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // return;
42367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
42377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.CURRENCY, begin, end);
42387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
42397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.SIGN, begin, end);
42407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (affix.indexOf(symbols.getPercent()) > -1) {
42417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.PERCENT, begin, end);
42427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (affix.indexOf(symbols.getPerMill()) > -1) {
42437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            addAttribute(Field.PERMILLE, begin, end);
42447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
42457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
42467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
42487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * [Spark/CDL] Use this method to add attribute.
42497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
42507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void addAttribute(Field field, int begin, int end) {
42517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        FieldPosition pos = new FieldPosition(field);
42527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        pos.setBeginIndex(begin);
42537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        pos.setEndIndex(end);
42547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        attributes.add(pos);
42557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
42567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
42587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Formats the object to an attributed string, and return the corresponding iterator.
42597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
42607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.6
42617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
42627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
42637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
42647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert      return formatToCharacterIterator(obj, NULL_UNIT);
42657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
42667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    AttributedCharacterIterator formatToCharacterIterator(Object obj, Unit unit) {
42687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!(obj instanceof Number))
42697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException();
42707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Number number = (Number) obj;
42717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer text = new StringBuffer();
42727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        unit.writePrefix(text);
42737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        attributes.clear();
42747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (obj instanceof BigInteger) {
42757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            format((BigInteger) number, text, new FieldPosition(0), true);
42767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (obj instanceof java.math.BigDecimal) {
42777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            format((java.math.BigDecimal) number, text, new FieldPosition(0)
42787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                          , true);
42797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (obj instanceof Double) {
42807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            format(number.doubleValue(), text, new FieldPosition(0), true);
42817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (obj instanceof Integer || obj instanceof Long) {
42827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            format(number.longValue(), text, new FieldPosition(0), true);
42837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
42847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException();
42857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
42867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        unit.writeSuffix(text);
42877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        AttributedString as = new AttributedString(text.toString());
42887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // add NumberFormat field attributes to the AttributedString
42907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int i = 0; i < attributes.size(); i++) {
42917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            FieldPosition pos = attributes.get(i);
42927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Format.Field attribute = pos.getFieldAttribute();
42937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());
42947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
42957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
42967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // return the CharacterIterator from AttributedString
42977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return as.getIterator();
42987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
42997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
43007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
43017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Appends an affix pattern to the given StringBuffer. Localize unquoted specials.
43027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
43037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,
43047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    boolean localized) {
43057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String affixPat = null;
43067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (isPrefix) {
43077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
43087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
43097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
43107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
43117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
43127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // When there is a null affix pattern, we use the affix itself.
43137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (affixPat == null) {
43147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String affix = null;
43157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (isPrefix) {
43167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                affix = isNegative ? negativePrefix : positivePrefix;
43177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
43187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                affix = isNegative ? negativeSuffix : positiveSuffix;
43197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
43207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Do this crudely for now: Wrap everything in quotes.
43217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            buffer.append(QUOTE);
43227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (int i = 0; i < affix.length(); ++i) {
43237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                char ch = affix.charAt(i);
43247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (ch == QUOTE) {
43257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer.append(ch);
43267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
43277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buffer.append(ch);
43287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
43297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            buffer.append(QUOTE);
43307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return;
43317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
43327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
43337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!localized) {
43347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            buffer.append(affixPat);
43357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
43367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int i, j;
43377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (i = 0; i < affixPat.length(); ++i) {
43387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                char ch = affixPat.charAt(i);
43397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                switch (ch) {
43407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case QUOTE:
43417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    j = affixPat.indexOf(QUOTE, i + 1);
43427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (j < 0) {
43437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
43447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
43457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer.append(affixPat.substring(i, j + 1));
43467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    i = j;
43477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    continue;
43487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PATTERN_PER_MILLE:
43497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ch = symbols.getPerMill();
43507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
43517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PATTERN_PERCENT:
43527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ch = symbols.getPercent();
43537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
43547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case PATTERN_MINUS:
43557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ch = symbols.getMinusSign();
43567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
43577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
43587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // check if char is same as any other symbol
43597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) {
43607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer.append(QUOTE);
43617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer.append(ch);
43627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer.append(QUOTE);
43637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
43647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer.append(ch);
43657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
43667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
43677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
43687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
43697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
43707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
43717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Does the real work of generating a pattern.
43727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
43737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String toPattern(boolean localized) {
43747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        StringBuffer result = new StringBuffer();
43757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
43767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
43777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char sigDigit = 0;
43787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean useSigDig = areSignificantDigitsUsed();
43797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (useSigDig) {
43807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
43817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
43827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR;
43837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i;
43847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
43857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String roundingDigits = null;
43867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int padPos = (formatWidth > 0) ? padPosition : -1;
43877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String padSpec = (formatWidth > 0)
43887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ? new StringBuffer(2).append(localized
43897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                         ? symbols.getPadEscape()
43907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                         : PATTERN_PAD_ESCAPE).append(pad).toString()
43917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            : null;
43927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingIncrementICU != null) {
43937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            i = roundingIncrementICU.scale();
43947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            roundingDigits = roundingIncrementICU.movePointRight(i).toString();
43957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            roundingDecimalPos = roundingDigits.length() - i;
43967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
43977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int part = 0; part < 2; ++part) {
43987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // variable not used int partStart = result.length();
43997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (padPos == PAD_BEFORE_PREFIX) {
44007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(padSpec);
44017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
44037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Use original symbols read from resources in pattern eg. use "\u00A4"
44047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // instead of "$" in Locale.US [Richard/GCL]
44057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            appendAffixPattern(result, part != 0, true, localized);
44067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (padPos == PAD_AFTER_PREFIX) {
44077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(padSpec);
44087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int sub0Start = result.length();
44107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
44117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
44127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                g += groupingSize2;
44137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int maxDig = 0, minDig = 0, maxSigDig = 0;
44157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (useSigDig) {
44167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                minDig = getMinimumSignificantDigits();
44177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxDig = maxSigDig = getMaximumSignificantDigits();
44187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
44197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                minDig = getMinimumIntegerDigits();
44207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxDig = getMaximumIntegerDigits();
44217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (useExponentialNotation) {
44237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
44247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    maxDig = 1;
44257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (useSigDig) {
44277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxDig = Math.max(maxDig, g + 1);
44287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
44297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1;
44307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            for (i = maxDig; i > 0; --i) {
44327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) {
44337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(group);
44347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (useSigDig) {
44367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos,
44377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // count from the right) Use # if pos > maxSigDig or 1 <= pos <=
44387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <=
44397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // maxSigDig
44407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
44417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
44427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (roundingDigits != null) {
44437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int pos = roundingDecimalPos - i;
44447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (pos >= 0 && pos < roundingDigits.length()) {
44457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
44467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
44477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
44487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
44497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(i <= minDig ? zero : digit);
44507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!useSigDig) {
44537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
44547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(localized ? symbols.getDecimalSeparator() :
44557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                  PATTERN_DECIMAL_SEPARATOR);
44567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int pos = roundingDecimalPos;
44587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (i = 0; i < getMaximumFractionDigits(); ++i) {
44597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (roundingDigits != null && pos < roundingDigits.length()) {
44607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        result.append(pos < 0 ? zero :
44617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                      (char) (roundingDigits.charAt(pos) - '0' + zero));
44627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ++pos;
44637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
44647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
44657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(i < getMinimumFractionDigits() ? zero : digit);
44667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (useExponentialNotation) {
44697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (localized) {
44707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(symbols.getExponentSeparator());
44717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
44727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(PATTERN_EXPONENT);
44737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (exponentSignAlwaysShown) {
44757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN);
44767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                for (i = 0; i < minExponentDigits; ++i) {
44787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(zero);
44797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
44817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (padSpec != null && !useExponentialNotation) {
44827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int add = formatWidth
44837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        - result.length()
44847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        + sub0Start
44857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        - ((part == 0)
44867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                           ? positivePrefix.length() + positiveSuffix.length()
44877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                           : negativePrefix.length() + negativeSuffix.length());
44887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                while (add > 0) {
44897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.insert(sub0Start, digit);
44907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++maxDig;
44917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    --add;
44927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Only add a grouping separator if we have at least 2 additional
44937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // characters to be added, so we don't end up with ",###".
44947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (add > 1 && isGroupingPosition(maxDig)) {
44957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        result.insert(sub0Start, group);
44967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        --add;
44977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
44987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
44997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
45007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (padPos == PAD_BEFORE_SUFFIX) {
45017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(padSpec);
45027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
45037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Use original symbols read from resources in pattern eg. use "\u00A4"
45047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // instead of "$" in Locale.US [Richard/GCL]
45057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            appendAffixPattern(result, part != 0, false, localized);
45067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (padPos == PAD_AFTER_SUFFIX) {
45077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.append(padSpec);
45087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
45097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (part == 0) {
45107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (negativeSuffix.equals(positiveSuffix) &&
45117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    negativePrefix.equals(PATTERN_MINUS + positivePrefix)) {
45127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
45137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
45147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);
45157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
45167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
45177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
45187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return result.toString();
45197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
45207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
45217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
45227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Applies the given pattern to this Format object. A pattern is a short-hand
45237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * specification for the various formatting properties. These properties can also be
45247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * changed individually through the various setter methods.
45257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>There is no limit to integer digits are set by this routine, since that is the
45277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
45287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * negative numbers, use a second pattern, separated by a semicolon
45297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Example "#,#00.0#" -> 1,234.56
45317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
45337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * fraction digits.
45347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
45367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
45387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * presumed to be set in the positive pattern.
45397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
45417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
45427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void applyPattern(String pattern) {
45437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPattern(pattern, false);
45447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
45457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
45467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
45477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Applies the given pattern to this Format object. The pattern is assumed to be in a
45487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * localized notation. A pattern is a short-hand specification for the various
45497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * formatting properties. These properties can also be changed individually through
45507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the various setter methods.
45517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>There is no limit to integer digits are set by this routine, since that is the
45537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * typical end-user desire; use setMaximumInteger if you want to set a real value. For
45547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * negative numbers, use a second pattern, separated by a semicolon
45557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Example "#,#00.0#" -> 1,234.56
45577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
45597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * fraction digits.
45607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
45627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>In negative patterns, the minimum and maximum counts are ignored; these are
45647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * presumed to be set in the positive pattern.
45657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
45667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
45677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
45687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void applyLocalizedPattern(String pattern) {
45697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPattern(pattern, true);
45707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
45717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
45727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
45737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Does the real work of applying a pattern.
45747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
45757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void applyPattern(String pattern, boolean localized) {
45767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        applyPatternWithoutExpandAffix(pattern, localized);
45777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expandAffixAdjustWidth(null);
45787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
45797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
45807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void expandAffixAdjustWidth(String pluralCount) {
45817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Bug 4212072 Update the affix strings according to symbols in order to keep the
45827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // affix strings up to date.  [Richard/GCL]
45837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        expandAffixes(pluralCount);
45847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
45857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Now that we have the actual prefix and suffix, fix up formatWidth
45867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (formatWidth > 0) {
45877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            formatWidth += positivePrefix.length() + positiveSuffix.length();
45887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
45897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
45907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
45917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
45927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
45937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
45947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
45957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
45967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char percent = PATTERN_PERCENT;
45977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char perMill = PATTERN_PER_MILLE;
45987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char digit = PATTERN_DIGIT; // '#'
45997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char separator = PATTERN_SEPARATOR;
46007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        String exponent = String.valueOf(PATTERN_EXPONENT);
46017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char plus = PATTERN_PLUS_SIGN;
46027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char padEscape = PATTERN_PAD_ESCAPE;
46037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL]
46047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (localized) {
46057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            zeroDigit = symbols.getZeroDigit();
46067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            sigDigit = symbols.getSignificantDigit();
46077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            groupingSeparator = symbols.getGroupingSeparator();
46087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            decimalSeparator = symbols.getDecimalSeparator();
46097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            percent = symbols.getPercent();
46107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            perMill = symbols.getPerMill();
46117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            digit = symbols.getDigit();
46127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            separator = symbols.getPatternSeparator();
46137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponent = symbols.getExponentSeparator();
46147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            plus = symbols.getPlusSign();
46157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            padEscape = symbols.getPadEscape();
46167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL]
46177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
46187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char nineDigit = (char) (zeroDigit + 9);
46197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
46207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean gotNegative = false;
46217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
46227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int pos = 0;
46237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Part 0 is the positive pattern. Part 1, if present, is the negative
46247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // pattern.
46257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
46267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,
46277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and
46287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // suffix, and consists of pattern characters. In the prefix and suffix,
46297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // percent, permille, and currency symbols are recognized and translated.
46307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
46317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
46327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // It's important that we don't change any fields of this object
46337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // prematurely. We set the following variables for the multiplier, grouping,
46347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // etc., and then only change the actual object fields if everything parses
46357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // correctly. This also lets us register the data from part 0 and ignore the
46367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // part 1, except for the prefix and suffix.
46377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StringBuilder prefix = new StringBuilder();
46387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StringBuilder suffix = new StringBuilder();
46397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int decimalPos = -1;
46407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int multpl = 1;
46417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
46427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte groupingCount = -1;
46437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte groupingCount2 = -1;
46447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int padPos = -1;
46457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            char padChar = 0;
46467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int incrementPos = -1;
46477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            long incrementVal = 0;
46487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte expDigits = -1;
46497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean expSignAlways = false;
46507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int currencySignCnt = 0;
46517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
46527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // The affix is either the prefix or the suffix.
46537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            StringBuilder affix = prefix;
46547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
46557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int start = pos;
46567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
46577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            PARTLOOP: for (; pos < pattern.length(); ++pos) {
46587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                char ch = pattern.charAt(pos);
46597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                switch (subpart) {
46607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case 0: // Pattern proper subpart (between prefix & suffix)
46617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Process the digits, decimal, and grouping characters. We record
46627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // five pieces of information. We expect the digits to occur in the
46637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // pattern ####00.00####, and we record the number of left digits,
46647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // zero (central) digits, and right digits. The position of the last
46657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // grouping character is recorded (should be somewhere within the
46667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // first two blocks of characters), as is the position of the decimal
46677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // point, if any (should be in the zero digits). If there is no
46687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // decimal point, then there should be no right digits.
46697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (ch == digit) {
46707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (zeroDigitCount > 0 || sigDigitCount > 0) {
46717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++digitRightCount;
46727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
46737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++digitLeftCount;
46747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
46757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (groupingCount >= 0 && decimalPos < 0) {
46767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++groupingCount;
46777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
46787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
46797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (digitRightCount > 0) {
46807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Unexpected '" + ch + '\'', pattern);
46817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
46827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (ch == sigDigit) {
46837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++sigDigitCount;
46847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
46857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++zeroDigitCount;
46867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (ch != zeroDigit) {
46877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                int p = digitLeftCount + zeroDigitCount + digitRightCount;
46887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (incrementPos >= 0) {
46897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    while (incrementPos < p) {
46907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        incrementVal *= 10;
46917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        ++incrementPos;
46927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
46937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
46947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    incrementPos = p;
46957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
46967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                incrementVal += ch - zeroDigit;
46977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
46987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
46997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (groupingCount >= 0 && decimalPos < 0) {
47007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++groupingCount;
47017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
47027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == groupingSeparator) {
47037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Bug 4212072 process the Localized pattern like
47047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator
47057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // == QUOTE) [Richard/GCL]
47067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (ch == QUOTE && (pos + 1) < pattern.length()) {
47077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            char after = pattern.charAt(pos + 1);
47087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
47097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // A quote outside quotes indicates either the opening
47107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // quote or two quotes, which is a quote literal. That is,
47117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // we have the first quote in 'do' or o''clock.
47127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (after == QUOTE) {
47137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    ++pos;
47147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    // Fall through to append(ch)
47157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
47167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (groupingCount < 0) {
47177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        subpart = 3; // quoted prefix subpart
47187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    } else {
47197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        // Transition to suffix subpart
47207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        subpart = 2; // suffix subpart
47217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        affix = suffix;
47227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        sub0Limit = pos--;
47237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
47247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    continue;
47257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
47267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
47277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
47287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
47297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (decimalPos >= 0) {
47307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Grouping separator after decimal", pattern);
47317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
47327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        groupingCount2 = groupingCount;
47337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        groupingCount = 0;
47347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == decimalSeparator) {
47357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (decimalPos >= 0) {
47367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Multiple decimal separators", pattern);
47377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
47387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Intentionally incorporate the digitRightCount, even though it
47397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // is illegal for this to be > 0 at this point. We check pattern
47407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // syntax below.
47417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
47427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
47437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
47447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (expDigits >= 0) {
47457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                patternError("Multiple exponential symbols", pattern);
47467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
47477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (groupingCount >= 0) {
47487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                patternError("Grouping separator in exponential", pattern);
47497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
47507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            pos += exponent.length();
47517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Check for positive prefix
47527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (pos < pattern.length() && pattern.charAt(pos) == plus) {
47537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                expSignAlways = true;
47547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                ++pos;
47557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
47567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Use lookahead to parse out the exponential part of the
47577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // pattern, then jump into suffix subpart.
47587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            expDigits = 0;
47597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {
47607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                ++expDigits;
47617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                ++pos;
47627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
47637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
47647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // 1. Require at least one mantissa pattern digit
47657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // 2. Disallow "#+ @" in mantissa
47667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // 3. Require at least one exponent pattern digit
47677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (((digitLeftCount + zeroDigitCount) < 1 &&
47687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 (sigDigitCount + digitRightCount) < 1)
47697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {
47707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                patternError("Malformed exponential", pattern);
47717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
47727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
47737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Transition to suffix subpart
47747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        subpart = 2; // suffix subpart
47757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        affix = suffix;
47767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        sub0Limit = pos--; // backup: for() will increment
47777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
47787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
47797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
47807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case 1: // Prefix subpart
47817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case 2: // Suffix subpart
47827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Process the prefix / suffix characters Process unquoted characters
47837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // seen in prefix or suffix subpart.
47847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
47857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Several syntax characters implicitly begins the next subpart if we
47867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // are in the prefix; otherwise they are illegal if unquoted.
47877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (ch == digit || ch == groupingSeparator || ch == decimalSeparator
47887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
47897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Any of these characters implicitly begins the
47907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // next subpart if we are in the prefix
47917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (subpart == 1) { // prefix subpart
47927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            subpart = 0; // pattern proper subpart
47937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            sub0Start = pos--; // Reprocess this character
47947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
47957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else if (ch == QUOTE) {
47967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // Bug 4212072 process the Localized pattern like
47977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH",
47987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // groupingSeparator == QUOTE) [Richard/GCL]
47997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
48007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // A quote outside quotes indicates either the opening quote
48017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // or two quotes, which is a quote literal. That is, we have
48027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            // the first quote in 'do' or o''clock.
48037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
48047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                ++pos;
48057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                affix.append(ch);
48067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
48077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                subpart += 2; // open quote
48087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
48097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
48107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        patternError("Unquoted special character '" + ch + '\'', pattern);
48127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == CURRENCY_SIGN) {
48137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Use lookahead to determine if the currency sign is
48147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // doubled or not.
48157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        boolean doubled = (pos + 1) < pattern.length() &&
48167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            pattern.charAt(pos + 1) == CURRENCY_SIGN;
48177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
48187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Bug 4212072 To meet the need of expandAffix(String,
48197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // StirngBuffer) [Richard/GCL]
48207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (doubled) {
48217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++pos; // Skip over the doubled character
48227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            affix.append(ch); // append two: one here, one below
48237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if ((pos + 1) < pattern.length() &&
48247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                pattern.charAt(pos + 1) == CURRENCY_SIGN) {
48257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                ++pos; // Skip over the tripled character
48267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                affix.append(ch); // append again
48277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
48287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
48297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                currencySignCnt = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
48307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
48317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
48327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            currencySignCnt = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
48337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Fall through to append(ch)
48357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == QUOTE) {
48367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // A quote outside quotes indicates either the opening quote or
48377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // two quotes, which is a quote literal. That is, we have the
48387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // first quote in 'do' or o''clock.
48397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
48407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++pos;
48417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            affix.append(ch); // append two: one here, one below
48427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
48437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            subpart += 2; // open quote
48447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Fall through to append(ch)
48467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == separator) {
48477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Don't allow separators in the prefix, and don't allow
48487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // separators in the second pattern (part == 1).
48497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (subpart == 1 || part == 1) {
48507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Unquoted special character '" + ch + '\'', pattern);
48517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        sub2Limit = pos++;
48537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break PARTLOOP; // Go to next part
48547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == percent || ch == perMill) {
48557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Next handle characters which are appended directly.
48567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (multpl != 1) {
48577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Too many percent/permille characters", pattern);
48587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        multpl = (ch == percent) ? 100 : 1000;
48607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Convert to non-localized pattern
48617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
48627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Fall through to append(ch)
48637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == minus) {
48647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Convert to non-localized pattern
48657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        ch = PATTERN_MINUS;
48667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Fall through to append(ch)
48677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (ch == padEscape) {
48687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (padPos >= 0) {
48697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Multiple pad specifiers", pattern);
48707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((pos + 1) == pattern.length()) {
48727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            patternError("Invalid pad specifier", pattern);
48737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        padPos = pos++; // Advance past pad char
48757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        padChar = pattern.charAt(pos);
48767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
48777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
48787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    affix.append(ch);
48797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
48807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case 3: // Prefix subpart, in quote
48817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case 4: // Suffix subpart, in quote
48827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // A quote within quotes indicates either the closing quote or two
48837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // quotes, which is a quote literal. That is, we have the second quote
48847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // in 'do' or 'don''t'.
48857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (ch == QUOTE) {
48867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
48877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            ++pos;
48887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            affix.append(ch);
48897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
48907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            subpart -= 2; // close quote
48917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
48927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // Fall through to append(ch)
48937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
48947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // NOTE: In ICU 2.2 there was code here to parse quoted percent and
48957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // permille characters _within quotes_ and give them special
48967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // meaning. This is incorrect, since quoted characters are literals
48977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // without special meaning.
48987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    affix.append(ch);
48997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
49007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
49017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (subpart == 3 || subpart == 4) {
49047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                patternError("Unterminated quote", pattern);
49057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (sub0Limit == 0) {
49087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                sub0Limit = pattern.length();
49097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (sub2Limit == 0) {
49127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                sub2Limit = pattern.length();
49137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Handle patterns with no '0' pattern character. These patterns are legal,
49167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // but must be recodified to make sense. "##.###" -> "#0.###". ".###" ->
49177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // ".0##".
49187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            //
49197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // We allow patterns of the form "####" to produce a zeroDigitCount of zero
49207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // (got that?); although this seems like it might make it possible for
49217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // format() to produce empty strings, format() checks for this condition and
49227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // outputs a zero digit in this situation. Having a zeroDigitCount of zero
49237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // yields a minimum integer digits of zero, which allows proper round-trip
49247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // patterns. We don't want "#" to become "#0" when toPattern() is called (even
49257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // though that's what it really is, semantically).
49267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (zeroDigitCount == 0 && sigDigitCount == 0 &&
49277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digitLeftCount > 0 && decimalPos >= 0) {
49287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Handle "###.###" and "###." and ".###"
49297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int n = decimalPos;
49307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (n == 0)
49317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ++n; // Handle ".###"
49327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digitRightCount = digitLeftCount - n;
49337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                digitLeftCount = n - 1;
49347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                zeroDigitCount = 1;
49357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Do syntax checking on the digits, decimal points, and quotes.
49387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)
49397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || (decimalPos >= 0
49407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    && (sigDigitCount > 0
49417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        || decimalPos < digitLeftCount
49427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        || decimalPos > (digitLeftCount + zeroDigitCount)))
49437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || groupingCount == 0
49447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || groupingCount2 == 0
49457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || (sigDigitCount > 0 && zeroDigitCount > 0)
49467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                || subpart > 2) { // subpart > 2 == unmatched quote
49477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                patternError("Malformed pattern", pattern);
49487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Make sure pad is at legal position before or after affix.
49517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (padPos >= 0) {
49527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (padPos == start) {
49537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    padPos = PAD_BEFORE_PREFIX;
49547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (padPos + 2 == sub0Start) {
49557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    padPos = PAD_AFTER_PREFIX;
49567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (padPos == sub0Limit) {
49577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    padPos = PAD_BEFORE_SUFFIX;
49587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (padPos + 2 == sub2Limit) {
49597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    padPos = PAD_AFTER_SUFFIX;
49607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
49617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    patternError("Illegal pad position", pattern);
49627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
49637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
49647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (part == 0) {
49667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Set negative affixes temporarily to match the positive
49677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // affixes. Fix this up later after processing both parts.
49687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
49707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // [Richard/GCL]
49717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                posPrefixPattern = negPrefixPattern = prefix.toString();
49727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                posSuffixPattern = negSuffixPattern = suffix.toString();
49737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                useExponentialNotation = (expDigits >= 0);
49757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (useExponentialNotation) {
49767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    minExponentDigits = expDigits;
49777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    exponentSignAlwaysShown = expSignAlways;
49787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
49797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
49807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // The effectiveDecimalPos is the position the decimal is at or would be
49817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // at if there is no decimal. Note that if decimalPos<0, then
49827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // digitTotalCount == digitLeftCount + zeroDigitCount.
49837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
49847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                boolean useSigDig = (sigDigitCount > 0);
49857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setSignificantDigitsUsed(useSigDig);
49867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (useSigDig) {
49877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    setMinimumSignificantDigits(sigDigitCount);
49887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    setMaximumSignificantDigits(sigDigitCount + digitRightCount);
49897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
49907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int minInt = effectiveDecimalPos - digitLeftCount;
49917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    setMinimumIntegerDigits(minInt);
49927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
49937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // Upper limit on integer and fraction digits for a Java double
49947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // [Richard/GCL]
49957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt :
49967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            DOUBLE_INTEGER_DIGITS);
49977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    _setMaximumFractionDigits(decimalPos >= 0 ?
49987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                             (digitTotalCount - decimalPos) : 0);
49997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    setMinimumFractionDigits(decimalPos >= 0 ?
50007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                             (digitLeftCount + zeroDigitCount - decimalPos) : 0);
50017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
50027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setGroupingUsed(groupingCount > 0);
50037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
50047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
50057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    ? groupingCount2 : 0;
50067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                this.multiplier = multpl;
50077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
50087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (padPos >= 0) {
50097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    padPosition = padPos;
50107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    formatWidth = sub0Limit - sub0Start; // to be fixed up below
50117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    pad = padChar;
50127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
50137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    formatWidth = 0;
50147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
50157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (incrementVal != 0) {
50167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // BigDecimal scale cannot be negative (even though this makes perfect
50177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // sense), so we need to handle this.
50187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int scale = incrementPos - effectiveDecimalPos;
50197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
50207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (scale < 0) {
50217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);
50227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
50237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    roundingMode = BigDecimal.ROUND_HALF_EVEN;
50247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
50257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    setRoundingIncrement((BigDecimal) null);
50267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
50277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Update currency sign count for the new pattern
50297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                currencySignCount = currencySignCnt;
50307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
50317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
50327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // [Richard/GCL]
50337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                negPrefixPattern = prefix.toString();
50347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                negSuffixPattern = suffix.toString();
50357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotNegative = true;
50367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
50377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
50387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Bug 4140009 Process the empty pattern [Richard/GCL]
50417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (pattern.length() == 0) {
50427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            posPrefixPattern = posSuffixPattern = "";
50437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setMinimumIntegerDigits(0);
50447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
50457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setMinimumFractionDigits(0);
50467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
50477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
50487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If there was no negative pattern, or if the negative pattern is identical to
50507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // the positive pattern, then prepend the minus sign to the positive pattern to
50517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // form the negative pattern.
50527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
50547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!gotNegative ||
50567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            (negPrefixPattern.equals(posPrefixPattern)
50577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             && negSuffixPattern.equals(posSuffixPattern))) {
50587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negSuffixPattern = posSuffixPattern;
50597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
50607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
50617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setLocale(null, null);
50627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // save the pattern
50637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        formatPattern = pattern;
50647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // special handlings for currency instance
50667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
50677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // reset rounding increment and max/min fractional digits
50687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // by the currency
50697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Currency theCurrency = getCurrency();
50707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (theCurrency != null) {
50717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
50727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int d = theCurrency.getDefaultFractionDigits(currencyUsage);
50737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setMinimumFractionDigits(d);
50747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                _setMaximumFractionDigits(d);
50757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
50767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // initialize currencyPluralInfo if needed
50787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT
50797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                && currencyPluralInfo == null) {
50807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale());
50817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
50827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
50837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        resetActualRounding();
50847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
50857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void patternError(String msg, String pattern) {
50887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
50897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
50907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits
50937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // for a Java double [Richard/GCL]
50947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
50957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
50967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the maximum number of digits allowed in the integer portion of a number. This
50977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * override limits the integer digit count to 309.
50987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
50997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#setMaximumIntegerDigits
51007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
51017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
51037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMaximumIntegerDigits(int newValue) {
51047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
51057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the minimum number of digits allowed in the integer portion of a number. This
51097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * override limits the integer digit count to 309.
51107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
51117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#setMinimumIntegerDigits
51127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
51137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
51157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMinimumIntegerDigits(int newValue) {
51167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
51177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the minimum number of significant digits that will be
51217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
51227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * returns true.
51237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
51247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the fewest significant digits that will be shown
51257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
51267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getMinimumSignificantDigits() {
51287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return minSignificantDigits;
51297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns the maximum number of significant digits that will be
51337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
51347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * returns true.
51357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
51367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return the most significant digits that will be shown
51377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
51387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getMaximumSignificantDigits() {
51407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return maxSignificantDigits;
51417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the minimum number of significant digits that will be displayed. If
51457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>min</code> is less than one then it is set to one. If the maximum significant
51467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * digits count is less than <code>min</code>, then it is set to <code>min</code>.
51477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This function also enables the use of significant digits by this formatter -
51487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@link #areSignificantDigitsUsed()} will return true.
51497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
51507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param min the fewest significant digits to be shown
51517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
51527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMinimumSignificantDigits(int min) {
51547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (min < 1) {
51557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            min = 1;
51567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
51577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // pin max sig dig to >= min
51587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int max = Math.max(maxSignificantDigits, min);
51597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        minSignificantDigits = min;
51607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxSignificantDigits = max;
51617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setSignificantDigitsUsed(true);
51627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets the maximum number of significant digits that will be displayed. If
51667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>max</code> is less than one then it is set to one. If the minimum significant
51677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * digits count is greater than <code>max</code>, then it is set to <code>max</code>.
51687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This function also enables the use of significant digits by this formatter -
51697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@link #areSignificantDigitsUsed()} will return true.
51707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
51717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param max the most significant digits to be shown
51727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
51737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMaximumSignificantDigits(int max) {
51757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (max < 1) {
51767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            max = 1;
51777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
51787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // pin min sig dig to 1..max
51797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int min = Math.min(minSignificantDigits, max);
51807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        minSignificantDigits = min;
51817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxSignificantDigits = max;
51827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setSignificantDigitsUsed(true);
51837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Returns true if significant digits are in use or false if integer and
51877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * fraction digit counts are in use.
51887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
51897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if significant digits are in use
51907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
51917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
51927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean areSignificantDigitsUsed() {
51937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return useSignificantDigits;
51947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
51957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
51967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
51977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Sets whether significant digits are in use, or integer and fraction digit
51987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * counts are in use.
51997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
52007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param useSignificantDigits true to use significant digits, or false to use integer
52017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * and fraction digit counts
52027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
52037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
52047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setSignificantDigitsUsed(boolean useSignificantDigits) {
52057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.useSignificantDigits = useSignificantDigits;
52067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
52077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
52097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
52107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * effect immediately, if this format is a currency format. If this format is not a
52117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency format, then the currency object is used if and when this object becomes a
52127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency format through the application of a new pattern.
52137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
52147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param theCurrency new currency object to use. Must not be null.
52157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.2
52167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
52177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
52187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setCurrency(Currency theCurrency) {
52197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // If we are a currency format, then modify our affixes to
52207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // encode the currency symbol for the given currency in our
52217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // locale, and adjust the decimal digits and rounding for the
52227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // given currency.
52237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super.setCurrency(theCurrency);
52257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (theCurrency != null) {
52267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean[] isChoiceFormat = new boolean[1];
52277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String s = theCurrency.getName(symbols.getULocale(),
52287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                           Currency.SYMBOL_NAME, isChoiceFormat);
52297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            symbols.setCurrency(theCurrency);
52307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            symbols.setCurrencySymbol(s);
52317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
52327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) {
52347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (theCurrency != null) {
52357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
52367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int d = theCurrency.getDefaultFractionDigits(currencyUsage);
52377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setMinimumFractionDigits(d);
52387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setMaximumFractionDigits(d);
52397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
52407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (currencySignCount != CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
52417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // This is not necessary for plural format type
52427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // because affixes will be resolved in subformat
52437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                expandAffixes(null);
52447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
52457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
52467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
52477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
52497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the <tt>Currency Usage</tt> object used to display currency.
52507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This takes effect immediately, if this format is a
52517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * currency format.
52527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param newUsage new currency context object to use.
52537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @draft ICU 54
52547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @provisional This API might change or be removed in a future release.
52557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
52567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setCurrencyUsage(CurrencyUsage newUsage) {
52577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (newUsage == null) {
52587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new NullPointerException("return value is null at method AAA");
52597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
52607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        currencyUsage = newUsage;
52617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Currency theCurrency = this.getCurrency();
52627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // We set rounding/digit based on currency context
52647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (theCurrency != null) {
52657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage));
52667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int d = theCurrency.getDefaultFractionDigits(currencyUsage);
52677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setMinimumFractionDigits(d);
52687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            _setMaximumFractionDigits(d);
52697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
52707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
52717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
52737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the <tt>Currency Usage</tt> object used to display currency
52747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @draft ICU 54
52757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @provisional This API might change or be removed in a future release.
52767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
52777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CurrencyUsage getCurrencyUsage() {
52787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return currencyUsage;
52797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
52807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
52827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the currency in effect for this formatter. Subclasses should override this
52837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * method as needed. Unlike getCurrency(), this method should never return null.
52847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
52857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @internal
52867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @deprecated This API is ICU internal only.
52877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
52887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Deprecated
52897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
52907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected Currency getEffectiveCurrency() {
52917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Currency c = getCurrency();
52927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (c == null) {
52937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
52947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
52957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return c;
52967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
52977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
52987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
52997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the maximum number of digits allowed in the fraction portion of a number. This
53007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * override limits the fraction digit count to 340.
53017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
53027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#setMaximumFractionDigits
53037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
53047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
53057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
53067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMaximumFractionDigits(int newValue) {
53077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        _setMaximumFractionDigits(newValue);
53087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        resetActualRounding();
53097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
53127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Internal method for DecimalFormat, setting maximum fractional digits
53137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * without triggering actual rounding recalculated.
53147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
53157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void _setMaximumFractionDigits(int newValue) {
53167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
53177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
53207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets the minimum number of digits allowed in the fraction portion of a number. This
53217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * override limits the fraction digit count to 340.
53227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
53237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#setMinimumFractionDigits
53247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
53257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
53267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @Override
53277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setMinimumFractionDigits(int newValue) {
53287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
53297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
53327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
53337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * default value is false.
53347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
53357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param value true if {@link #parse(String, ParsePosition)}
53367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * returns BigDecimal.
53377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.6
53387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
53397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setParseBigDecimal(boolean value) {
53407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        parseBigDecimal = value;
53417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
53447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
53457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
53467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
53477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.6
53487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
53497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean isParseBigDecimal() {
53507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return parseBigDecimal;
53517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
53547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Set the maximum number of exponent digits when parsing a number.
53557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * If the limit is set too high, an OutOfMemoryException may be triggered.
53567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * The default value is 1000.
53577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param newValue the new limit
53587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @stable ICU 51
53597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
53607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setParseMaxDigits(int newValue) {
53617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (newValue > 0) {
53627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            PARSE_MAX_EXPONENT = newValue;
53637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
53647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
53677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Get the current maximum number of exponent digits when parsing a
53687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * number.
53697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @return the maximum number of exponent digits for parsing
53707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @stable ICU 51
53717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
53727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int getParseMaxDigits() {
53737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return PARSE_MAX_EXPONENT;
53747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void writeObject(ObjectOutputStream stream) throws IOException {
53777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Ticket#6449 Format.Field instances are not serializable. When
53787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // formatToCharacterIterator is called, attributes (ArrayList) stores
53797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is
53807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // not serializable, we need to clear the contents of the list when writeObject is
53817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // called. We could remove the field or make it transient, but it will break
53827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // serialization compatibility.
53837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        attributes.clear();
53847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        stream.defaultWriteObject();
53867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
53877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
53897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * First, read the default serializable fields from the stream. Then if
53907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was
53917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since
53927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the
53937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * maximum allowed value so that default serialization will work properly if this
53947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * object is streamed out again.
53957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
53967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
53977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        stream.defaultReadObject();
53987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
53997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Bug 4185761 validate fields [Richard/GCL]
54007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // We only need to check the maximum counts because NumberFormat .readObject has
54027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // already ensured that the maximum is greater than the minimum count.
54037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Commented for compatibility with previous version, and reserved for further use
54057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
54067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new
54077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // InvalidObjectException("Digit count out of range"); }
54087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and
54117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // maximumFractionDigits to DOUBLE_FRACTION_DIGITS
54127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
54147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
54157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
54167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
54177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
54187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
54197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (serialVersionOnStream < 2) {
54207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            exponentSignAlwaysShown = false;
54217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInternalRoundingIncrement(null);
54227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            roundingMode = BigDecimal.ROUND_HALF_EVEN;
54237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            formatWidth = 0;
54247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            pad = ' ';
54257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            padPosition = PAD_BEFORE_PREFIX;
54267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (serialVersionOnStream < 1) {
54277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // Didn't have exponential fields
54287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                useExponentialNotation = false;
54297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
54307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
54317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (serialVersionOnStream < 3) {
54327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // Versions prior to 3 do not store a currency object.  Create one to match
54337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // the DecimalFormatSymbols object.
54347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setCurrencyForSymbols();
54357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
54367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (serialVersionOnStream < 4) {
54377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            currencyUsage = CurrencyUsage.STANDARD;
54387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
54397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        serialVersionOnStream = currentSerialVersion;
54407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        digitList = new DigitList();
54417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingIncrement != null) {
54437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
54447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
54457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        resetActualRounding();
54467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
54477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void setInternalRoundingIncrement(BigDecimal value) {
54497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        roundingIncrementICU = value;
54507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        roundingIncrement = value == null ? null : value.toBigDecimal();
54517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
54527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ----------------------------------------------------------------------
54547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // INSTANCE VARIABLES
54557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ----------------------------------------------------------------------
54567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient DigitList digitList = new DigitList();
54587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
54607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The symbol used as a prefix when formatting positive numbers, e.g. "+".
54617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
54627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
54637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPositivePrefix
54647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
54657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String positivePrefix = "";
54667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
54687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The symbol used as a suffix when formatting positive numbers. This is often an
54697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * empty string.
54707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
54717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
54727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPositiveSuffix
54737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
54747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String positiveSuffix = "";
54757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
54777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The symbol used as a prefix when formatting negative numbers, e.g. "-".
54787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
54797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
54807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getNegativePrefix
54817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
54827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String negativePrefix = "-";
54837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
54857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The symbol used as a suffix when formatting negative numbers. This is often an
54867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * empty string.
54877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
54887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
54897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getNegativeSuffix
54907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
54917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String negativeSuffix = "";
54927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
54937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
54947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The prefix pattern for non-negative numbers. This variable corresponds to
54957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>positivePrefix</code>.
54967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
54977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
54987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>positivePrefix</code> to update the latter to reflect changes in
54997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>symbols</code>. If this variable is <code>null</code> then
55007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>positivePrefix</code> is taken as a literal value that does not change when
55017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>symbols</code> changes.  This variable is always <code>null</code> for
55027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>DecimalFormat</code> objects older than stream version 2 restored from
55037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * stream.
55047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // [Richard/GCL]
55087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String posPrefixPattern;
55097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The suffix pattern for non-negative numbers. This variable corresponds to
55127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>positiveSuffix</code>. This variable is analogous to
55137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>posPrefixPattern</code>; see that variable for further documentation.
55147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // [Richard/GCL]
55187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String posSuffixPattern;
55197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The prefix pattern for negative numbers. This variable corresponds to
55227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>negativePrefix</code>. This variable is analogous to
55237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>posPrefixPattern</code>; see that variable for further documentation.
55247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // [Richard/GCL]
55287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String negPrefixPattern;
55297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The suffix pattern for negative numbers. This variable corresponds to
55327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>negativeSuffix</code>. This variable is analogous to
55337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>posPrefixPattern</code>; see that variable for further documentation.
55347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // [Richard/GCL]
55387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String negSuffixPattern;
55397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Formatter for ChoiceFormat-based currency names. If this field is not null, then
55427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * delegate to it to format currency symbols.
55437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since ICU 2.6
55457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private ChoiceFormat currencyChoice;
55477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The multiplier for use in percent, permill, etc.
55507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getMultiplier
55537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int multiplier = 1;
55557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The number of digits between grouping separators in the integer portion of a
55587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true.
55597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getGroupingSize
55627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see NumberFormat#isGroupingUsed
55637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private byte groupingSize = 3; // invariant, > 0 if useThousands
55657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The secondary grouping size. This is only used for Hindi numerals, which use a
55687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this
55697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * value is less than 1, then secondary grouping is equal to the primary grouping.
55707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private byte groupingSize2 = 0;
55737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * If true, forces the decimal separator to always appear in a formatted number, even
55767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * if the fractional part of the number is zero.
55777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isDecimalSeparatorAlwaysShown
55807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean decimalSeparatorAlwaysShown = false;
55827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The <code>DecimalFormatSymbols</code> object used by this format. It contains the
55857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * symbols used to format numbers, e.g. the grouping separator, decimal separator, and
55867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * so on.
55877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setDecimalFormatSymbols
55907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see DecimalFormatSymbols
55917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
55927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
55937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
55947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
55957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * True to use significant digits rather than integer and fraction digit counts.
55967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
55977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
55987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since ICU 3.0
55997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean useSignificantDigits = false;
56017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The minimum number of significant digits to show. Must be >= 1 and <=
56047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * maxSignificantDigits. Ignored unless useSignificantDigits == true.
56057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since ICU 3.0
56087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int minSignificantDigits = 1;
56107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The maximum number of significant digits to show. Must be >=
56137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * minSignficantDigits. Ignored unless useSignificantDigits == true.
56147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since ICU 3.0
56177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int maxSignificantDigits = 6;
56197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * True to force the use of exponential (i.e. scientific) notation
56227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * when formatting numbers.
56237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *<p> Note that the JDK 1.2 public API provides no way to set this
56257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * field, even though it is supported by the implementation and
56267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the stream format. The intent is that this will be added to the
56277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * API in the future.
56287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean useExponentialNotation; // Newly persistent in JDK 1.2
56327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The minimum number of digits used to display the exponent when a number is
56357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * formatted in exponential notation.  This field is ignored if
56367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>useExponentialNotation</code> is not true.
56377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Note that the JDK 1.2 public API provides no way to set this field, even though
56397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * it is supported by the implementation and the stream format. The intent is that
56407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * this will be added to the API in the future.
56417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private byte minExponentDigits; // Newly persistent in JDK 1.2
56457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * If true, the exponent is always prefixed with either the plus sign or the minus
56487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has
56497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * no effect unless <code>useExponentialNotation</code> is true.
56507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
56537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean exponentSignAlwaysShown = false;
56557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The value to which numbers are rounded during formatting. For example, if the
56587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
56597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
56607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * positive value if rounding is in effect. Default value <code>null</code>.
56617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
56647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note: this is kept in sync with roundingIncrementICU.
56667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
56677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private java.math.BigDecimal roundingIncrement = null;
56687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The value to which numbers are rounded during formatting. For example, if the
56717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
56727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
56737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * positive value if rounding is in effect. Default value <code>null</code>. WARNING:
56747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the roundingIncrement value is the one serialized.
56757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
56787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient BigDecimal roundingIncrementICU = null;
56807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The rounding mode. This value controls any rounding operations which occur when
56837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * applying a rounding increment or when reducing the number of fraction digits to
56847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * satisfy a maximum fraction digits limit. The value may assume any of the
56857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigDecimal</code> rounding mode values. Default value
56867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>BigDecimal.ROUND_HALF_EVEN</code>.
56877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
56887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
56897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
56907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
56917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
56927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
56937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
56947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Operations on <code>BigDecimal</code> numbers are controlled by a {@link
56957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * MathContext} object, which provides the context (precision and other information)
56967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * for the operation. The default <code>MathContext</code> settings are
56977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>;
56987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * these settings perform fixed point arithmetic with unlimited precision, as defined
56997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * for the original BigDecimal class in Java 1.1 and Java 1.2
57007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // context for plain unlimited math
57027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private MathContext mathContext = new MathContext(0, MathContext.PLAIN);
57037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The padded format width, or zero if there is no padding. Must be >= 0. Default
57067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * value zero.
57077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
57097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
57107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int formatWidth = 0;
57127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The character used to pad the result of format to <code>formatWidth</code>, if
57157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * padding is in effect. Default value ' '.
57167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
57187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
57197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private char pad = ' ';
57217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The position in the string at which the <code>pad</code> character will be
57247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * inserted, if padding is in effect.  Must have a value from
57257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value
57267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>PAD_BEFORE_PREFIX</code>.
57277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
57297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since AlphaWorks NumberFormat
57307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int padPosition = PAD_BEFORE_PREFIX;
57327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than
57357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Long, Double or BigDecimal except special values. This property is introduced for
57367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * J2SE 5 compatibility support.
57377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
57397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since ICU 3.6
57407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setParseBigDecimal(boolean)
57417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #isParseBigDecimal()
57427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean parseBigDecimal = false;
57447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The currency usage for the NumberFormat(standard or cash usage).
57477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * It is used as STANDARD by default
57487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @since ICU 54
57497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private CurrencyUsage currencyUsage = CurrencyUsage.STANDARD;
57517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ----------------------------------------------------------------------
57537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int currentSerialVersion = 4;
57557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The internal serial version which says which version was written Possible values
57587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * are:
57597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ul>
57617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <li><b>0</b> (default): versions before JDK 1.2
57637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
57657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
57667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad,
57687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * padPosition, exponentSignAlwaysShown, roundingIncrement.
57697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <li><b>3</b>: ICU 2.2. Adds currency object.
57717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <li><b>4</b>: ICU 54. Adds currency usage(standard vs cash)
57737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * </ul>
57757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @serial
57777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int serialVersionOnStream = currentSerialVersion;
57797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ----------------------------------------------------------------------
57817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // CONSTANTS
57827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // ----------------------------------------------------------------------
57837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
57867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * specify pad characters inserted before the prefix.
57877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
57887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
57897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
57907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_PREFIX
57917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_SUFFIX
57927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_SUFFIX
57937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
57947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
57957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static final int PAD_BEFORE_PREFIX = 0;
57967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
57977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
57987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
57997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * specify pad characters inserted after the prefix.
58007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
58017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
58027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
58037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_PREFIX
58047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_SUFFIX
58057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_SUFFIX
58067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
58077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static final int PAD_AFTER_PREFIX = 1;
58097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
58117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
58127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * specify pad characters inserted before the suffix.
58137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
58147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
58157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
58167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_PREFIX
58177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_PREFIX
58187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_SUFFIX
58197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
58207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static final int PAD_BEFORE_SUFFIX = 2;
58227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
58247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
58257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * specify pad characters inserted after the suffix.
58267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
58277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #setPadPosition
58287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #getPadPosition
58297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_PREFIX
58307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_AFTER_PREFIX
58317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @see #PAD_BEFORE_SUFFIX
58327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 2.0
58337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public static final int PAD_AFTER_SUFFIX = 3;
58357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Constants for characters used in programmatic (unlocalized) patterns.
58377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_ZERO_DIGIT = '0';
58387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_ONE_DIGIT = '1';
58397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_TWO_DIGIT = '2';
58407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_THREE_DIGIT = '3';
58417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_FOUR_DIGIT = '4';
58427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_FIVE_DIGIT = '5';
58437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_SIX_DIGIT = '6';
58447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_SEVEN_DIGIT = '7';
58457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_EIGHT_DIGIT = '8';
58467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_NINE_DIGIT = '9';
58477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_GROUPING_SEPARATOR = ',';
58487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_DECIMAL_SEPARATOR = '.';
58497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_DIGIT = '#';
58507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_SIGNIFICANT_DIGIT = '@';
58517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_EXPONENT = 'E';
58527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_PLUS_SIGN = '+';
58537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Affix
58557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char PATTERN_PER_MILLE = '\u2030';
58567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char PATTERN_PERCENT = '%';
58577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final char PATTERN_PAD_ESCAPE = '*';
58587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
58597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
58607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char PATTERN_MINUS = '-';
58627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Other
58647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char PATTERN_SEPARATOR = ';';
58657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Pad escape is package private to allow access by DecimalFormatSymbols.
58677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Also plus sign. Also exponent.
58687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
58707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in
58717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * patterns and substitued with either the currency symbol, or if it is doubled, with
58727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then
58737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the decimal separator is replaced with the monetary decimal separator.
58747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
58757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The CURRENCY_SIGN is not localized.
58767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char CURRENCY_SIGN = '\u00A4';
58787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char QUOTE = '\'';
58807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
58827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Upper limit on integer and fraction digits for a Java double [Richard/GCL]
58837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int DOUBLE_INTEGER_DIGITS = 309;
58857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int DOUBLE_FRACTION_DIGITS = 340;
58867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
58887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * When someone turns on scientific mode, we assume that more than this number of
58897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * digits is due to flipping from some other mode that didn't restrict the maximum,
58907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * and so we force 1 integer digit. We don't bother to track and see if someone is
58917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * using exponential notation with more than this number, it wouldn't make sense
58927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * anyway, and this is just to make sure that someone turning on scientific mode with
58937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * default settings doesn't end up with lots of zeroes.
58947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
58957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
58967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
58977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Proclaim JDK 1.1 serial compatibility.
58987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final long serialVersionUID = 864413376551465018L;
58997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>();
59017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // The following are used in currency format
59037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // -- triple currency sign char array
59057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
59067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // -- triple currency sign string
59077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private static final String tripleCurrencyStr = new String(tripleCurrencySign);
59087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //
59097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // -- default currency plural pattern char array
59107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private static final char[] defaultCurrencyPluralPatternChar =
59117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //   {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
59127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // -- default currency plural pattern string
59137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private static final String defaultCurrencyPluralPattern =
59147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //     new String(defaultCurrencyPluralPatternChar);
59157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // pattern used in this formatter
59177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private String formatPattern = "";
59187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // style is only valid when decimal formatter is constructed by
59197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // DecimalFormat(pattern, decimalFormatSymbol, style)
59207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int style = NumberFormat.NUMBERSTYLE;
59217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
59227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Represents whether this is a currency format, and which currency format style. 0:
59237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * not currency format type; 1: currency style -- symbol name, such as "$" for US
59247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style
59257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for
59267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * "3.00 US Dollars".
59277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
59287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int currencySignCount = CURRENCY_SIGN_COUNT_ZERO;
59297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
59317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * For parsing purposes, we need to remember all prefix patterns and suffix patterns
59327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * of every currency format pattern, including the pattern of the default currency
59337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * style, ISO currency style, and plural currency style. The patterns are set through
59347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * applyPattern. The following are used to represent the affix patterns in currency
59357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * plural formats.
59367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
59377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final class AffixForCurrency {
59387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // negative prefix pattern
59397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String negPrefixPatternForCurrency = null;
59407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // negative suffix pattern
59417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String negSuffixPatternForCurrency = null;
59427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // positive prefix pattern
59437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String posPrefixPatternForCurrency = null;
59447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // positive suffix pattern
59457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private String posSuffixPatternForCurrency = null;
59467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private final int patternType;
59477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix,
59497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                String posSuffix, int type) {
59507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negPrefixPatternForCurrency = negPrefix;
59517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            negSuffixPatternForCurrency = negSuffix;
59527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            posPrefixPatternForCurrency = posPrefix;
59537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            posSuffixPatternForCurrency = posSuffix;
59547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            patternType = type;
59557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
59567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getNegPrefix() {
59587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return negPrefixPatternForCurrency;
59597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
59607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getNegSuffix() {
59627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return negSuffixPatternForCurrency;
59637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
59647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getPosPrefix() {
59667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return posPrefixPatternForCurrency;
59677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
59687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String getPosSuffix() {
59707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return posSuffixPatternForCurrency;
59717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
59727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public int getPatternType() {
59747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return patternType;
59757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
59767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
59777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Affix pattern set for currency.  It is a set of AffixForCurrency, each element of
59797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // the set saves the negative prefix, negative suffix, positive prefix, and positive
59807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // suffix of a pattern.
59817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient Set<AffixForCurrency> affixPatternsForCurrency = null;
59827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // For currency parsing. Since currency parsing needs to parse against all currency
59847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // patterns, before the parsing, we need to set up the affix patterns for all currencies.
59857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient boolean isReadyForParsing = false;
59867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Information needed for DecimalFormat to format/parse currency plural.
59887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private CurrencyPluralInfo currencyPluralInfo = null;
59897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
59907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
59917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Unit is an immutable class for the textual representation of a unit, in
59927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * particular its prefix and suffix.
59937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
59947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @author rocketman
59957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
59967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
59977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static class Unit {
59987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private final String prefix;
59997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private final String suffix;
60007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public Unit(String prefix, String suffix) {
60027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.prefix = prefix;
60037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            this.suffix = suffix;
60047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
60057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public void writeSuffix(StringBuffer toAppendTo) {
60077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            toAppendTo.append(suffix);
60087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
60097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public void writePrefix(StringBuffer toAppendTo) {
60117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            toAppendTo.append(prefix);
60127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
60137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
60157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public boolean equals(Object obj) {
60167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (this == obj) {
60177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return true;
60187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
60197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!(obj instanceof Unit)) {
60207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return false;
60217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
60227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Unit other = (Unit) obj;
60237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return prefix.equals(other.prefix) && suffix.equals(other.suffix);
60247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
60257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @Override
60267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public String toString() {
60277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return prefix + "/" + suffix;
60287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
60297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
60307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final Unit NULL_UNIT = new Unit("", "");
60327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Note about rounding implementation
60347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //
60357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // The original design intended to skip rounding operation when roundingIncrement is not
60367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // set. However, rounding may need to occur when fractional digits exceed the width of
60377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // fractional part of pattern.
60387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //
60397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // DigitList class has built-in rounding mechanism, using ROUND_HALF_EVEN. This implementation
60407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // forces non-null roundingIncrement if the setting is other than ROUND_HALF_EVEN, otherwise,
60417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // when rounding occurs in DigitList by pattern's fractional digits' width, the result
60427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // does not match the rounding mode.
60437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //
60447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Ideally, all rounding operation should be done in one place like ICU4C trunk does
60457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // (ICU4C rounding implementation was rewritten recently). This is intrim implemetation
60467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // to fix various issues. In the future, we should entire implementation of rounding
60477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // in this class, like ICU4C did.
60487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //
60497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // Once we fully implement rounding logic in DigitList, then following fields and methods
60507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // should be gone.
60517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient BigDecimal actualRoundingIncrementICU = null;
60537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient java.math.BigDecimal actualRoundingIncrement = null;
60547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
60567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The actual rounding increment as a double.
60577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
60587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient double roundingDouble = 0.0;
60597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
60617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * If the roundingDouble is the reciprocal of an integer (the most common case!), this
60627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * is set to be that integer.  Otherwise it is 0.0.
60637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
60647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private transient double roundingDoubleReciprocal = 0.0;
60657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
60677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Set roundingDouble, roundingDoubleReciprocal and actualRoundingIncrement
60687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * based on rounding mode and width of fractional digits. Whenever setting affecting
60697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * rounding mode, rounding increment and maximum width of fractional digits, then
60707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * this method must be called.
60717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
60727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * roundingIncrementICU is the field storing the custom rounding increment value,
60737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * while actual rounding increment could be larger.
60747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
60757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void resetActualRounding() {
60767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingIncrementICU != null) {
60777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            BigDecimal byWidth = getMaximumFractionDigits() > 0 ?
60787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    BigDecimal.ONE.movePointLeft(getMaximumFractionDigits()) : BigDecimal.ONE;
60797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (roundingIncrementICU.compareTo(byWidth) >= 0) {
60807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                actualRoundingIncrementICU = roundingIncrementICU;
60817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
60827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                actualRoundingIncrementICU = byWidth.equals(BigDecimal.ONE) ? null : byWidth;
60837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
60847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
60857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (roundingMode == BigDecimal.ROUND_HALF_EVEN || isScientificNotation()) {
60867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // This rounding fix is irrelevant if mode is ROUND_HALF_EVEN as DigitList
60877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // does ROUND_HALF_EVEN for us.  This rounding fix won't work at all for
60887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // scientific notation.
60897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                actualRoundingIncrementICU = null;
60907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
60917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (getMaximumFractionDigits() > 0) {
60927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    actualRoundingIncrementICU = BigDecimal.ONE.movePointLeft(getMaximumFractionDigits());
60937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }  else {
60947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    actualRoundingIncrementICU = BigDecimal.ONE;
60957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
60967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
60977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
60987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
60997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (actualRoundingIncrementICU == null) {
61007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setRoundingDouble(0.0d);
61017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            actualRoundingIncrement = null;
61027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
61037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setRoundingDouble(actualRoundingIncrementICU.doubleValue());
61047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            actualRoundingIncrement = actualRoundingIncrementICU.toBigDecimal();
61057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
61067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
61077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
61087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static final double roundingIncrementEpsilon = 0.000000001;
61097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
61107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void setRoundingDouble(double newValue) {
61117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        roundingDouble = newValue;
61127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (roundingDouble > 0.0d) {
61137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            double rawRoundedReciprocal = 1.0d / roundingDouble;
61147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
61157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
61167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                roundingDoubleReciprocal = 0.0d;
61177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
61187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
61197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            roundingDoubleReciprocal = 0.0d;
61207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
61217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
61227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
61237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
61247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// eof
6125